11 October 2014

AutoCompleteTextView Hell

Today, I ran into a weird "feature" of Android. I was working on an AutoCompleteTextView with the dropdown list having section dividers. It all works well in portrait mode, but gets all messed up in landscape.

I made a sample app to illustrate the point of this blog [Github repo]. Clone it, run it, rotate the phone, select an item from the suggested auto-complete results, and get your mind blown. Or your heart stabbed. Or your stomach sucker-punched. Your choice.

So what was happening? Here's what.

When we tell the app to perform a filter, we construct an array of the resulting matches. The example is pretty straightforward, just look for countries that start with whatever the user has typed in.

// Filter by start of string
String country = mCountries.get(i);
if(country.toLowerCase().startsWith(constraint.toString().toLowerCase())) {
    mFilteredData.add(country);
}
You can make this filtering as complicated as you like or need, just make sure to pass in whatever the user needs to see.

To illustrate having section headers (aka disabled items), we insert dummy text every fifth place in the list. The sample app does not care if there are more results after a section header, we still insert anyway.

So. Let's filter. Typing in "pa" will give us this set of data:
10-11 02:45:46.028  16282-20011/com.blogspot.droidista.autocompletetextviewhell D/AutoCompleteFragment﹕ 
Filtered results: [Section!, Pakistan, Palestine, Panama, Papua New Guinea, Section!, Paraguay]

There are two sections and five countries. Remember this.
Position in listValue
0Section!
1Pakistan
2Palestine
3Panama
4Papua New Guinea
5Section!
6Paraguay

This screenshot shows how the results are rendered in portrait mode. So far, so good. Selecting an item from the list populates the EditText with the country's name.

Now let's try rotating our phone. This is where things get juicy. First off, there are no section headers. Second, the results are not in alphabetical order anymore. If we debug all over the adapter, we see what is written on the screenshot: Item on the left is position = 1, item in the middle is position = 0, and item on the right is position = 2.

Remember the result set we have? "Pakistan" is definitely NOT in position = 0, it should have been a section header! If we go ahead and select "Pakistan" in the suggestions above the keyboard, the EditText will populate with the item in position = 0 of the result set, i.e. "Section!". Definitely not good.


The AutoCompleteTextView widget has been around since API level 1, but I haven't messed around with it as much as I did today. Googling returns very, very sparse results on this topic.
  • Does this mean people do not have the same problem as I did?
  • No one uses section headers in AutoCompleteTextViews?
  • No one uses this screen mode (EditText in full screen) in landscape without setting IME flags?
  • Is there a secret trick to making this work out-of-the-box?
Or the most plausible of all,
  • Am I being stupid?