Android Kotlin中EditText自动补小数位时setText引发崩溃求助
解决EditText自动补全两位小数时的TextWatcher无限循环问题
你遇到的崩溃确实是因为setText修改文本后会再次触发onTextChanged,形成无限循环导致的。以下是正确的实现方案:
核心处理思路
- 用布尔标志位控制格式化操作的执行时机,避免监听器被重复触发
- 增加输入合法性校验,防止非数字输入引发崩溃
- 对比格式化前后的文本内容,减少无意义的重复设置
修改后的完整代码
val etTesting = findViewById<EditText>(R.id.etTesting) // 标志位:标记是否正在执行文本格式化,阻断循环触发 var isFormatting = false etTesting.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable?) {} override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { // 正在格式化/输入为空/仅输入小数点时,直接返回 if (isFormatting || s.isNullOrEmpty() || s.toString() == ".") { return } try { // 处理部分区域设置下的逗号小数点格式 val inputStr = s.toString().replace(",", ".") val value = inputStr.toDouble() val formatted = String.format("%.2f", value) // 仅当格式化结果与原输入不同时,才执行设置操作 if (formatted != s.toString()) { isFormatting = true etTesting.setText(formatted) etTesting.setSelection(formatted.length) // 光标保持在文本末尾 isFormatting = false } } catch (e: NumberFormatException) { // 捕获非数字输入异常,避免程序崩溃 e.printStackTrace() } } })
关键细节说明
- 标志位
isFormatting:在执行setText前将其设为true,此时监听器触发会直接返回,阻断循环;操作完成后重置为false,恢复正常监听逻辑。 - 异常捕获:通过
NumberFormatException捕获用户输入非数字内容的情况,避免崩溃。 - 文本对比:只有当格式化后的文本与原输入不一致时才执行设置,减少不必要的UI操作。
内容的提问来源于stack exchange,提问作者dl7754
相关产品推荐
相关产品推荐

