In a recent app I wanted to have an autocomplete text field which offers suggestions in a dropdown, with the suggestions appearing as soon as the user starts typing and also able to be cleared by the tapping on a button within the text field.
Here's how I did it.
If you use the standard AutoCompleteTextView from Android, the autocomplete suggestions only start appearing once the text in the field has reached the setThreshold value. This wasn't enough for me, since the documentation states "When threshold is less than or equals 0, a threshold of 1 is applied." - ie, the user must type at least one character before suggestions appear.
The solution is to extend the AutoCompleteTextView class, and to specifically override:
a) the enoughToFilter() method to always return true;
b) the onFocusChanged() method to always perform filtering when focused;
Here's what the code looks like. I keep this in a InstantAutoComplete.java class under main/elements.
package my.package.name;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.AutoCompleteTextView;
public class InstantAutoComplete extends AutoCompleteTextView {
public InstantAutoComplete(Context context) {
super(context);
}
public InstantAutoComplete(Context arg0, AttributeSet arg1) {
super(arg0, arg1);
}
public InstantAutoComplete(Context arg0, AttributeSet arg1, int arg2) {
super(arg0, arg1, arg2);
}
@Override
public boolean enoughToFilter() {
return true;
}
@Override
protected void onFocusChanged(boolean focused, int direction,
Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if (focused) {
performFiltering(getText(), 0);
}
}
}
With this class created, I can now add this element within my layout file. In this case, I added this element to a layout file called preference.xml like so:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<my.package.name.elements.InstantAutoComplete
android:id="@+id/pref_location_autocomplete"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:padding="10dp"
android:inputType="text"
android:completionThreshold="0"
android:drawableRight="@drawable/ic_text_field_clear_btn"
/>
<!-- Rest of layout -->
<LinearLayout>
Note the drawableRight icon I added to the element, which is the small cross you see in the first screenshot.
I was using this autocomplete field in a SettingsActivity, so there were 2 things I had to do in the onCreate method of this activity. These were to set the data which will be shown as autocomplete suggestions, via an adapter, and secondly to clear the field if the user taps anywhere within it. The SettingsActivity code looks like this:
package my.package.name;
import my.package.name.elements.InstantAutoComplete;
import android.preference.PreferenceActivity;
import android.widget.ArrayAdapter;
// other imported classes
public class SettingsActivity extends PreferenceActivity
implements Preference.OnPreferenceChangeListener {
private static final String[] COUNTRIES = new String[] {
"Sydney, CA", "Sydney, AU", "France", "Italy", "Germany", "Spain"
};
private static ArrayAdapter mCityAdapter;
private static InstantAutoComplete mAutoCompleteLocation;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preference);
// ---- [SNIP]some other setup code[/SNIP] --//
// Setup autocomplete
mAutoCompleteLocation = (InstantAutoComplete) findViewById(R.id.pref_location_autocomplete);
mCityAdapter = new ArrayAdapter(
getBaseContext(),
android.R.layout.simple_dropdown_item_1line,
COUNTRIES
);
mAutoCompleteLocation.setAdapter(mCityAdapter);
// Clear autocomplete
mAutoCompleteLocation.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mAutoCompleteLocation.setText("");
}
});
}
}
What happens here is that I add the list of items in COUNTRIES as the objects for the mCityAdapter, which is then set as the adapter for the autocomplete text field. I also set a click listener so that if the user taps anywhere in the text field, it gets cleared. (Note this is not specifically tapping on the clear text icon on the right - to do so would involve setting a separate button in the layout and was not necessary in this case.)
That's all there is to it. In this particular example, I ended up adding other listeners for when a suggestion item gets selected etc but most of that is standard AutoCompleteTextView stuff.