【问题标题】:Listview autocomplete列表视图自动完成
【发布时间】:2014-08-27 14:43:45
【问题描述】:

我有一个简单的问题:

我有一个包含这些字符串的 Listview 数据:

String words[] = {
        "man",
        "guy",
        "penny-wise",
        "(just)",

我在 Listview 中添加了一个搜索功能,如下所示:

         * Enabling Search Filter
     * */
    search.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
            // When user changed the Text
            Words.this.adapter.getFilter().filter(cs); {

                lv.setOnItemClickListener(new OnItemClickListener(){

                    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {




                    }

                });

            }


        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                int arg3) {
            // TODO Auto-generated method stub

        }

        @Override
        public void afterTextChanged(Editable arg0) {
            // TODO Auto-generated method stub                          
        }




    });
}

所以,搜索功能运行良好,但我想识别当我从字符串(listview 数据)中键入部分ceratin 单词时,从 penny-wise 项目中作为“明智”,他们不提供 penny-明智的建议应该是(因为它存在于列表视图数据中)

如果我输入只是他们不提供建议...因为我的字符串中有一个 ( )...

我该如何解决这个问题。我是新手。谢谢!!!

【问题讨论】:

  • 那么你的 search 是 AutoCompleteTextView 吗?

标签: android android-listview autocomplete


【解决方案1】:

您需要为适配器创建自己的自定义过滤器。为此,您需要创建自己的自定义适配器类。这不是一件容易的事,尤其是考虑到您是新手。

您没有提到您使用的适配器类型。如果它是 ArrayAdapter,那么最好和最简单的解决方案是使用 Advanced-Adapters 开源库。它有一个等效的适配器,可以轻松地让您自定义过滤逻辑,但是您需要手动处理视图创建。你可以阅读更多关于here的信息。

否则,很多人会告诉您直接扩展 ArrayAdapter 类并覆盖 getFilter() 方法,但这是一个错误的答案。为什么?多种原因。

过滤操作发生在后台线程上。这意味着您需要担心并发问题。这带来了一些问题。一方面,ArrayAdapter 使用的锁没有暴露,使用类实例的锁也没有暴露。这意味着您将需要自己的锁,这会大大增加死锁的风险...为同一组数据设置两个不同的锁是不好的,尤其是因为 ArrayAdapter 在更多地方同步,而不仅仅是过滤器。

ArrayAdapter 使用两个列表来跟踪它的数据:mObjectsmOriginalValues。前者跟踪显示的列表,后者跟踪整个列表以了解何时发生过滤操作。例如,如果您过滤包含 10 个项目的列表以仅显示 1 个,则适配器内部仍需要知道原始 10 个是什么,以便稍后恢复该列表。当只覆盖getFilter() 时,您必须提供这种类似的行为,但存在一个主要问题。 ArrayAdapter 不公开任何一个列表。虽然您可以一次从mObjects 中提取一个项目,但您不能提取整个列表本身。一个常见的解决方案是在使用项目实例化您的自定义适配器时创建另一个列表。

但是,这会带来更多问题,因为有多种方法可以在适配器中添加/删除/更新项目。这意味着您需要重写每个 mutate 方法以确保您的列表与 ArrayAdapter 保持同步。添加您必须考虑适配器是否被进一步过滤的事实使问题复杂化。基本上,您的列表很容易与内部 ArrayAdapter 不同步。

到目前为止,您已经覆盖了 ArrayAdapter 的许多方法,这使得 ArrayAdapter 在很大程度上无关紧要。当您开始跟踪从 ArrayAdapter 派生的自定义类中的数据列表时,您应该停止并从头开始实现自己的适配器。

这就是为什么从BaseAdapter 创建自己的适配器是最佳解决方案的原因。如果您知道自己在做什么,那么做起来并不难……只是真的很痛苦。否则,该开源库会为您完成所有这些工作,同时保留 getView() 方法抽象并公开自定义过滤器逻辑的方法。

【讨论】:

  • 您介意告诉我们为什么覆盖getFilter() 方法会是一个错误的答案吗?
  • 更新了原因的答案。
  • 感谢您的详细解释,尽管我不得不承认我从未遇到过使用getFilter() 方法的问题。 (好吧,我正在做你刚才说的几乎所有事情,即创建第二个列表,处理并发等等)
猜你喜欢
  • 2022-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-03
  • 2017-01-23
  • 1970-01-01
  • 2012-04-04
  • 1970-01-01
相关资源
最近更新 更多