Dynamically updating an AutoCompleteTextView adapter

45,983

Solution 1

This is how I update my AutoCompleteTextView:

String[] data = terms.toArray(new String[terms.size()]);  // terms is a List<String>
ArrayAdapter<?> adapter = new ArrayAdapter<Object>(activity, android.R.layout.simple_dropdown_item_1line, data);
keywordField.setAdapter(adapter);  // keywordField is a AutoCompleteTextView
if(terms.size() < 40) keywordField.setThreshold(1); 
else keywordField.setThreshold(2);

Now of course, this is static and doesn't deal with an over-the-air suggestions but, I can also suggest you to notify adapter for the changes after you assign it to the AutoCompleteTextView:

adapter.notifyDataSetChanged();   

Hope this helps.

-serkan

Solution 2

I didn't have any luck using adapter.notifyDataSetChanged() when dynamically adding and changing the data in the adapter. In my situation, I was hitting an external api asynchronously and getting a list of completion data periodically.

This code clears the adapter, and adds the new data as you'd expect. However, I had to call the getFilter().Filter method to force the data to show. Also, I had to explicitly filter based on the current text in the AutocompleteTextView because my api call was asynchronous.

adapter.clear();
for (Map<String, String> map : completions) {
     adapter.add(map.get("name"));
}

//Force the adapter to filter itself, necessary to show new data.
//Filter based on the current text because api call is asynchronous. 
adapter.getFilter().filter(autocompleteTextView.getText(), null);

Solution 3

The best solution I found for updating the adapter:

Editable text = autocomplete.getText();
autocomplete.setText(text);
autocomplete.setSelection(text.length());

How it works:

We set the text of autoCompleteTextView with its current text, so the adapter notifies that data is changed and updates the listViews's content.

But by this trick the cursor moves to the beginning of edittext. so we use autocomplete.setSelection(text.length()) for moving the cursor to the end.

Works like a charm!

Edit:

Also you must use clear(), add() and remove() methods directly on your ArrayAdapter instead of your ArrayList.

Solution 4

Since i am not able to add a comment, i am giving a new answer There is no need for clearing the adapter or calling adapter.getFilter().filter(...)... To dynamically update an AutoCompleteTextView adapter, simply add the new item to the adapter and setAdapter again. For the example given in the original question, i tried the following and it works (the code below does not show the initial setting of the adapter, since multiple answers here cover that. This just shows updating the adapter dynamically). The adapter update can be alongside the code that updates the List associated with the ArrayAdapter.

    adapter.add(String newSuggestion); // this goes inside a loop for adding multiple suggestions
    speciesName.setAdapter(adapter) ; // speciesName is an AutoCompleteTextView as given in the original question.
Share:
45,983
jaybee
Author by

jaybee

Updated on August 13, 2020

Comments

  • jaybee
    jaybee over 3 years

    I want to periodically change the suggestions given by an AutoCompleteTextview by getting the list from a RESTful web service, and can't get it working smoothly. I set up a hard-coded list of suggestions to make sure it's working:

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, new String[] {"Hi", "Ho"});
    speciesName.setAdapter(adapter);//my autocomplete tv
    

    I have got a TextWatcher on the textview and when the text changes that launches a non-blocking call to get a new list of suggestions -- this part which gets a new list is working fine. Then I want to reset the adapter, like so:

    public void setOptionsAndUpdate(String[] options) {
        Log.d(TAG, "setting options");
        //speciesName.setAdapter((ArrayAdapter<String>)null);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, options);
        speciesName.setAdapter(adapter);
    }
    

    This method is called, but doesn't work -- the list of suggestions either disappears or the displayed suggestions remain unchanged despite the call to setAdapter.

    Is this even the right approach? I looked at SimpleCursorAdapter but couldn't see how to register my web service as a content provider. (It's of the form http://www.blah.com/query?term=XX, where the XX is the input from my app, and the response is a JSON Array of strings.)

  • Luis A. Florit
    Luis A. Florit over 11 years
    @serkan: Great, this is what I needed. However, I think the threshold is not updated, right? So in your example, if terms.size() < 40 at the beginning, the threshold will stay in 1 forever. Of course you can run that line of code again to update. Thanks!
  • serkanozel
    serkanozel over 11 years
    Thanks Luis. Well, what I'm doing there is just saying, if I have a small list of things, I can start suggesting even after 1 character's entered; however if my pool is large, then, I should wait until two characters are entered for me to suggest anything - for efficiency purposes. You certainly keep it 1, or 2 at all times.
  • kassim
    kassim about 9 years
    instead of passing in null you can pass in the autocompleteTextView to have it behave in the same way that AutoCompleteTextView.performFiltering() does - which is the method usually called after the text is changed
  • Dũng Trần Trung
    Dũng Trần Trung over 8 years
    Spending hours searching for this. I own you a beer :)
  • Matt
    Matt about 5 years
    I tried many different solutions, but this one was the only solution that worked for me.
  • Денис Чорный
    Денис Чорный over 3 years
    this is the best solution for this sort of problem! Meny thanks!
  • RedGlyph
    RedGlyph over 2 years
    That's the only way I could get an update of the autocompletion list after updating it from within doAfterTextChanged, where I asynchronously fetch the relevant list from a DB query. And it avoids creating an adapter each time. Thanks!