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

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


1516330704071mz效果圖.gif

主要實(shí)現(xiàn)步驟及相關(guān)代碼:
1.首先創(chuàng)建一個類繼承EditText,實(shí)現(xiàn)構(gòu)造方法议纯;
2.定義相關(guān)屬性:在《項(xiàng)目名稱》\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從左向右擴(kuò)展浅役,right從右向左擴(kuò)展顯示,
            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()中實(shí)現(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()中實(shí)時計(jì)算:

 @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ù)增多時向右擴(kuò)展
    public final static int GRAVITY_RIGHT = 2;//字?jǐn)?shù)顯示在右邊钧椰,當(dāng)數(shù)字位數(shù)增多時向左擴(kuò)展
    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 要校驗(yàn)的字符
     * @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)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市符欠,隨后出現(xiàn)的幾起案子嫡霞,更是在濱河造成了極大的恐慌,老刑警劉巖希柿,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诊沪,死亡現(xiàn)場離奇詭異,居然都是意外死亡曾撤,警方通過查閱死者的電腦和手機(jī)端姚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挤悉,“玉大人渐裸,你說我怎么就攤上這事∽氨” “怎么了橄仆?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長衅斩。 經(jīng)常有香客問我盆顾,道長,這世上最難降的妖魔是什么畏梆? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任您宪,我火速辦了婚禮,結(jié)果婚禮上奠涌,老公的妹妹穿的比我還像新娘宪巨。我一直安慰自己,他們只是感情好溜畅,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布捏卓。 她就那樣靜靜地躺著,像睡著了一般慈格。 火紅的嫁衣襯著肌膚如雪怠晴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天浴捆,我揣著相機(jī)與錄音蒜田,去河邊找鬼。 笑死选泻,一個胖子當(dāng)著我的面吹牛冲粤,可吹牛的內(nèi)容都是我干的美莫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼梯捕,長吁一口氣:“原來是場噩夢啊……” “哼厢呵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起傀顾,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤襟铭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后锣笨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡道批,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年错英,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隆豹。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡椭岩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出璃赡,到底是詐尸還是另有隱情判哥,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布碉考,位于F島的核電站塌计,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏侯谁。R本人自食惡果不足惜锌仅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望墙贱。 院中可真熱鬧热芹,春花似錦、人聲如沸惨撇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽魁衙。三九已至报腔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間剖淀,已是汗流浹背榄笙。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工狂秘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留懊昨,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓稽穆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親米丘。 傳聞我的和親對象是個殘疾皇子剑令,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359