如何在保留字符状态的情况下动态向AutocompleteTextView添加建议

14
问题描述:

我在使用 AutoCompleteTextView 时遇到了一些问题,我需要在每次按键后显示建议。问题在于,建议列表是动态的,就像谷歌的建议功能一样。这意味着,新的建议应该随着用户不断输入而添加,同时还应显示所有匹配的旧建议。

例如

我写下 "te",然后它应该显示之前的建议,比如“test1”和“test2”,以及从 Web API 中获取的新建议。假设 Web API 给出单词 "tea" 和 "tension"。

现在,AutoCompleteTextView 将有 "te" 作为字符串,并显示其下方的所有四个建议。

这正是我要寻找的东西。

看起来很简单,但它显示了奇怪的行为。

我正在使用默认的 ArrayAdapter 类实例,我将它全局声明。

arrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line,suggestions);
word.setAdapter(arrayAdapter);
是一个ArrayList。

当从WebApi获得新结果时,我只是简单地调用

arrayAdapter.notifyDataSetChanged();

刷新与此相关的数据观察器和视图(在我们的情况下是AutoCompleteListView)。

但它会关闭建议功能。

当我不使用 notifyDataSetChanged(); 时,它会显示所有建议,而不管我键入了哪些字符。

我尝试了许多人建议的自定义筛选器,但没有一个对我有帮助,因为我无法使用 notifyDataSetChanged()。

我发布了一张图片以避免混淆。enter image description here

我有一个疑惑,为什么 notifyDataSetChanged(); 没有起作用。我没有使用同一个 ArrayAdapter 实例的其他列表引用。我真的怀疑这是否是一个引用问题。


何时以及如何将网络结果添加到适配器中? - pskink
@pskink:我将它添加到建议中,这是一个ArrayList。然后我调用notifyDataSetChanged()。我在从WebApi获取结果的Asynctask的postExecute()中执行此操作。 - kaushal trivedi
你应该在适配器的Filter的performFilteting/publishResults方法中执行此操作。 - pskink
我还没有尝试过那个。让我去查一下。 - kaushal trivedi
您可以使用现有的过滤器,如CursorFilter及其与CursorAdapter的集成,请参见下面的答案。 - pskink
通过添加维基百科的免费OpenSearch更新了答案。 - pskink
2个回答

19

在onCreate中放置代码是最简单的方法之一:

编辑:添加了维基百科免费的OpenSearch(如果https://en.wikipedia.org不起作用,请尝试http://en.wikipedia.org)。

    AutoCompleteTextView actv = new AutoCompleteTextView(this);
    actv.setThreshold(1);
    String[] from = { "name", "description" };
    int[] to = { android.R.id.text1, android.R.id.text2 };
    SimpleCursorAdapter a = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, null, from, to, 0);
    a.setStringConversionColumn(1);
    FilterQueryProvider provider = new FilterQueryProvider() {
        @Override
        public Cursor runQuery(CharSequence constraint) {
            // run in the background thread
            Log.d(TAG, "runQuery constraint: " + constraint);
            if (constraint == null) {
                return null;
            }
            String[] columnNames = { BaseColumns._ID, "name", "description" };
            MatrixCursor c = new MatrixCursor(columnNames);
            try {
                String urlString = "https://en.wikipedia.org/w/api.php?" +
                        "action=opensearch&search=" + constraint +
                        "&limit=8&namespace=0&format=json";
                URL url = new URL(urlString);
                InputStream stream = url.openStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
                String jsonStr = reader.readLine();
                // output ["query", ["n0", "n1", ..], ["d0", "d1", ..]]
                JSONArray json = new JSONArray(jsonStr);
                JSONArray names = json.getJSONArray(1);
                JSONArray descriptions = json.getJSONArray(2);
                for (int i = 0; i < names.length(); i++) {
                    c.newRow().add(i).add(names.getString(i)).add(descriptions.getString(i));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return c;
        }
    };
    a.setFilterQueryProvider(provider);
    actv.setAdapter(a);
    setContentView(actv, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));

1
嘿, 我找到了解决方案,你在评论中说得对,它帮助我部分解决了问题。 虽然我还有其他问题正在处理中。 我没有尝试这种方法来获得答案,因为我不想为这个单一目的使用数据库。 非常感谢你的全力支持,并给你点赞。 感谢你的所有帮助。 - kaushal trivedi
我不使用任何数据库,数据是从JSON Web服务中读取的。 - pskink
到目前为止,我尝试了很多不同的东西:TextWatcher、AsyncTask等。 这正是我一直在寻找的!我能找到的最好的代码。完美地工作! - Olivier Picault
1
@OlivierP。简单而有效,不是吗?不幸的是,即使他们看到这么简单的解决方案,这里仍有90%的人想要与那些观察者、自定义ArrayAdapters、AsyncTasks等进行斗争,我不知道为什么... - pskink
@pskink 我们其中之一 ^^ 我不知道可以这样做。我很高兴找到了你的代码片段。此外,当你在互联网、StackOverflow等搜索时,你的答案并不是应该被突出显示的那个! - Olivier Picault
@OlivierP。你们其中之一,但你以前没有看到这个解决方案,我正在谈论那些看到它但仍然相信存储在某些POJO和ArrayAdapter中的数据比存储在被CursorAdapter使用的Cursor中的数据“更好”的人。 - pskink

0

您已在ArrayAdapter的子类中实现了自定义过滤器,在perform filter方法中,您需要进行网络调用并从服务器获取数据。您可以将此数据设置在主要的ArrayList中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接