Это аналогичная, но несколько иная проблема, чем вопрос, который я задал здесь: Когда мой источник InputFilter входит в состав spannable, источник не удаляет символы, которые я отфильтрую
В моем примере я делаю входной фильтр для проверки канадских почтовых индексов.
У меня есть аннотация здесь:
abstract class MyInputFilter : InputFilter {
protected abstract fun String.isValid(): Boolean
private fun getFinalResultOfChange(source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int): CharSequence {
return dest.replaceRange(dstart, dend, source.subSequence(start, end))
}
private fun getNoChangeResult(source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int): CharSequence {
val initialSubSequence = dest.subSequence(dstart, dend)
return try {
if (source is Spanned) {
val spannable = SpannableString(initialSubSequence)
TextUtils.copySpansFrom(source, start, end, null, spannable, 0)
spannable
} else {
initialSubSequence
}
} catch (e: Exception) {
initialSubSequence
}
}
override fun filter(source: CharSequence?, start: Int, end: Int, dest: Spanned?, dstart: Int, dend: Int): CharSequence? {
if (source == null || dest == null) {
return null
}
val input = getFinalResultOfChange(source, start, end, dest, dstart, dend).toString()
return if (input.isValid()) {
null // Allow the edit to proceed unchanged.
} else {
getNoChangeResult(source, start, end, dest, dstart, dend)
}
}
}
, которую я наследую и переопределяю isValid для всех моих входных фильтров. Этот фильтр ... странный, но появился на основе вопроса, связанного выше, и несколько решил проблему, которая у меня была.
Это наивно из-за моего намерения быть преднамеренным, но вот фильтр CAN:
private val patterns = listOf(
"^(?!.*[DFIOQUdfioqu])[A-VXYa-vxy]$",
"^(?!.*[DFIOQUdfioqu])[A-VXYa-vxy][0-9]$",
"^(?!.*[DFIOQUdfioqu])[A-VXYa-vxy][0-9][A-Za-z]$",
"^(?!.*[DFIOQUdfioqu])[A-VXYa-vxy][0-9][A-Za-z][0-9]$",
"^(?!.*[DFIOQUdfioqu])[A-VXYa-vxy][0-9][A-Za-z][0-9][A-Za-z]$",
"^(?!.*[DFIOQUdfioqu])[A-VXYa-vxy][0-9][A-Za-z][0-9][A-Za-z][0-9]$"
)
override fun String.isValid(): Boolean {
return when (length) {
0 -> true
1, 2, 3, 4, 5, 6 -> this.matches(Regex(patterns[length - 1]))
else -> false
}
}
Теперь у меня новая проблема. Если самый первый введенный символ является недопустимой буквой, клавиатура продолжает загружать символы в «слово» и пытается повторно отправить их. Поэтому, если я наберу
D
, ничего не будет введено правильно. Но, если я наберу
DA
, все равно ничего не будет введено, и мой телефон попытается автоматически предложить слово «da». Если я не щелкну предложенное слово или клавишу возврата, чтобы очистить, поле НЕ будет принимать никаких вводимых данных, но клавиатура будет продолжать «ставить в очередь» слово со всеми набранными мной буквами. Если я введу плохой символ в ЛЮБУЮ ДРУГУЮ позицию, пока первый символ был принят, это работает. Телефон не начинает «ставить в очередь» слово на клавиатуре, и я могу сразу ввести правильный символ.
Также важно: цифры не вызывают проблемы. Клавиатура не пытается начать «строить» слово из числа, поэтому, если я наберу
1A
, то в поле вводится «A» без проблем.
Я могу почти ни у кого не было таких проблем с фильтрами ввода и включаемым, а не включаемым вводом CharSequence, но клавиатура строит слово и пытается передать все так, как я не понимаю. Я попробовал это на GBoard на OnePlus 6T, а также на стандартной клавиатуре Samsung Samsung Tab E по умолчанию, так что это не похоже на отдельную ошибку клавиатуры.