在应用开发中,有时需要实现有字数限制的EditText,首先来分析下市面上存在的类似实现方案吧,好有个感性的认识。

【方案一:腾讯微博】

每个中文字符算一个字数,每两个英文字符算一个字数,当用户输入内容时,实时显示剩余的字数,当超出字数限制时,剩余字数显示为负数,但此时用户仍然可以继续在EditText中输入内容,直到用户点击菜单中的“发送”按钮时,才会弹出对话框或者Toast显示用户输入的字数超标,如下图所示:

 

这个方案实现起来很简单,只需要给EditText设置TextWatcher监听器,然后判断输入的是中文字符还是英文字符,实时更新剩余输入字数显示即可,不需要限制EditText的输入。

【方案二:百度旅游】

中英文字符都算一个字数,当用户输入内容时,实时显示剩余的字数,当超出字数限制时,剩余字数显示为0,不会出现负数的情况,这时EditText再也不接收用户输入的任何内容了。

这个方案由于中英文都占一个字数,因此可以直接给EditText设置InputFilter.LengthFilter,这时LengthFilter会自动帮EditText限制用户输入的内容;再给EditText设置TextWatcher监听器,就可以实时更新剩余字数了。

本文综合上面两个方案,给出【方案三】,每个中文字符算一个字数,每两个英文字符算一个字数,当用户输入内容时,实时显示剩余的字数,当超出字数限制时,剩余字数显示为0,不会出现负数的情况,这时EditText再也不接收用户输入的任何内容了。

方案三可用于app需要集成第三方sns分享功能,且必须自己实现分享界面的情况。由于中英文所占的字数不一样,就不能使用LengthFilter来限制用户再EditText中输入内容(因为在用户完成内容输入之前,是不知道要给lengthFilter设置的最大值的)。因此只能在TextWatcher中做些手脚了。方案三界面如下:

 
整个功能的核心实现都在EditText的TextWatcher监听器里面的afterTextChanged回调函数中。代码如下所示:
  1. package com.hust.demo;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.text.Editable;
  5. import android.text.TextWatcher;
  6. import android.widget.EditText;
  7. import android.widget.TextView;
  8. public class MainActivity extends Activity {
  9. private EditText mEditText = null;
  10. private TextView mTextView = null;
  11. private static final int MAX_COUNT = 140;
  12. @Override
  13. protected void onCreate(Bundle savedInstanceState) {
  14. super.onCreate(savedInstanceState);
  15. setContentView(R.layout.main);
  16. mEditText = (EditText) findViewById(R.id.content);
  17. mEditText.addTextChangedListener(mTextWatcher);
  18. mEditText.setSelection(mEditText.length()); // 将光标移动最后一个字符后面
  19. mTextView = (TextView) findViewById(R.id.count);
  20. setLeftCount();
  21. }
  22. private TextWatcher mTextWatcher = new TextWatcher() {
  23. private int editStart;
  24. private int editEnd;
  25. public void afterTextChanged(Editable s) {
  26. editStart = mEditText.getSelectionStart();
  27. editEnd = mEditText.getSelectionEnd();
  28. // 先去掉监听器,否则会出现栈溢出
  29. mEditText.removeTextChangedListener(mTextWatcher);
  30. // 注意这里只能每次都对整个EditText的内容求长度,不能对删除的单个字符求长度
  31. // 因为是中英文混合,单个字符而言,calculateLength函数都会返回1
  32. while (calculateLength(s.toString()) > MAX_COUNT) { // 当输入字符个数超过限制的大小时,进行截断操作
  33. s.delete(editStart - 1, editEnd);
  34. editStart--;
  35. editEnd--;
  36. }
  37. // mEditText.setText(s);将这行代码注释掉就不会出现后面所说的输入法在数字界面自动跳转回主界面的问题了,多谢@ainiyidiandian的提醒
  38. mEditText.setSelection(editStart);
  39. // 恢复监听器
  40. mEditText.addTextChangedListener(mTextWatcher);
  41. setLeftCount();
  42. }
  43. public void beforeTextChanged(CharSequence s, int start, int count,
  44. int after) {
  45. }
  46. public void onTextChanged(CharSequence s, int start, int before,
  47. int count) {
  48. }
  49. };
  50. /**
  51. * 计算分享内容的字数,一个汉字=两个英文字母,一个中文标点=两个英文标点 注意:该函数的不适用于对单个字符进行计算,因为单个字符四舍五入后都是1
  52. *
  53. * @param c
  54. * @return
  55. */
  56. private long calculateLength(CharSequence c) {
  57. double len = 0;
  58. for (int i = 0; i < c.length(); i++) {
  59. int tmp = (int) c.charAt(i);
  60. if (tmp > 0 && tmp < 127) {
  61. len += 0.5;
  62. } else {
  63. len++;
  64. }
  65. }
  66. return Math.round(len);
  67. }
  68. /**
  69. * 刷新剩余输入字数,最大值新浪微博是140个字,人人网是200个字
  70. */
  71. private void setLeftCount() {
  72. mTextView.setText(String.valueOf((MAX_COUNT - getInputCount())));
  73. }
  74. /**
  75. * 获取用户输入的分享内容字数
  76. *
  77. * @return
  78. */
  79. private long getInputCount() {
  80. return calculateLength(mEditText.getText().toString());
  81. }
  82. }

