Android-EditText仿QQ名称限制内容长度中文占2个长度

思路依据:

Java中无论是汉字还是英文字母都是用Unicode编码来表示的,一个Unicode码是16位,每字节是8位,所以一个Unicode码占至少两字节。但是英文字母比较特殊,源自于8位(1字节)的ASCII吗,于是在Unicode码仅使用了低8位(1字节)就可以表示,高8位的话不使用也无所谓。所以
char a = ‘a’;
byte b = (byte) a;
a = (char) b;
System.out.println(a);//最后输出结果还是a
但是中就不行了,中文至少占两个字节,经过上面转换会丢失高于1个字节的编码

实战
首先来看一下,TextWatcher 接口
public interface TextWatcher extends NoCopySpan {

  @Override public void afterTextChanged(Editable s) {//表示最终内容

  }

  @Override
  public void beforeTextChanged(CharSequence s, int start/*开始的位置*/, int count/*删除的内容数*/, int after/*增加的内容数量*/) {
    //这里的s表示改变之前的内容,通常start和count组合,可以在s中读取本次删除的内容。而after表示增加的内容数量。
  }

  @Override
  public void onTextChanged(CharSequence s, int start/*开始位置*/, int before/*删除内容的数量*/, int count/*新增数*/) {
    //这里的s表示改变之后的内容,
}

接下来,贴出判断是不是中文让人眼前一亮的代码,当时楼主看到的时候,感到很赞~~

(char) (byte) s.charAt(index) != s.charAt(index)

这段代码什么意思呢,大家都知道 byte在java中占一个字节,char占两个字节。根据上面思路依据所知中文在java中占两个字节。而英文、中文在char中都占一个char的长度。那么byte在java中占一个字节,英文为一个字节,char两个字节,我把char转成byte,就把2个字节转成一个字节。如果是英文没问题。char转byte还等于原来的char。但是中文就有问题了。因为中文占2个字节,char转byte丢了一个字节,那么char转byte后就不等于原来的char了
####最终代码

public class BaseTextChangedListener implements TextWatcher {

  /**
   * 中文占2个长度,英文占一个长度
   */
  protected int mMaxLength = 10;
  
  
  protected int mCurrentLength = 0;

  EditText mEditText;

  public BaseTextChangedListener(int maxLength, EditText editText) {
    this.mMaxLength = maxLength;
    this.mEditText = editText;
  }

  @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {

  }

  @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
    if (mEditText == null) {
      return;
    }
    if (count != 0) {//增加了新内容,注意count和before的取值范围为>=1

      for (int index = start; index < start + count; index++) {

        if ((char) (byte) s.charAt(index) != s.charAt(index)) {//判断输入的是不是中文
          mCurrentLength += 2;
        } else {
          mCurrentLength += 1;
        }
        
        if (mCurrentLength > mMaxLength) {//输入的字符长度大于最大长度
          mEditText.removeTextChangedListener(this);

          String leftString = s.subSequence(0, index).toString();//获取最大合法长度的内容
          mEditText.setText(leftString);
          mEditText.setSelection(index);

          mEditText.addTextChangedListener(this);

          if ((char) (byte) s.charAt(index) != s.charAt(index)) {
            mCurrentLength -= 2;
          } else {
            mCurrentLength -= 1;
          }
          return;
        }//end mCurrentLength > mMaxLength
      }// end for
    }//end count != 0

    mCurrentLength = 0;
	//重新计算当前的总长度
    char[] chars = s.toString().toCharArray();
    for (int i = 0; i < chars.length; i++) {
      if ((char) (byte) chars[i] != chars[i]) {
        mCurrentLength += 2;
      } else {
        mCurrentLength += 1;
      }
    }
  }

  @Override public void afterTextChanged(Editable s) {

  }
}
注意
       mEditText.removeTextChangedListener(this);//如果不remove setText会再次调用TextWatcher 造成递归
          mEditText.setText(leftString);
          mEditText.addTextChangedListener(this);

###思路
在onTextChanged中,我们首先判断是不是增加了内容,如果不是,直接统计最新的长度,如果是则循环遍历每个字符,并且判断每个字符是中文还是英文。如果遍历到某个字符时,长度超过了限制的大小则生成新的字符串,新的字符串为改变后的字符串裁剪到超过限制的前一个字符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值