40

我想通过从 RESTful Web 服务获取列表来定期更改 AutoCompleteTextview 给出的建议,并且无法使其顺利运行。我设置了一个硬编码的建议列表,以确保它正常工作:

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

我在 textview 上有一个 TextWatcher,当文本更改时,它会启动一个非阻塞调用以获取新的建议列表——这部分获取新列表的工作正常。然后我想重置适配器,如下所示:

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

此方法被调用,但不起作用——建议列表要么消失,要么显示的建议保持不变,尽管调用setAdapter.

这甚至是正确的方法吗?我查看了SimpleCursorAdapter但看不到如何将我的网络服务注册为内容提供者。(格式为http://www.blah.com/query?term=XX,其中 XX 是我的应用程序的输入,响应是 JSON 字符串数组。)

4

5 回答 5

57

在适配器中动态添加和更改数据时,我没有任何运气使用 adapter.notifyDataSetChanged() 。在我的情况下,我正在异步访问外部 api 并定期获取完成数据列表。

此代码清除适配器,并按照您的预期添加新数据。但是,我不得不调用 getFilter().Filter 方法来强制显示数据。此外,我必须根据 AutocompleteTextView 中的当前文本显式过滤,因为我的 api 调用是异步的。

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);
于 2013-10-29T19:32:58.607 回答
24

这就是我更新 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);

当然,现在这是静态的,不处理无线建议,但我也可以建议您在将更改分配给 AutoCompleteTextView 后通知适配器:

adapter.notifyDataSetChanged();   

希望这可以帮助。

-serkan

于 2011-11-15T20:49:52.780 回答
24

有一个关于这个主题的非常好的教程,使用谷歌地图 API 中的远程数据来填充 AutoCompleteTextView here

如果您需要缓存版本,我从这里检索了它。原始教程已被删除,但本质上您需要以与下面所示类似的方式编写带有自定义过滤器的 ArrayAdapter,并将其分配给您的 AutoCompleteTextView。

注意:您需要实现一个方法 autocomplete() 来执行同步获取和返回自动完成项所需的任何操作。由于过滤器是在后台线程中调用的,因此不会阻塞主 UI 线程。

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;
}
}
于 2013-06-20T09:29:36.083 回答
2

由于我无法添加评论,因此我给出了新答案 无需清除适配器或调用 adapter.getFilter().filter(...)... 要动态更新 AutoCompleteTextView 适配器,只需添加将新项目添加到适配器并再次 setAdapter。对于原始问题中给出的示例,我尝试了以下并且它有效(下面的代码没有显示适配器的初始设置,因为这里有多个答案涵盖了这一点。这只是显示动态更新适配器)。适配器更新可以与更新与 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.
于 2015-01-30T07:33:51.777 回答
2

我发现更新适配器的最佳解决方案:

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

这个怎么运作:

我们将autoCompleteTextView的文本设置为其当前文本,因此适配器会通知数据已更改并更新 listViews 的内容。

但是通过这个技巧,光标移动到了edittext的开头。所以我们autocomplete.setSelection(text.length())用于将光标移动到末尾。

奇迹般有效!

编辑:

clear()此外,您必须直接在您的add()而不是您的.remove()ArrayAdapterArrayList

于 2018-08-12T11:41:05.643 回答