Dynamically updating an AutoCompleteTextView adapter

后端 未结 5 1547
执笔经年
执笔经年 2020-11-28 23:20

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

相关标签:
5条回答
  • 2020-11-28 23:49

    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

    0 讨论(0)
  • 2020-11-28 23:49

    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.
    
    0 讨论(0)
  • 2020-11-29 00:07

    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;
    }
    }
    
    0 讨论(0)
  • 2020-11-29 00:08

    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.

    0 讨论(0)
  • 2020-11-29 00:10

    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);
    
    0 讨论(0)
提交回复
热议问题