EditText自动格式化银行卡、手机号等号码,亮瞎钛合金

1,610 阅读2分钟
原文链接: note.youdao.com

一.背景

项目需求,有一个验证码交互稿: image
其中edittext输入验证码,且验证码能够自动4位一组进行格式化。

二.分析实现

这种简单的ui缺失难不倒工作两年的我,所以最开始直接就工具设计稿的样式,一眼看去得到的解决方案是:监听edittext,给它添加addTextChangedListener监听器,当输入长度是4或者4的倍数的时候,插入一个空格。这种解决方案其实实现很简单,但是却很死板。
最终你通过edittext.getText().toString()的时候,其实你得到的真实String是:"ABCD EFGH IJKL ****"这样的带有空格的字符串,如果要得到真实的输入数据,你岂不是还要进行解析去除空格?
总之,实现是简单的,但是却增加了解析工作量。

三.优化

后续在代码优化的过程中,重新进行了解决方案的分析。
其实对于每一个Edittext而言,他都是TextView,TextView可以通过SpannableString来定义各式各样的文字显示效果,那么我们也肯定可以通过SpannableString来自定义文字显示空格的效果吧。
话不多说直接一通google。大家可以参考教你自定义android中span来了解ReplacementSpan这个基类,所有TextView显示的Spann样式都是通过它来实现的。 下面我直接上代码了。代码了比较少,也好理解:

public class SpaceSpan extends ReplacementSpan {
    private int mSize;//span宽度,可以自己定制
    private int mMargin;

    public SpaceSpan(int margin) {
        mMargin = margin;
    }

    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
        //测量文字的宽度,这里人为的添加了一个margin,表示该文字占用的显示宽度增加了。
        mSize = (int) (paint.measureText(text, start, end) + mMargin);
        return mSize;
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
        paint.setAntiAlias(true);
        canvas.drawText(text, start, end, x, y, paint);//绘制文字
    }
}

调用:

String content = mEtInvitedCode.getText().toString();
SpannableString string = new SpannableString(content);
int length = content.length();
int times = length / SPACE_STEP;//需要显示空格的步频,本文中4个字符显示一个空格。
for (int i = 0; i < times &&; i++) {
    string.setSpan(new SpaceSpan((int) getResources().getDimension(R.dimen.auth_edit_margin)), (i+1) * SPACE_STEP - 1, (i + 1) * SPACE_STEP, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
mEtInvitedCode.setText(string);
mEtInvitedCode.setSelection(string.length());

所以,本身比较简单的一个UI显示需求,通过更加简单以及合理的方式来实现它,满满的爱的力量。 扩展知识面是很重要的,他可以让你有新的思路去更加简单的解决问题。