自定義EditView實現(xiàn)同步顯示輸入的字符長度

在日常開發(fā)中有時需要實現(xiàn)在一個輸入框中輸入字并且同步顯示已輸入字符的長度,以方便查看此輸入框最大能輸入多少字符,現(xiàn)在已輸入多少字符。實現(xiàn)效果如下:


1516330704071mz效果圖.gif

主要實現(xiàn)步驟及相關(guān)代碼:
1.首先創(chuàng)建一個類繼承EditText,實現(xiàn)構(gòu)造方法;
2.定義相關(guān)屬性:在《項目名稱》\src\main\res\values\attrs.xml文件中:

 <declare-styleable name="WordsNumEditText">
        <attr name="numTextGravity" format="enum">
            <enum name="left" value="1" />
            <enum name="right" value="2" />
        </attr>
        <attr name="numTextSize" format="dimension" />
        <attr name="numTextColor" format="color" />

3.初始化設(shè)置的相關(guān)屬性:

/**
     * @param context
     * @param attrs   初始化屬性
     */
    private void initAttribute(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.WordsNumEditText);
        try {
            mNumTextSize = (int) ta.getDimension(R.styleable.WordsNumEditText_numTextSize, DensityUtils.sp2px(context, 12));//字體大小
            mNumTextColor = ta.getColor(R.styleable.WordsNumEditText_numTextColor, Color.parseColor("#b1b1b1"));//字體顏色
            grivity = ta.getInt(R.styleable.WordsNumEditText_numTextGravity, grivity);//顯示的位置,left從左向右擴展,right從右向左擴展顯示,
            maxLength = getMaxLength();//獲取設(shè)置的最大顯示字?jǐn)?shù)
            paddingLeft = getPaddingLeft();
            paddingRight = getPaddingRight();
            bottom = DensityUtils.dip2px(context, 10);
            setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() + DensityUtils.dip2px(context, 10));
        } finally {
            ta.recycle();
        }
      initPaint();//初始化畫筆
    
    }

