Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 117293|回复: 0

Android EditText输入字数限制总结(包含中文输入内存溢出的解决方法)

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-4-7 03:50:37 | 显示全部楼层 |阅读模式


    转载请注明,大飞:http://blog.csdn.net/rflyee/article/details/38856539

    限定EditText输入个数的解决方式非常多,可是一般主要考虑两点。也就是处理两件事:
    (1)不同语言字符(英文、中文等)处理方式
    (2)输入字符达到数目后,是否仍然同意用户输入

    第一点,涉及的东东事实上蛮多,不同语言在不同编码中占领字节数等,不同语言在U8等编码的表示范围等,这一整块知识非常丰富,自己临时没有理的特别顺。稍后整理再说吧。

    第二点。眼下主流app的处理方案也各有不同,qq5.0曾经的版本号,发表说说貌似是没有字数限制的(我试了一个350字左右的照样发),5.0以后限制了,这样假设用户输入字数超过限制便显示负数,可是仍然同意用户输入,就是不能发表了。这样就把处理权所有交给用户了,事实上更省事了!


    实现吧。



    方法一:
    布局中限制。

    android:maxLength="10"  // 即限制最大输入字符个数为10。
    (1)中英文都算一个字符。


    (2)字数到,不能输入

    方法二:
    InputFilter限制,同布局中限制类似。

    editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(10)});
    (1)中英文都算一个字符。


    (2)字数到。不能输入

    方法三:
    TextWatcher限制。

    这里假设字数达到限制仍然同意用户输入的情况不多说,好实现。


    crash问题:使用搜狗输入法时,在字数将要或者已经达到限制之后,一次输入大量中文(不按空格,一直打字。知道搜狗的缓存字符达到上限)。 crash。stackoverflow 内存溢出。呵呵,百度输入法不会哈。


    解决:监听器中动态去除、加入就ok了。见下边方案一

    方案一,中文按两个,英文按一个。个数到限制,用户不能输入
    private TextWatcher textWatcher = new TextWatcher() {
        private int editStart;
        private int editEnd;
        private int maxLen = 10; // the max byte
    	@Override
    	public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    		Log.d("TextChanged", "---->beforeTextChanged : start = " + start + " count = " + count + " after = " + after);
    	}
    
    	@Override
    	public void onTextChanged(CharSequence s, int start, int before, int count) {
    	}
    
    	@Override
    	public void afterTextChanged(Editable s) {
    		editStart = opinion.getSelectionStart();
    		editEnd = opinion.getSelectionEnd();
    		// 先去掉监听器,否则会出现栈溢出
    		opinion.removeTextChangedListener(textWatcher);
    		if (!TextUtils.isEmpty(opinion.getText())) {
    			String etstring = opinion.getText().toString().trim();
    			while (calculateLength(s.toString()) > maxLen) {
    				s.delete(editStart - 1, editEnd);
    				editStart--;
    				editEnd--;
    				Log.d("TextChanged", "editStart = " + editStart + " editEnd = " + editEnd);
    			}
    		}
    
    		opinion.setText(s);
    		opinion.setSelection(editStart);
    
    		// 恢复监听器
    		opinion.addTextChangedListener(textWatcher);
    		// end by zyf --------------------------
    	}
    	private int calculateLength(String etstring) {
    		char[] ch = etstring.toCharArray();
    
    		int varlength = 0;
    		for (int i = 0; i < ch.length; i++) {
    			// changed by zyf 0825 , bug 6918,增加中文标点范围 , TODO 标点范围有待详细化
    			if ((ch >= 0x2E80 && ch <= 0xFE4F) || (ch >= 0xA13F && ch <= 0xAA40) || ch >= 0x80) { // 中文字符范围0x4e00 0x9fbb
    				varlength = varlength + 2;
    			} else {
    				varlength++;
    			}
    		}
    		Log.d("TextChanged", "varlength = " + varlength);
    		// 这里也能够使用getBytes,更准确嘛
            // varlength = etstring.getBytes(CharSet.forName("GBK")).lenght;// 编码依据自己的需求,注意u8中文占3个字节...
    		return varlength;
    	}
    };


    补加:

    事实上在字符超出的情况下不一个一个删。而是将多余字符一次性全删掉。就可以避免内存溢出的问题,例如以下面方式。(暂未在afterTextChanged处理验证。可自行尝试,兴许补上)。方案二同理,仅仅只是处理截取方式不同罢了。(注:中英字符问题如以上方案自行处理)

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    String str = s.toString();
    if (length > maxNum) {
    ToastUtil.show(mContext, "超出字数限制!");
    str = str.substring(0, maxNum);
    etContent.setText(str);
    etContent.setSelection(str.length());
    }
    }



    方案二
    // 达到限制字数后,假设在文字中间输入文字或者空格。最后的字符会被删除
    titleTv.addTextChangedListener(new TextWatcher() {
    
    	@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) {
    		 // add by zyf 0825 . 多余的从新输入的位置删除,而不是最后
    		   editStart = opinion.getSelectionStart();
    		   editEnd = opinion.getSelectionEnd();
    
    		if (!TextUtils.isEmpty(titleTv.getText())) {
    			int varlength = 0;
    			int size = 0;
    			String etstring = titleTv.getText().toString().trim();
    			char[] ch = etstring.toCharArray();
    			for (int i = 0; i < ch.length; i++) {
    				size++;
    				if (ch >= 0x4e00 && ch <= 0x9fbb) {
    					varlength = varlength + 2;
    				} else
    					varlength++;
    				if (varlength > 80) {
    					break;
    				}
    			}
    			if (varlength > 80) {
    				 s.delete(size - 1, etstring.length());
    				 // add by zyf 0825 . 多余的从新输入的位置删除,而不是最后
    				 // s.delete(editStart - 1, editEnd); // crash stackoverflow,解决方法參考上边方案一
    			}
    		}
    	}
    
    }); 


    转载请注明,大飞: http://blog.csdn.net/rflyee/article/details/38856539



    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-29 13:44 , Processed in 0.070726 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表