有效地操作或捕获 EditText 输入
Manipulate or capture EditText input efficiently
我想要实现的目标
我想将用户输入的每个字符转换为另一个字符并显示在 EditText
。
我做了什么
我的第一个方法是使用 TextWatcher
实现的。
private val textWatcher2 = object : TextWatcher {
private var byUser = true
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 (!byUser) return
byUser = false
val t = this@ManipulatingEditText.text.toString()
val m = convert(t.last())
val s = t.substring(0, t.length - 1) + m
this@ManipulatingEditText.setText("")
this@ManipulatingEditText.setText(s)
this@ManipulatingEditText.setSelection(this@ManipulatingEditText.text!!.length)
byUser = true
}
}
/*This is just an mock of my real implementation. But the same delay occurs*/
fun convert(c: Char) : String {
return c.toString()
}
这是有效的:每个新的输入字符都通过 convert(Char) 函数进行转换。不幸的是,这个解决方案 非常慢 并且 效率低下 。每次输入后都有一个短暂的延迟,您无法快速输入。
此解决方案不适用于生产应用。但是我还没有找到另一个更好的解决方案(通过 RxJava 去抖动或延迟不起作用,因为某些字符被跳过或竞争条件适用)。
如有任何想法、解决方案或帮助,我们将不胜感激。
我改变了一些东西,发现延迟大大降低,但我不能说哪个影响最大(如果有的话):
- 用直接操作
Editable
替换了对 setText
的调用
- 将文本操作从
onTextChanged
回调移至 afterTextChanged
回调,因为这是给我们 Editable
而不是 CharSequence
[=25 的回调=]
简化了决定新文本内容的逻辑——希望这仍然符合您的预期;我对你提供的示例代码有点不清楚
private val textWatcher2 = object : TextWatcher {
private var byUser = true
override fun afterTextChanged(s: Editable?) {
if (!byUser) return
byUser = false
s?.let {
if (s.isNotEmpty()) {
s.replace(s.length - 1, s.length, convert(s.last()))
}
}
byUser = true
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
}
我想要实现的目标
我想将用户输入的每个字符转换为另一个字符并显示在 EditText
。
我做了什么
我的第一个方法是使用 TextWatcher
实现的。
private val textWatcher2 = object : TextWatcher {
private var byUser = true
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 (!byUser) return
byUser = false
val t = this@ManipulatingEditText.text.toString()
val m = convert(t.last())
val s = t.substring(0, t.length - 1) + m
this@ManipulatingEditText.setText("")
this@ManipulatingEditText.setText(s)
this@ManipulatingEditText.setSelection(this@ManipulatingEditText.text!!.length)
byUser = true
}
}
/*This is just an mock of my real implementation. But the same delay occurs*/
fun convert(c: Char) : String {
return c.toString()
}
这是有效的:每个新的输入字符都通过 convert(Char) 函数进行转换。不幸的是,这个解决方案 非常慢 并且 效率低下 。每次输入后都有一个短暂的延迟,您无法快速输入。
此解决方案不适用于生产应用。但是我还没有找到另一个更好的解决方案(通过 RxJava 去抖动或延迟不起作用,因为某些字符被跳过或竞争条件适用)。
如有任何想法、解决方案或帮助,我们将不胜感激。
我改变了一些东西,发现延迟大大降低,但我不能说哪个影响最大(如果有的话):
- 用直接操作
Editable
替换了对setText
的调用 - 将文本操作从
onTextChanged
回调移至afterTextChanged
回调,因为这是给我们Editable
而不是CharSequence
[=25 的回调=] 简化了决定新文本内容的逻辑——希望这仍然符合您的预期;我对你提供的示例代码有点不清楚
private val textWatcher2 = object : TextWatcher { private var byUser = true override fun afterTextChanged(s: Editable?) { if (!byUser) return byUser = false s?.let { if (s.isNotEmpty()) { s.replace(s.length - 1, s.length, convert(s.last())) } } byUser = true } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { } }