Creating an instant autocomplete field in Android

Jun 2nd, 2015 in  by Michael Cho

How to create an autocomplete text field in Android, which displays suggestions in the dropdown and has a clear button.

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.

The end result looked like this:

Here's how I did it.

Immediate Suggestions

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);
    }
  }

}

 

 

Resource element xml

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.

 

Wire up your adapter

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.

 


Other articles you may like

Debugging mobile apps with Charles proxy
Aug 15th, 2016
Consuming a JSON API - Part 2 (EventBus)
Jul 30th, 2015
Consuming a JSON API - Part 1 (Retrofit)
Jul 15th, 2015
Simple Android utility to parse config files in your app
Jun 19th, 2015
Android swipe to refresh, only at the top of the list
Jun 10th, 2015