NiceAutoCompleteTextView
A standard AutoCompleteTextView, but a bit nicer
What can be nice about an AutoCompleteTextView ?
- It tells you whether the user selected an item from its drop down list, or simply typed some text ignoring auto-complete suggestions.
- It will
performFiltering(CharSequence,int)
immediatelyonTouchEvent(MotionEvent)
. - It is available for download in this Gist :-)
Yes, instead you can setOnItemClickListener(OnItemClickListener)
, and be sure that once called, the user indeed selected an item from the drop down list.
Though, if the user decided to change the text ( on purpose, by mistake or maliciously ), before or after it was selected from the list, then leave focus by, for example, submitting a dialog, or simply skipping on to the next EditText - you'll have to build some text/state validation tests into your code, in order to be sure that the text in a specific EditText was indeed auto-completed by selecting a suggested completion from the displayed drop down list.
It might come out just fine, though NiceAutoCompleteTextView deals with such a scenario internally, already in your input component, thus keeping your code encapsulated and readable.
How do we know that the user selected an item from the drop down list?
By overriding replaceText(CharSequence)
:
@Override
protected void replaceText(CharSequence text) {
super.replaceText(text);
/**
* The user selected an item from the suggested completion list.
* The selection got converted to String, and replaced the whole content
* of the edit box.
*/
mSelectionFromPopUp = true;
}
Secondly, a TextWatcher is added, to watch and reset our indicator, mSelectionFromPopUp
, after some text has changed:
{
addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
/** no-op */
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
/** no-op */
}
@Override
public void afterTextChanged(Editable s) {
mSelectionFromPopUp = false;
}
});
}
To performFiltering(CharSequence,int)
immediately onTouchEvent(MotionEvent)
we need to override two functions:
@Override
public boolean enoughToFilter() {
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (getAdapter() != null) {
performFiltering(getText(), 0);
}
return super.onTouchEvent(event);
}
enoughToFilter()
will always return true
saying "There is no filtering standard; it is always enough to filter."
onTouchEvent(MotionEvent)
will behave exactly the same, except it will execute performFiltering(CharSequence,int)
on the input, when called.
Now, checking if the user selected an item from the drop down list, is simple and elegant:
if (!mNiceAutoCompleteTextView.isSelectionFromPopUp()) {
mNiceAutoCompleteTextView.setError("Not selected from the list!");
}
You're welcome to use the complete source code: