EditText输入最大字数控制

android EditText输入框如何实现文字的输入长度控制呢,达到这种需求的有很多种方法;

第一种:那就是直接在XML布局代码里面设置:

<EditText
    android:id="@+id/et_suggestion"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:maxLength="40"
    android:minHeight="100dp"
    />

上面的android:maxLength="40" 是表示输入的最大长度为40字节;

第二种,利用 TextWatcher 进行监听

mEditText.addTextChangedListener(new TagNameTextWatch(mEditText),40);
。。。。。。。
。。。。。。。
//TagNameTextWatch 可以直接写成内部类
class TagNameTextWatch implements TextWatcher {
    private EditText et;
    private int maxLenth;
    TagNameTextWatch(EditText et,int maxLenth) {
        this.maxLenth = et;
        this.et = et;    }  
  @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) {     
 
     Editable editable = et.getText();  
        int len = editable.length();  
        if(len > maxLen)  
        {  
            int selEndIndex = Selection.getSelectionEnd(editable);  
            String str = editable.toString();  
            //截取新字符串  
            String newStr = str.substring(0,maxLen);  
            editText.setText(newStr);  
            editable = editText.getText();  
              
            //新字符串的长度  
            int newLen = editable.length();  
            //旧光标位置超过字符串长度  
            if(selEndIndex > newLen)  
            {  
                selEndIndex = editable.length();  
            }  
            //设置新光标所在的位置  
            Selection.setSelection(editable, selEndIndex);  
              
        }  
    }
}

第三种就是用到了InputFilter实现;

网上查到有些人会直接这样写来实现字数输入的控制:

editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(40)});  

上面的代码是能实现基本的字数控制,当如果加上以下别的需求,比如在输入超过40个字节是给予用户提示;那么下面我们就来吧InputFilter进行封装下;

先写一个EditTextLengthFilter类来继承InputFilter

在Activity里面执行mEditText.setFilters(newInputFilter[]{newEditTextLengthFilter(this,40,mEditText)});

下面是EditTextLengthFilter 的代码:


public class EditTextLengthFilter implements InputFilter {
    private int maxLength;// 最大英文/数字长度 一个汉字算两个字母
    private Context mContext;
    /**
     * unicode编码,判断是否为汉字(中文汉字区间)
     */
    String regEx = "[\\u4e00-\\u9fa5]";
    private String mToast;
    private TextView tvShowNum;
    /**
     * 标示是单数还是双数
     */
    private boolean isMupli = false;
    /**
     * 设置文本框最大输入长度
     *
     * @param context 上下文
     * @param length  最大长度(备注:字符长度为应为英文长度)
     * @param toast   提示语
     * @param showNum 显示文字变化的TextView
     */
    public EditTextLengthFilter(Context context, int length, TextView showNum, String toast) {
        init(context, length, toast, showNum, null);
    }
    /**
     * 初始化EditText必要参数
     *
     * @param context                      上下文
     * @param length                       最大长度(备注:字符长度为应为英文长度,单数不处理,双数 /2 )
     * @param toast                        提示语
     * @param showNum                      显示文字变化的TextView
     * @param editTextLengthChangeListener 文字变化的监听
     */
    private void init(Context context, int length, String toast, TextView showNum, EditTextLengthChangeListener editTextLengthChangeListener) {
        mContext = context;
        isMupli = length % 2 == 0;
        maxLength = isMupli ? length / 2 : length;
        mToast = toast != null ? toast : "输入文字超过最大长度";
        tvShowNum = showNum;
    }


    /**
     * @param source 新输入的字符串
     * @param start  新输入的字符串起始下标,一般为0
     * @param end    新输入的字符串终点下标,一般为source长度-1
     * @param dest   输入之前文本框内容
     * @param dStart 原内容起始坐标,一般为0
     * @param dEnd   原内容终点坐标,一般为dest长度-1
     * @return 返回输入的字符
     */
    @Override
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dStart, int dEnd) {
        // 计算原始长度
        int destCount = getLength(dest.toString());
        // 计算原始长度是否会改变
        boolean changeLength = dEnd - dStart != 0 && end - start != 0;
        int deleteLength = 0;
        if (changeLength ){
            // 说明文字会被替换,需要计算替换长度
            String sub = dest.subSequence(dStart,dEnd).toString();
            deleteLength = getLength(sub);
        }
        // 计算输入长度
        int sourceCount = getLength(source.toString());
        //  判断添加文字之后长度 initLength 为 不做处理的长度
        int initLength = destCount + sourceCount - deleteLength;
        int length = isMupli ? (initLength + 1) / 2 : initLength;
        if (length > maxLength) {


            // 多余部分显示可以显示数据
            int overSize = isMupli ? 2 * maxLength - (destCount - deleteLength) : maxLength -                     (destCount - deleteLength);
            String overContent = "";
            if (sourceCount != 0 ) {
                int subSize = getLength(source.toString(), overSize);
                if (subSize > 0) {
                    overContent = source.subSequence(0, subSize).toString();
                }
            }
            if (!TextUtils.isEmpty(mToast)) {
                ToastUtil.showTextViewPrompt(AppContextUtils.getAppContext(), mToast);
            }
            operator(maxLength);
            return overContent;
        } else {
            int d = dEnd - dStart;
            // 说明是在删除文字
            if (d > 0 && length > 0 && start == 0 && end == 0) {
                // 说明是全部删除英文字母 &&  说明是全部删除中文字母
                if (d == destCount || d == dest.length()) {
                    length = 0;
                } else {
                    // sourceCount 字符长度如果为0 则说明在删除文字
                    if (sourceCount == 0) {
                        int sub = getLength(dest.subSequence(dStart, dEnd).toString());
                        if (sub > 1) {
                            length = length - (sub + 1) / 2;
                        } else if (sub == 1) {
                            if (destCount % 2 != 0) {
                                length = length - 1;
                            }
                        }
                    }
                }
            }
            operator(length);
            return source;
        }
    }


    /**
这里显示我们平时看到的12/40的需求,
     */
    private void operator(int length) {
        if (tvShowNum != null) {
            String num = length + "/" + maxLength;
            tvShowNum.setText(num);
        }
     
    }


    /**
     * 计算字符长度 中文算两个
     *
     * @param str 原始字符长度
     * @return 返回总长度
     */
    private int getLength(String str) {
        int count = str.length();
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        while (m.find()) {
            for (int i = 0; i <= m.groupCount(); i++) {
                count = count + 1;
            }
        }
        return count;
    }
    /**
     * 获取可以显示的长度
     *
     * @param str       待截取文本
     * @param maxLength 可以显示的大小
     * @return 返回截取文本的长度
     */
    private int getLength(String str, int maxLength) {
        // 对于用户显示的长度
        int count = 0;
        // 实际字节的长度
        int cutIndex = 0;
        if (maxLength > 0) {
            char[] currentCh = str.toCharArray();
            for (char c : currentCh) {
                if (c >= 0x4e00 && c <= 0x9fbb) {
                    // 中文加2个
                    count = count + 2;
                } else {
                    count++;
                }
                if (count > maxLength) {
                    return cutIndex;
                }
                cutIndex++;
            }
        }
        return cutIndex;
    }

上面EditTextLengthFilter 重写了InputFilter 里面的filter方法,里面有比较清楚的截取文字长度的逻辑,大家需要细看;






  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值