【Android】设置EditText为仅输入数字且最多只能有两位数字

简介:

需求很简单,就是要设置一个EditText仅能输入数字且输入的数字中小数部分最多可以有两位。

第一步,很简单,在XML文件中,将EditText的inputType设置成NumberDecimal,多余的属性我就不写出来,只写出主要的部分:

<EditText
            。。。
            android:inputType="numberDecimal"
            。。。
 />

第二部,代码中修改EditText 的addTextChangedListener 方法,同样的先上代码,再来解释:

EditText.addTextChangedListener(new TextWatcher() {
	        //    Tips: 
		//    1. onTextChanged和beforTextChanged传入的参数s其实是当前EditText的文字内容,而不是当前输入的内容
		//    2. 如果在任意一个方法中调用了设置当前EditText文本的方法,setText(),实际都触发了一遍这3个函数,
		//       所以要有判断条件,在if体内去setText,而且就需要手动设置光标的位置,不然每次光标都会到最开始的位置
		//    3. onTextChanged中,before=0: 增加;before=1: 点击删除按键
			
		private int count_decimal_points_ = 0;  // 标识当前是不是已经有小数点了
		private int selection_start_;  			// 监听光标的位置
		private StringBuffer str_buf_;			// 缓存当前的string,用以修改内容
		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
			str_buf_ = new StringBuffer(s.toString().trim());
			// 先判断输入的第一位不能是小数点
			if (before == 0 && s.length() == 1 && s.charAt(start) == '.') {
				recharge_money.setText("");
			} else if (before == 0 && count_decimal_points_ == 1) {
			// 在判断如果当前是增加,并且已经有小数点了,就要判断输入是否合法;如果是减少不做任何判断
				// 注意在if语句中都是在else体内调用了设置光标监听位的方法,因为在调用setText之后会出现嵌套的情况
				// 非合法的输入包括: 1. 输入的依旧是小数点,2.小数点后位数已经达到两位了
				if (s.charAt(start) == '.' ||  (start - str_buf_.indexOf(".") > 2) ) {
					str_buf_.deleteCharAt(start);
					recharge_money.setText(str_buf_);
				} else {
					selection_start_ = str_buf_.length();		// 设置光标的位置为结尾
				}
			} else {
				selection_start_ = str_buf_.length();		// 设置光标的位置为结尾	
			}
		}
		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {
			if (s.toString().contains(".")) {
				count_decimal_points_ = 1;
			} else {
				count_decimal_points_ = 0;	// 因为可能存在如果是删除的话,把小数点删除的情况
			}
		}
		@Override
		public void afterTextChanged(Editable s) {
			// 重置光标位置
			recharge_money.setSelection(selection_start_);
			
			if (s != null) {
				try {
					// TODO Your things
				} catch (NumberFormatException e) {
					e.printStackTrace();
				}
			}
		}
		});


 
其实我们看到在listener中是new 了一个TextWatcher类,在TextWatcher类中,其实有3个方法,beforeTextChanged、onTextChanged和afterTextChanged。 从它们的名字中我们也不难看出分别是当text发生变化的时候,要做的处理。 

在类中,我们声明了3个变量,变量的作用我在注释里面也添加了,这里就不啰嗦了。注意的是之所以用StringBuffer来代替String是因为StringBuffer的效率更高,至于为什么,自行Google。

看了一下我的代码,觉得我该说的东西在注释里面都已经写出来了。这里需要特别注意的是,如果在你的类中,你调用了EditText的setText方法,那么就会立即触发TextWatch类,所以,如果你不加if条件判断,而是直接setText,那么就会出现死循环最终内存泄露而崩溃。所以一定要注意,比如你发现用户的输入不合法,要把刚输入的内容删除掉,重新set一下当前EditText的内容,那么一定是在if循环语句中setText。

还有一点也是和这个相关的,就是我开始的时候,在onTextChanged方法中,把设置光标位置的语句放在了if循环体之外,因为我觉得每次不管你是不是满足条件,都要执行一遍重置光标的操作,就出现了bug,后来是打log的时候才发现了,这里我把代码中的log内容省去了。

具体情况我来给大家解释一遍,我们先来看一下我最初的代码:

