package dev.dworks.libs.actionbarplus.widget; import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.TypedArray; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import com.nineoldandroids.animation.Animator; import com.nineoldandroids.animation.AnimatorListenerAdapter; import com.nineoldandroids.animation.AnimatorSet; import com.nineoldandroids.animation.ObjectAnimator; import dev.dworks.libs.actionbarplus.R; public class FloatLabelEditText extends LinearLayout { private int mFocusedColor, mUnFocusedColor, mFitScreenWidth, mCurrentApiVersion = android.os.Build.VERSION.SDK_INT; private float mTextSizeInSp; private String mHintText, mEditText; private AttributeSet mAttrs; private Context mContext; private EditText mEditTextView; private TextView mFloatingLabel; // ----------------------------------------------------------------------- // default constructors public FloatLabelEditText(Context context) { super(context); mContext = context; initializeView(); } public FloatLabelEditText(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; mAttrs = attrs; initializeView(); } public FloatLabelEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mContext = context; mAttrs = attrs; initializeView(); } // ----------------------------------------------------------------------- // public interface public EditText getEditText() { return mEditTextView; } public String getText() { if (getEditTextString() != null && getEditTextString().toString() != null && getEditTextString().toString().length() > 0) { return getEditTextString().toString(); } return ""; } // ----------------------------------------------------------------------- // private helpers private void initializeView() { if (mContext == null) return; LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mInflater.inflate(R.layout.floatlabel_edittext, this, true); mFloatingLabel = (TextView) findViewById(R.id.floating_label_hint); mEditTextView = (EditText) findViewById(R.id.floating_label_edit_text); getAttributesFromXmlAndStoreLocally(); setupEditTextView(); setupFloatingLabel(); } private void getAttributesFromXmlAndStoreLocally() { TypedArray attributesFromXmlLayout = mContext.obtainStyledAttributes(mAttrs, R.styleable.FloatLabelEditText ); if (attributesFromXmlLayout == null) return; mHintText = attributesFromXmlLayout.getString(R.styleable.FloatLabelEditText_hint); mEditText = attributesFromXmlLayout.getString(R.styleable.FloatLabelEditText_text); mTextSizeInSp = getScaledFontSize(attributesFromXmlLayout.getDimensionPixelSize(R.styleable.FloatLabelEditText_textSize, (int) mEditTextView.getTextSize())); mFocusedColor = attributesFromXmlLayout.getColor(R.styleable.FloatLabelEditText_textColorHintFocused, android.R.color.black); mUnFocusedColor = attributesFromXmlLayout.getColor(R.styleable.FloatLabelEditText_textColorHintUnFocused, android.R.color.darker_gray); mFitScreenWidth = attributesFromXmlLayout.getInt(R.styleable.FloatLabelEditText_fitScreenWidth, 0); attributesFromXmlLayout.recycle(); } private void setupEditTextView() { mEditTextView.setHint(mHintText); mEditTextView.setHintTextColor(mUnFocusedColor); mEditTextView.setText(mEditText); mEditTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextSizeInSp); mEditTextView.addTextChangedListener(getTextWatcher()); if (mFitScreenWidth > 0) { mEditTextView.setWidth(getSpecialWidth()); } if (mCurrentApiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) { mEditTextView.setOnFocusChangeListener(getFocusChangeListener()); } } private void setupFloatingLabel() { mFloatingLabel.setText(mHintText); mFloatingLabel.setTextColor(mUnFocusedColor); mFloatingLabel.setTextSize(TypedValue.COMPLEX_UNIT_SP, (float) (mTextSizeInSp / 1.3)); mFloatingLabel.setPadding(mEditTextView.getPaddingLeft(), 0, 0, 0); if (getText().length() > 0) { showFloatingLabel(); } } private TextWatcher getTextWatcher() { return new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} @Override public void afterTextChanged(Editable s) { if (s.length() > 0 && mFloatingLabel.getVisibility() == INVISIBLE) { showFloatingLabel(); } else if (s.length() == 0 && mFloatingLabel.getVisibility() == VISIBLE) { hideFloatingLabel(); } } }; } private void showFloatingLabel() { setShowHint(true); //mFloatingLabel.setVisibility(VISIBLE); //mFloatingLabel.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.slide_from_bottom)); } private void hideFloatingLabel() { setShowHint(true); //mFloatingLabel.setVisibility(INVISIBLE); //mFloatingLabel.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.slide_to_bottom)); } private void setShowHint(final boolean show) { AnimatorSet animation = null; if ((mFloatingLabel.getVisibility() == VISIBLE) && !show) { animation = new AnimatorSet(); ObjectAnimator move = ObjectAnimator.ofFloat(mFloatingLabel, "translationY", 0, mFloatingLabel.getHeight() / 8); ObjectAnimator fade = ObjectAnimator.ofFloat(mFloatingLabel, "alpha", 1, 0); animation.playTogether(move, fade); } else if ((mFloatingLabel.getVisibility() != VISIBLE) && show) { animation = new AnimatorSet(); ObjectAnimator move = ObjectAnimator.ofFloat(mFloatingLabel, "translationY", mFloatingLabel.getHeight() / 8, 0); ObjectAnimator fade = ObjectAnimator.ofFloat(mFloatingLabel, "alpha", 0, 1); animation.playTogether(move, fade); } if (animation != null) { animation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); mFloatingLabel.setVisibility(VISIBLE); } @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mFloatingLabel.setVisibility(show ? VISIBLE : INVISIBLE); } }); animation.start(); } } private OnFocusChangeListener getFocusChangeListener() { return new OnFocusChangeListener() { ValueAnimator mFocusToUnfocusAnimation, mUnfocusToFocusAnimation; @Override public void onFocusChange(View v, boolean hasFocus) { ValueAnimator lColorAnimation; if (hasFocus) { lColorAnimation = getFocusToUnfocusAnimation(); } else { lColorAnimation = getUnfocusToFocusAnimation(); } lColorAnimation.setDuration(700); lColorAnimation.start(); } private ValueAnimator getFocusToUnfocusAnimation() { if (mFocusToUnfocusAnimation == null) { mFocusToUnfocusAnimation = getFocusAnimation(mUnFocusedColor, mFocusedColor); } return mFocusToUnfocusAnimation; } private ValueAnimator getUnfocusToFocusAnimation() { if (mUnfocusToFocusAnimation == null) { mUnfocusToFocusAnimation = getFocusAnimation(mFocusedColor, mUnFocusedColor); } return mUnfocusToFocusAnimation; } }; } private ValueAnimator getFocusAnimation(int fromColor, int toColor) { ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), fromColor, toColor); colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { mFloatingLabel.setTextColor((Integer) animator.getAnimatedValue()); } }); return colorAnimation; } private Editable getEditTextString() { return mEditTextView.getText(); } private float getScaledFontSize(float fontSizeFromAttributes) { float scaledDensity = getContext().getResources().getDisplayMetrics().scaledDensity; return fontSizeFromAttributes/scaledDensity; } private int getSpecialWidth() { float screenWidth = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth(); int prevWidth = mEditTextView.getWidth(); switch (mFitScreenWidth) { case 2: return (int) Math.round(screenWidth * 0.5); default: return Math.round(screenWidth); } } }