但是上面代码存在一个bug,给EditText设置TextWatcher之后,由于afterTextChanged的代码实现会导致输入法界面刷新,从而使得每次输入字符,输入法界面都会跳转到他的主界面去,

例如我们当我们要输入数字时,首先要转到数字输入界面,正常情况下可以连续输入多个数字,数字输入完成后,界面仍然维持在数字输入界面,输入数字1前后界面对比图(正常情况):

 

而给EditText设置我们定义的Textwatcher监听器之后,在数字输入界面,每输入一个数字,输入法都会跳回主界面,需要用户再点击才能回到数字输入界面,如下图所示(引入的bug),也是输入数字1前后界面对比图:

 
如果有哪位知道怎么解决的,欢迎在评论中予以指出。
附:上面代码中对Editable作操作前,必须先将自身的监听器去使能,否则会引起EditText自身的死循环,从而导致堆栈溢出,将函数afterTextChanged中去掉监听器和添加监听器两行代码注释掉,再次运行程序,在输入内容超出字数限制时,如下代码将被执行到:
  1. while (calculateLength(s.toString()) > MAX_COUNT) { // 当输入字符个数超过限制的大小时,进行截断操作
  2. s.delete(editStart - 1, editEnd);
  3. editStart--;
  4. editEnd--;
  5. }

这时Demo出现Crash,异常信息如下:

Demo源码参见:http://download.csdn.net/detail/ace1985/4757626

