Android之EditText限制6个中文12个英文

本文只是记录一些零碎的东西

要求输入框最多输入6个中文,12个英文

主要是监听输入框变化

如何使用

EditText.addTextChangedListener(new SketchTextWatcher(mTitleContent));
InputFilter[] filters = {new SketchLengthFilter()};
EditText.setFilters(filters);

自己处理的两个类:

private static class SketchTextWatcher implements TextWatcher {
        private int editStart;
        private int editEnd;
        private int maxLen = 12; // 6 个汉字 12 个英文字符 (表情 2 个字符)

        private EditText editText;

        public SketchTextWatcher(EditText e) {
            editText = e;
        }

        @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) {
            D.i("slack", "afterTextChanged..." + s);
            editStart = editText.getSelectionStart();
            editEnd = editText.getSelectionEnd();
            // 先去掉监听器,否则会出现栈溢出
            editText.removeTextChangedListener(this);
            if (!TextUtils.isEmpty(s.toString())) {
                while (calculateLength(s.toString()) > maxLen) {
                    s.delete(--editStart, editEnd--);
                        D.i("slack", "editStart = " + editStart + " editEnd = " + editEnd + " s = " + s);
                }
            }

            editText.setText(s);
            editText.setSelection(editStart);
            // 恢复监听器
            editText.addTextChangedListener(this);
        }

        /**
         * 英文一个字符  中文两个字符
         */
        private int calculateLength(String string) {
            char[] ch = string.toCharArray();

            int varlength = 0;
            for (char c : ch) {
                // changed by zyf 0825 , bug 6918,加入中文标点范围 , TODO 标点范围有待具体化
                if ((c >= 0x2E80 && c <= 0xFE4F) || (c >= 0xA13F && c <= 0xAA40) || c >= 0x80) { // 中文字符范围0x4e00 0x9fbb
//                    if (c >= 0x4E00 && c <= 0x9FBB) { // 中文字符范围 0x4E00-0x9FA5 + 0x9FA6-0x9FBB
                    varlength = varlength + 2;
                } else {
                    varlength++;
                }
            }
            D.i("slack", "length : " + varlength + " l: " + string.length());
            return varlength;
        }
    }

    /**
     * 纯英文 纯中文 可以实现 from : http://justwyy.iteye.com/blog/1543419
     * 中英混输入 :
     * 中文 占 2 位
     * 英文 占 1 位
     * 思路:计算 已有文字的长度,计算新增文字的长度,长度没有到达限制时,拼接
     * 小米 输入时,没有边输入边写入EditText的手机有问题,比如小米
     * 华为这种输入一个字符就写入的,没有问题
     */
    private static class SketchLengthFilter implements InputFilter {

        private final int LENGTH_ENGLISH;

        SketchLengthFilter() {
            this(12);
        }

        SketchLengthFilter(int english) {
            LENGTH_ENGLISH = english;
        }

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {

            int keep = LENGTH_ENGLISH - (calculateLength(dest.toString()) - (dend - dstart));
            end = calculateLength(source.toString());
            D.i("slack", "source("+start+","+end+")="+source+",dest("+dstart+","+dend+")="+dest + " keep:" + keep);

            CharSequence result = "";
            if(keep >= 0) {
                if (keep >= end - start) {
                    result = null; // keep original
                } else {
                    result = subSequence(source.toString(), start, start + keep);
                }
            }
            D.i("slack","result : " + (result == null ? "null": result) + ".");
            return result;
        }

        private CharSequence subSequence(@NonNull String source,int start,int length){
            int size = calculateLength(source);
            if(size < length){
                return source;
            }
            char[] chars = source.toCharArray();
            if(chars.length < length){
                return source;
            }
            char[] result = new char[length - start];
            System.arraycopy(chars, start , result, 0, length);
            return new String(result);
        }

        private int calculateLength(String string){
            int length = 0;
            char[] chars = string.toCharArray();
            for (char c : chars) {
                if (isChinese(c)) {
                    length += 2;
                } else {
                    length++;
                }
            }
            return length;
        }

        private boolean isChinese(char c) {
            Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
            return ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                    || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                    || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                    || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                    || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                    || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS;
        }
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值