I want to use the android component autocomplete:
https://developer.android.com/reference/android/widget/AutoCompleteTextView
There are some possible values the user can select, but I also want that, the user starts typing and, if there is no match with any of the "possible" optionsm, then, the text the user wrote is also valid. So, to put an example, imagine we have an autocomplete to select favourite fruit, and the options are Banana, Apple, but the user types Pear, then, it should be fine.
For that, I did this:
mAutocompleteTextView = findViewById(R.id.select_fruit_autoCompleteTextView)
mAutocompleteTextView.threshold = 1
val fruitListener = OnFruitSet()
// if the user clicks in one of the options
mAutocompleteTextView.onItemClickListener = fruitListener
// if the user writes a different option
mAutocompleteTextView.addTextChangedListener(fruitListener)
And then, my OnFruitSet private inner class:
private inner class OnFruitSet: AdapterView.OnItemClickListener, TextWatcher {
private val textModified = AtomicBoolean(false)
// this is used to change focus if the user finishes (by clicking on one of the options, or in the go button, next, etc. but it isn't working very good)
private val goToNext = AtomicBoolean(false)
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
// this means that the fruit is an option
listeners.forEach{ it.onFruitSet(parent?.adapter?.getItem(position), true) }
}
override fun afterTextChanged(s: Editable?) {
if (textModified.get()) {
textModified.set(false)
goToNext.set(true)
// right now the user can add new lines, and I want to avoid it.
mAutocompleteTextView.setText(s?.replace("[\n]".toRegex(), ""))
} else {
goToNext.set(false)
}
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val name = if (s?.contains('\n') == true) {
textModified.set(true)
s.replace("[\n]".toRegex(), "")
} else {
s
}
if (!textModified.get()) {
val fruit = if (name.isNullOrEmpty() || name.isNullOrBlank()) {
null
} else {
s.toString()
}
listeners.forEach{ it.onFruitSet(fruit, goToNext.get()) }
}
}
}
There are some corner cases that don't work very good, specially with the \n, and when the user clicks on "Next".
Any hint on how to improve it? or is there any component already doing this?
Thanks
s.replace("[\n]".toRegex(), "")
is called, it is the last thing thatonTextChanged
does (astextModified
is set). Doess.replace
change theCharSequence
itself? \$\endgroup\$