其中獲取editText的maxLength屬性值的方法詳情如下:

 /**
     * @return length
     * 獲取editText的MaxLength的屬性值
     */
    public int getMaxLength() {
        int length = 0;
        try {
            InputFilter[] inputFilters = this.getFilters();
            for (InputFilter filter : inputFilters) {
                Class<?> c = filter.getClass();
                if (c.getName().equals("android.text.InputFilter$LengthFilter")) {
                    Field[] f = c.getDeclaredFields();
                    for (Field field : f) {
                        if (field.getName().equals("mMax")) {
                            field.setAccessible(true);
                            length = (Integer) field.get(filter);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return length;
    }

3.初始化畫筆,需根據(jù)設(shè)置的grivity屬性確定畫筆滑動的方向:

 /**
     * 創(chuàng)建一個畫筆
     *
     * @param paintColor 畫筆顏色
     * @param textSize   文字大小
     * @param style      畫筆樣式
     * @param roundWidth 畫筆寬度
     * @return
     */
    private Paint createLeftPaint(int paintColor, int textSize, Paint.Style style, int roundWidth) {
        Paint paint = new Paint();
        paint.setColor(paintColor);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(roundWidth);
        paint.setDither(true);
        paint.setTextSize(textSize);
        paint.setTextAlign(Paint.Align.LEFT);//這是grivity為left的時候,若grivity是right,則設(shè)置為 Paint.Align.RIGHT
        paint.setStyle(style);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeJoin(Paint.Join.ROUND);
        return paint;
    }

4.在onDraw()中實現(xiàn)畫“數(shù)字”的邏輯:

 /**
     * @param canvas 畫輸入框中 字?jǐn)?shù)/最大字?jǐn)?shù)
     */
    private void drawNumberText(Canvas canvas) {

        int length = getText().length();
        String str = length + "/" + maxLength;
        int x = 0;
        if (grivity == GRAVITY_LEFT) {
            x = 0 + paddingLeft;
        } else {
            x = width - paddingRight;
        }
        int y = height - bottom;
        canvas.drawText(str, x, y, textPaint);
    }

其中width和height需要在onMeasure()中實時計算:

 @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
    }

最后附上完整代碼及demo地址(名稱有些繁瑣,莫見怪哈):https://github.com/ErieCorner/DesplayInputCharacterLengthEdittextModule.git

public class DeplayInputCharacterLenghtEditText extends EditText {
    public DeplayInputCharacterLenghtEditText(Context context) {
        super(context);
        initAttribute(context, null);
    }

    public DeplayInputCharacterLenghtEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttribute(context, attrs);
    }

    public DeplayInputCharacterLenghtEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttribute(context, attrs);
    }

    private int mNumTextColor = Color.parseColor("#b1b1b1");
    private int mNumTextSize = 12;
    public final static int GRAVITY_LEFT = 1;//字?jǐn)?shù)顯示在左邊,當(dāng)數(shù)字位數(shù)增多時向右擴展
    public final static int GRAVITY_RIGHT = 2;//字?jǐn)?shù)顯示在右邊,當(dāng)數(shù)字位數(shù)增多時向左擴展
    private int grivity = GRAVITY_RIGHT;
    private Context context;
    private Paint textPaint;
    private int width;
    private int height;
    private int maxLength;
    private int paddingLeft = 0;
    private int paddingRight = 0;
    private int bottom = 0;

    /**
     * 初始化畫筆
     */
    private void initPaint() {
        if (grivity == GRAVITY_LEFT) {
            textPaint = createLeftPaint(mNumTextColor, mNumTextSize, Paint.Style.FILL, 2);
        } else {
            textPaint = createRightPaint(mNumTextColor, mNumTextSize, Paint.Style.FILL, 2);
        }

    }

    /**
     * @param context
     * @param attrs   初始化屬性
     */
    private void initAttribute(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.DeplayInputCharacterLenghtEditText);
        try {
            mNumTextSize = (int) ta.getDimension(R.styleable.DeplayInputCharacterLenghtEditText_numTextSize, DensityUtils.sp2px(context, 12));
            mNumTextColor = ta.getColor(R.styleable.DeplayInputCharacterLenghtEditText_numTextColor, Color.parseColor("#b1b1b1"));
            grivity = ta.getInt(R.styleable.DeplayInputCharacterLenghtEditText_numTextGravity, grivity);
            maxLength = getMaxLength();
        } finally {
            ta.recycle();
        }
        paddingLeft = getPaddingLeft();
        paddingRight = getPaddingRight();
        bottom = DensityUtils.dip2px(context, 10);
        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom() + DensityUtils.dip2px(context, 10));
        initPaint();

    }


    /**
     * 判斷是否為emoji表情
     *
     * @param codePoint 要校驗的字符
     * @return 是否為表情
     */
    private boolean isEmojiCharacter(char codePoint) {
        return !((codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA) ||
                (codePoint == 0xD) || ((codePoint >= 0x20) && codePoint <= 0xD7FF)) ||
                ((codePoint >= 0xE000) && (codePoint <= 0xFFFD));
    }

    /**
     * 創(chuàng)建一個畫筆
     *
     * @param paintColor 畫筆顏色
     * @param textSize   文字大小
     * @param style      畫筆樣式
     * @param roundWidth 畫筆寬度
     * @return
     */
    private Paint createLeftPaint(int paintColor, int textSize, Paint.Style style, int roundWidth) {
        Paint paint = new Paint();
        paint.setColor(paintColor);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(roundWidth);
        paint.setDither(true);
        paint.setTextSize(textSize);
        paint.setTextAlign(Paint.Align.LEFT);
        paint.setStyle(style);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeJoin(Paint.Join.ROUND);
        return paint;
    }

    /**
     * 創(chuàng)建一個畫筆
     *
     * @param paintColor 畫筆顏色
     * @param textSize   文字大小
     * @param style      畫筆樣式
     * @param roundWidth 畫筆寬度
     * @return
     */
    private Paint createRightPaint(int paintColor, int textSize, Paint.Style style, int roundWidth) {
        Paint paint = new Paint();
        paint.setColor(paintColor);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(roundWidth);
        paint.setDither(true);
        paint.setTextSize(textSize);
        paint.setTextAlign(Paint.Align.RIGHT);
        paint.setStyle(style);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeJoin(Paint.Join.ROUND);
        return paint;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawNumberText(canvas);
    }

    /**
     * @param canvas 畫輸入框中 字?jǐn)?shù)/最大字?jǐn)?shù)
     */
    private void drawNumberText(Canvas canvas) {

        int length = getText().length();
        String str = length + "/" + maxLength;
        int x = 0;
        if (grivity == GRAVITY_LEFT) {
            x = 0 + paddingLeft;
        } else {
            x = width - paddingRight;
        }
        int y = height - bottom;
        canvas.drawText(str, x, y, textPaint);


    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        super.onTextChanged(text, start, lengthBefore, lengthAfter);
        postInvalidate();
    }

    /**
     * @return length
     * 獲取editText的MaxLength的屬性值
     */
    public int getMaxLength() {
        int length = 0;
        try {
            InputFilter[] inputFilters = this.getFilters();
            for (InputFilter filter : inputFilters) {
                Class<?> c = filter.getClass();
                if (c.getName().equals("android.text.InputFilter$LengthFilter")) {
                    Field[] f = c.getDeclaredFields();
                    for (Field field : f) {
                        if (field.getName().equals("mMax")) {
                            field.setAccessible(true);
                            length = (Integer) field.get(filter);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return length;
    }
}
最后編輯于
?著作權(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ù)。

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