Building an autocomplete form that only accepts some values
A really common use case that doesn’t have an amazing out of the box solution is an auto complete textbox that needs to be constrained to a finite set of values. One example we have during our registration is choosing the nearest primary school to our farmer.
While it’s not immediately obvious whether you should be using filters, special adapters or array validators it’s actually rather easy to build a solution that works quite well for relatively small numbers of inputs.
We create a new view that extends AutoCompleteTextView. Since there’s no default constructor for AutoCompleteTextView, we end up extending all of the constructors. It’s quite likely that only some of these need to be overridden, but since the simplest ( super(context)) did not work, and the more complex constructors are hidden behind various min android SDKs, I kept it simple and overrode all of them.
Then we want to build an AutoCompleteTextView.Validator, which is called to determine 1) if the text is valid and 2) if it’s not valid, to try and convert the text to valid text.
To implement #1, we implement public boolean isValid(CharSequence charSequence)
Now, all you need to do is attach this validator to the AutoCompleteTextView anytime the adapter is set. Overriding the setAdapter method and we’re nearly done.
At this point, you have a perfectly functioning, if still slightly unfriendly AutoCompleTextView. The painful bit here is that even if the casing is off in the text, the filter will interpret this as invalid and will wipe the input after the user loses focus on the field. While matching the user’s attempt at an input to the input item is probably domain specific, here’s a simple example that ignores case errors.
If your needs extend beyond basic matching, it may be worth looking into implementing a more complex matcher. For example, you could use Levenshtein Distance to compute the difference between the inputs and the canonical version and decide if they’re close enough together. Things get complicated quickly with more sophisticated approaches, as you may have multiple matches for your data set.
Putting it all together, here is a complete version of the code.