<pre name="code" class="java">public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				str_buf_ = new StringBuffer(s.toString().trim());
				// 先判断输入的第一位不能是小数点
				if (before == 0 && s.length() == 1 && s.charAt(start) == '.') {
					LogUtil.logMsg("输入错误","第一位不能是小数点");
					recharge_money.setText("");
				} else if (before == 0 && count_decimal_points_ == 1) {
					// 在判断如果当前是增加,并且已经有小数点了,就要判断输入是否合法;如果是减少不做任何判断
					// 注意在if语句中都是在else体内调用了设置光标监听位的方法,因为在调用setText之后会出现嵌套的情况
					// 非合法的输入包括: 1. 输入的依旧是小数点,2.小数点后位数已经达到两位了
					if (s.charAt(start) == '.' ||  (start - str_buf_.indexOf(".") > 2) ) {
						str_buf_.deleteCharAt(start);
						EditText.setText(str_buf_);
					}
				}
selection_start_ = str_buf_.length();		// 设置光标的位置为结尾	
			}


 


 
重点就在最后一行,我在任何时候都会设置光标的位置。我们来看bug是如何产生的: 

加入这时候已经有一串合法的数字123.45写在了EditText中,这个时候光标的位置是6,假设这个时候我们又输入了一个数字6,那么在TextWatch类中,selection_start_实际上变成了7,因为在这个方法中,CharSequence s,也就是str_buf_的长度是7,也就是123.456,然后我们发现已经有了两位小数了,手动设置EditText的setText方法,把它改成了123.45,前面我们说过了,这里会有一个嵌套调用,相当于递归了一下,注意我们的程序在afterTextChanged中要重置光标位置的,bug就出在这里。

我们来画一下流程吧:

123.456 onTextChanged --> 123.45 onTextChanged --> 123.45 afterTextChanged --> 123.456 afterTextChanged

我省去了beforeTextChanged的过程,但是可以看到,我们在循环体的外面是要调用123.456的afterTextChanged方法的,这个方法里面的selection_start_也就是光标位置是7,但是其实,这个时候text的内容已经变成了123.45,那这个text只有6位,你要把光标设置在7,那一定会崩溃的。

所以,因为有嵌套的关系,我们一定要谨慎地处理每一步。


目录
相关文章
|
5月前
|
Android开发
Android经典实战之Textview文字设置不同颜色、下划线、加粗、超链接等效果
本文介绍了 `SpannableString` 在 Android 开发中的强大功能,包括如何在单个字符串中应用多种样式,如颜色、字体大小、风格等,并提供了详细代码示例,展示如何设置文本颜色、添加点击事件等,助你实现丰富文本效果。
383 3
|
5月前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
201 0
|
6月前
|
XML API Android开发
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
本文介绍了如何使用androidx.preference库快速创建具有一级和二级菜单的Android设置界面的步骤和示例代码。
197 1
码农之重学安卓:利用androidx.preference 快速创建一、二级设置菜单(demo)
|
6月前
|
开发工具 Android开发
Android项目架构设计问题之外部客户方便地设置回调如何解决
Android项目架构设计问题之外部客户方便地设置回调如何解决
43 0
|
6月前
|
数据可视化 Java 数据挖掘
Android项目架构设计问题之设置RecyclerView的LayoutManager如何解决
Android项目架构设计问题之设置RecyclerView的LayoutManager如何解决
54 0
|
6月前
|
Java 网络安全 开发工具
UNITY与安卓⭐一、Android Studio初始设置
UNITY与安卓⭐一、Android Studio初始设置
|
7月前
|
XML Android开发 数据格式
Android 中如何设置activity的启动动画,让它像dialog一样从底部往上出来
在 Android 中实现 Activity 的对话框式过渡动画:从底部滑入与从顶部滑出。需定义两个 XML 动画文件 `activity_slide_in.xml` 和 `activity_slide_out.xml`,分别控制 Activity 的进入与退出动画。使用 `overridePendingTransition` 方法在启动 (`startActivity`) 或结束 (`finish`) Activity 时应用这些动画。为了使前 Activity 保持静止,可定义 `no_animation.xml` 并在启动新 Activity 时仅设置新 Activity 的进入动画。
222 12
|
7月前
|
Java Android开发
android 设置系统时间的流程
android 设置系统时间的方法
543 2
|
8月前
|
Android开发
Android Studio(2022.3.1)设置阿里云源-新旧版本
Android Studio(2022.3.1)设置阿里云源-新旧版本
1478 1
|
8月前
|
XML Java Android开发
Android RecyclerView用代码动态设置item的selector
Android RecyclerView用代码动态设置item的selector
63 0

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    Android历史版本与APK文件结构
  • 3
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 6
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 7
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 8
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 9
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 10
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 1
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    13
  • 2
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    28
  • 3
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    34
  • 4
    Android历史版本与APK文件结构
    121
  • 5
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    29
  • 6
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    23
  • 7
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
    60
  • 8
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    37
  • 9
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    73
  • 10
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    121