Android字数限制的EditText实现方案研究相关推荐

  1. Android字数限制的EditText实现

    在应用开发中,有时需要实现有字数限制的EditText,首先来分析下市面上存在的类似实现方案吧,好有个感性的认识. [方案一:腾讯微博] 每个中文字符算一个字数,每两个英文字符算一个字数,当用户输入内 ...

  2. Android 系统性能优化(30)---Android性能全面分析与优化方案研究

    Android 性能优化 1.结合以下四个部分讲解: 性能问题分类 性能优化原则和方法 借助性能优化工具分析解决问题 性能优化指标 2性能问题分类 1.渲染问题:过度绘制.布局冗杂 2.内存问题:内存 ...

  3. 几乎是史上最全最实用的Android性能全面分析与优化方案研究

    结合以下四个部分讲解: 性能问题分类 性能优化原则和方法 借助性能优化工具分析解决问题 性能优化指标 性能问题分类 1.渲染问题: 过度绘制.布局冗杂 2.内存问题: 内存浪费(内存管理).内存泄漏 ...

  4. Android实战场景 - 限制EditText仅支持输入数字、英文、汉字,禁止输入表情等特殊符号

    因项目需求,需要禁止用户输入表情符号,具体如下 ~ EditText相关Blog TextView.EditText属性大全 监听 EditText 文本变化 设置 EditText 光标颜色与下划线 ...

  5. android app攻击与防范论文,基于Android平台的应用程序安全保护研究与应用

    摘要: 随着Android操作系统的广泛使用和移动互联网时代的到来,Android系统的安全问题也不断出现,给用户和开发者造成了许多困扰.Android应用程序面临着知识产权被侵犯.被二次打包.应用程 ...

  6. Android视频点播-边播边缓存-方案

    Android视频点播-边播边缓存-方案 简述 一些知名的视频app客户端(优酷,爱奇艺)播放视频的时候都有一些缓存进度(二级进度缓存),qq,微信有关的小视频,还有一些短视频app,都有边播边缓的处 ...

  7. android 系统gpu 调试_基于Android系统的GPU动态调频方案 | Imagination中文技术社区

    针对移动终端上GPU的高功耗问题,提出一种基于Android系统的GPU动态调频方案.方案根据各种应用对GPU的性能需求,引入了GPU的频率一性能模型,包括选择工作频率和测量相对性能的方法.动态调频算 ...

  8. Android Q app内存压缩优化方案介绍

    Android Q app内存压缩优化方案介绍 原创文章,谢绝转载! Android Q新增了部分系统性能优化方案,这里简单学习下,本篇文章先分析app compaction. 一.愿景: 在保证后台 ...

  9. Android APP全局黑白化实现方案

    作者:小帅 链接:https://zhuanlan.zhihu.com/p/587516253 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 在清明节时各大APP都 ...

最新文章

  1. android实践项目一实现简单的验证码和spinner下拉选项效果
  2. 网站关键词优化从这几方面下手效果会更好!
  3. 正则验证车牌号码,包括新能源车牌
  4. 在鹅厂当程序媛是什么体验?
  5. 怎么增加android模拟器内存卡,增加android模拟器的内存大小
  6. TTL expired in transit--问题篇~
  7. java中测试计算能力_这 10 道 Java 测试题,据说阿里 P7 的正确率只有 50%
  8. 王道 —— 操作系统的四个特征
  9. asp.net中的post和get请求操作
  10. 关于 2020 年的前端趋势预测
  11. 利用Jquery将表单序列化成JS对象
  12. 2011年最后一小时
  13. 【java学习之路】(java框架)001.Maven配置及使用
  14. Android跳转到拨打电话的页面
  15. Spring生态系统(Spring可能大家都在用,很少去关注整体架构)
  16. Spring Cloud构建微服务架构(五)服务网关 原创 2016-07-12 翟永超 Spring Cloud 被围观 53984 次 通过之前几篇Spring Cloud中几个核心组件的介
  17. 在《寒门状元之死》上,咪蒙贩卖的是什么?
  18. [JZOJ5551] 【NOI2019模拟6.24】旅途【最短路】
  19. 计算机开机密码有几成,电脑密码设置有哪些类型 电脑开机密码忘了怎么解锁...
  20. 阿里巴巴何以超越周期?| 一点财经

热门文章

  1. 实验代做 行人识别_《行人跨模态重识别 | 双向限制的排序损失》
  2. 演示和解析Flex布局中的各种属性
  3. CSS中Position定位属性的使用
  4. lua 函数 默认值_Unity热更新框架之xLua
  5. 20200927:Java和Cpp中栈与队列的区别
  6. php 特殊字符¥,php正则怎么替换符号
  7. php读取西门子plc_AB PLC和西门子PLC之间需要交换数据
  8. 生成对抗网络的损失函数如何设计_如何检测极小人脸?试试超分辨率
  9. 在javascript使用EL表达式注意事项
  10. redis集群内部的带宽消耗