Android 自定義view之TextInputLayout

一.使用EditText實現(xiàn)TextInputLayout

1.1效果


MaterialEditText.gif

1.2 talk is cheap

import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;

import com.example.rookie.hencoder_plus.R;
import com.example.rookie.hencoder_plus.custom_view_06.Utils;

/**
 * 帶有提示的EditText
 * 類似于design包中的TextInputLayout
 * 1.加大paddingTop(文字高度+間距)用來擺放hintText
 * 2.文字變化(有->無,無->有)時,增加動畫效果
 * 3.增加xml自定義屬性以及java代碼的開關(guān)
 */
public class MaterialEditText extends AppCompatEditText {
    private static final float HINT_TEXT_ANIMATION_OFFSET = Utils.dp2px(25);//動畫距離
    private static final float EXTRA_PADDING_TOP_DISTANCE = Utils.dp2px(12);//文字高度
    private static final float EXTRA_MARGIN_TOP_DISTANCE = Utils.dp2px(10);//hint文字距editText高度
    private static final float EXTRA_VERTICAL_OFFSET_ORIGINAL = EXTRA_PADDING_TOP_DISTANCE + EXTRA_MARGIN_TOP_DISTANCE;
    private static final float EXTRA_HORIZONTAL_OFFSET = Utils.dp2px(4);//橫向偏移,為了與EditText的content對齊
    TextPaint hintTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
    private String hintText = getHint().toString();
    private ObjectAnimator showHintUpAnimator, disappearHintDownAnimator;
    private boolean hintHasShown;//hintText是否已經(jīng)顯示
    private boolean shouldShowTopHint = true;//是否需要顯示上面的hint(給外部開發(fā)者調(diào)用)
    private TextWatcher watcher;

    public MaterialEditText(Context context) {
        this(context, null);
    }

    public MaterialEditText(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MaterialEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MaterialEditText);
        shouldShowTopHint = typedArray.getBoolean(R.styleable.MaterialEditText_shouldShowTopHint, true);
        typedArray.recycle();
        init();
    }

    private void init() {

        initTextPaint();
        initPadding();
        initTextWatcher();
    }

    private void initTextWatcher() {
        if (!shouldShowTopHint) {
            removeTextChangedListener(watcher);
            return;
        }
        if (watcher == null) {
            watcher = 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) {
                    if (hintHasShown && TextUtils.isEmpty(s)) {
                        //如果已經(jīng)顯示并且EditText已經(jīng)清空
                        hintHasShown = false;
                        getAnimatorToDisappearDownHint().start();
                    } else if (!hintHasShown && !TextUtils.isEmpty(s.toString())) {
                        //上方的hint還未顯示,并且EditText的文字非空
                        hintHasShown = true;
                        getAnimatorToShowUpHint().start();
                    }
                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            };
            Log.e("test", "看看加了幾次");
            addTextChangedListener(watcher);
        }

    }


    ObjectAnimator getAnimatorToShowUpHint() {
        if (showHintUpAnimator == null) {
            showHintUpAnimator = ObjectAnimator.ofFloat(this, "hintFraction", 0, 1);
            showHintUpAnimator.setDuration(1000);
        }
        return showHintUpAnimator;
    }

    ObjectAnimator getAnimatorToDisappearDownHint() {
        if (disappearHintDownAnimator == null) {
            disappearHintDownAnimator = ObjectAnimator.ofFloat(this, "hintFraction", 1, 0);
            disappearHintDownAnimator.setDuration(1000);
        }
        return disappearHintDownAnimator;
    }

    private void initPadding() {
        //增大paddingtop,為hinttext騰地方
        int paddingTop = shouldShowTopHint ? (int) (getPaddingTop() + EXTRA_VERTICAL_OFFSET_ORIGINAL) : (int) (getPaddingTop() - EXTRA_VERTICAL_OFFSET_ORIGINAL);
        setPadding(getPaddingLeft(), paddingTop, getPaddingRight(), getPaddingBottom());
    }

    private void initTextPaint() {
        hintTextPaint.setColor(Color.BLACK);
        hintTextPaint.setTextSize(EXTRA_PADDING_TOP_DISTANCE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //通過動畫的fraction配合paint的alpha來實現(xiàn)文字的顯示和消失
        hintTextPaint.setAlpha((int) (0xff * hintFraction));
        canvas.drawText(hintText, EXTRA_HORIZONTAL_OFFSET, EXTRA_PADDING_TOP_DISTANCE + HINT_TEXT_ANIMATION_OFFSET * (1 - hintFraction), hintTextPaint);
    }

    /* 屬性動畫使用start */
    private float hintFraction;

    public float getHintFraction() {
        return hintFraction;
    }

    /**
     * dont  call this method from outside
     *
     * @param hintFraction
     */
    public void setHintFraction(float hintFraction) {
        this.hintFraction = hintFraction;
        invalidate();
    }
    /* 屬性動畫使用end */

    public void setShouldShowTopHint(boolean shouldShowTopHint) {
        if (this.shouldShowTopHint != shouldShowTopHint) {
            //如果當(dāng)前顯示的flag和傳入的flag不同時,才修改狀態(tài)
            //1。修改padding
            if (this.shouldShowTopHint) {
                //原來顯示,變?yōu)椴伙@示,則去掉padding
            } else {
                //原來不顯示,變?yōu)轱@示,加上padding
            }
            this.shouldShowTopHint = shouldShowTopHint;
            initPadding();
            initTextWatcher();
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容