我的解决方案与其他解决方案很相似,只是我使用视图绑定对其进行了自定义旋转
我创建了以下 TextWatcher
class ControlledTextWatcher(
private val parent: TextView,
private val onChange: ((text: CharSequence?, start: Int, before: Int, count: Int) -> Unit)?,
private val beforeChange: ((text: CharSequence?, start: Int, count: Int, after: Int) -> Unit)? = null,
private val afterChange: ((editable: Editable?) -> Unit)? = null
) : TextWatcher {
init {
parent.addTextChangedListener(this)
}
private var enabled = true
var text: String?
get() = parent.value
set(value) {
this.enabled = false
parent.text = value
this.enabled = true
}
var res: Int
get() = throw RuntimeException("String resource cannot be retrieved after being set")
set(value) {
parent.text = parent.context.getString(value)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
if (enabled)
beforeChange?.invoke(s, start, count, after)
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (enabled)
onChange?.invoke(s, start, before, count)
}
override fun afterTextChanged(s: Editable?) {
if (enabled)
afterChange?.invoke(s)
}
fun detach() {
parent.removeTextChangedListener(this)
}
}
我主要将它用于像这样的视图绑定
类 TestActivity : AppCompatActivity() {
class TestActivity : AppCompatActivity() {
private lateinit var binding: ActivityTestBinding
private val edit by lazy { ControlledTextWatcher(binding.text, this::textChanged }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTestBinding.inflate(layoutInflater)
setContentView(binding.root)
}
所以当我希望更改实际的EditText 时,我会使用ControlledTextWatcher 的text 或res 属性,如下所示:
edit.text = "hello world" //this does not trigger the text watcher
但是当用户改变EditText时它会触发
不幸的是,如果您想更改 EditText 的其他参数,则使用此解决方案很遗憾,您要么必须通过绑定获取原始 EditText,要么将这些函数复制到 ControlledTextWatcher
您在afterChange 中进行更改时也必须小心,因为更改已发布到TextView,因此您可能会陷入无限循环