这里大多数答案的问题是它们都弄乱了光标位置。
- 如果您只是替换文本,您的光标最终会出现在下一个输入字符的错误位置
- 如果您认为您通过将光标放回末尾来处理该问题,那么他们无法添加前缀文本或中间文本,它们总是在每个键入的字符上跳回到末尾,这是一种糟糕的体验。
你有一个简单的方法来处理它,还有一个更通用的方法来处理它。
简单的方法
<EditText
android:id="@+id/itemNameEditText"
android:text="@={viewModel.selectedCartItemModel.customName}"
android:digits="abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
android:inputType="textVisiblePassword"/>
完毕!
可见密码将解决双重回调的问题和类似的问题。此解决方案的问题在于它会删除您的建议和自动完成功能,以及类似的事情。因此,如果您可以摆脱这个方向,请这样做!!!它将消除试图处理所有可能的困难问题的麻烦,哈哈。
艰难的道路
该问题与自动完成触发的 inputfilter 回调结构有关。它很容易复制。只需设置您的 inputType = text,然后输入 abc@,您会看到它被调用了两次,并且如果您试图忽略 @,您最终可以使用 abcabc 而不是 abc。
- 您必须处理的第一件事是删除来执行此操作,您必须返回 null 以接受“”,因为这是由删除触发的。
- 您必须处理的第二件事是保持删除,因为它会经常更新,但可能会以一长串字符的形式出现,因此您需要在替换文本之前查看文本长度是否缩小,否则最终可能会复制文本而持有删除。
- 您需要处理的第三件事是重复回调,通过跟踪先前的文本更改调用以避免获得两次。不用担心,您仍然可以背靠背输入相同的字母,这不会阻止。
这是我的例子。它并不完美,还有一些问题需要解决,但它是一个很好的起点。
以下示例使用数据绑定,但如果这是您的风格,欢迎您只使用不使用数据绑定的 intentFilter。用于仅显示重要部分的缩写 UI。
在此示例中,我仅限制为字母、数字和空格。我能够在疯狂地敲打安卓键盘的同时让一个分号出现一次。因此,我认为仍然需要进行一些调整。
免责声明
--我还没有测试过自动完成
--我没有用建议进行测试
--我没有测试过复制/粘贴
--这个解决方案是一个 90% 的解决方案来帮助你,而不是一个经过实战考验的解决方案
文件
<layout
xmlns:bind="http://schemas.android.com/apk/res-auto"
>
<EditText
bind:allowAlphaNumericOnly="@{true}
对象文件
@JvmStatic
@BindingAdapter("allowAlphaNumericOnly")
fun restrictTextToAlphaNumericOnly(editText: EditText, value: Boolean) {
val tagMap = HashMap<String, String>()
val lastChange = "repeatCheck"
val lastKnownSize = "handleHoldingDelete"
if (value) {
val filter = InputFilter { source, start, end, dest, dstart, dend ->
val lastKnownChange = tagMap[lastChange]
val lastKnownLength = tagMap[lastKnownSize]?.toInt()?: 0
//handle delete
if (source.isEmpty() || editText.text.length < lastKnownLength) {
return@InputFilter null
}
//duplicate callback handling, Android OS issue
if (source.toString() == lastKnownChange) {
return@InputFilter ""
}
//handle characters that are not number, letter, or space
val sb = StringBuilder()
for (i in start until end) {
if (Character.isLetter(source[i]) || Character.isSpaceChar(source[i]) || Character.isDigit(source[i])) {
sb.append(source[i])
}
}
tagMap[lastChange] = source.toString()
tagMap[lastKnownSize] = editText.text.length.toString()
return@InputFilter sb.toString()
}
editText.filters = arrayOf(filter)
}
}