You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 03:45:07