Dynamically updating an AutoCompleteTextView adapter

喜欢而已 提交于 2019-11-26 21:45:16

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

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

There was a pretty good tutorial on this topic using remote data in the Google Map API to populate a AutoCompleteTextView here.

If you need a cached version, I retrieved it from here. The original tutorial has been deleted, but essentially you need to write an ArrayAdapter with a custom filter in a similar way to that shown below and assign it to your AutoCompleteTextView.

Note: You need to implement a method autocomplete() that does whatever operation is required to synchronously fetch and return the autocompletion items. As the filter is invoked in a background thread, this will not block the main UI thread.

private class PlacesAutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
private ArrayList<String> resultList;

public PlacesAutoCompleteAdapter(Context context, int textViewResourceId) {
    super(context, textViewResourceId);
}

@Override
public int getCount() {
    return resultList.size();
}

@Override
public String getItem(int index) {
    return resultList.get(index);
}

@Override
public Filter getFilter() {
    Filter filter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults filterResults = new FilterResults();
            if (constraint != null) {
                // Retrieve the autocomplete results.
                resultList = autocomplete(constraint.toString());

                // Assign the data to the FilterResults
                filterResults.values = resultList;
                filterResults.count = resultList.size();
            }
            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results != null && results.count > 0) {
                notifyDataSetChanged();
            }
            else {
                notifyDataSetInvalidated();
            }
        }};
    return filter;
}
}

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.

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!