160

在 Android 上,如何ListView根据用户输入进行过滤,其中显示的项目根据TextView值动态更新?

我正在寻找这样的东西:

-------------------------
| Text View             |
-------------------------
| List item             |
| List item             |
| List item             |
| List item             |
|                       |
|                       |
|                       |
|                       |
-------------------------
4

3 回答 3

287

首先,您需要创建一个同时具有 EditText 和 ListView 的 XML 布局。

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <!-- Pretty hint text, and maxLines -->
    <EditText android:id="@+building_list/search_box" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="type to filter"
        android:inputType="text"
        android:maxLines="1"/>

    <!-- Set height to 0, and let the weight param expand it -->
    <!-- Note the use of the default ID! This lets us use a 
         ListActivity still! -->
    <ListView android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1" 
         /> 

</LinearLayout>

这将正确布置所有内容,ListView 上方有一个漂亮的 EditText。接下来,像往常一样创建一个 ListActivity,但setContentView()在方法中添加一个调用,onCreate()以便我们使用我们最近声明的布局。请记住,我们ListView特别识别了android:id="@android:id/list". 这允许我们ListActivity知道ListView我们想要在我们声明的布局中使用哪个。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.filterable_listview);

        setListAdapter(new ArrayAdapter<String>(this,
                       android.R.layout.simple_list_item_1, 
                       getStringArrayList());
    }

现在运行应用程序应该会显示你以前ListView的 ,上面有一个漂亮的框。为了让那个盒子做点什么,我们需要从中获取输入,并让那个输入过滤列表。虽然很多人尝试手动执行此操作,但大多数 ListView Adapter类都带有一个Filter可用于自动执行过滤的对象。我们只需要将输入从 管道传输EditTextFilter. 事实证明这很容易。要运行快速测试,请将此行添加到您的onCreate()通话中

adapter.getFilter().filter(s);

请注意,您需要将您的变量保存ListAdapter到一个变量中才能完成这项工作 - 我已将ArrayAdapter<String>之前的变量保存到一个名为“适配器”的变量中。

下一步是从EditText. 这实际上需要一些思考。你可以在OnKeyListener()你的EditText. 然而,这个监听器只接收一些关键事件。例如,如果用户输入“wyw”,则预测文本可能会推荐“eye”。在用户选择“wyw”或“eye”之前,您OnKeyListener将不会收到关键事件。有些人可能更喜欢这个解决方案,但我发现它令人沮丧。我想要每个关键事件,所以我可以选择过滤或不过滤。解决方案是一个TextWatcher. 只需创建 a 并将其添加TextWatcher到,并在每次文本更改时EditText传递a 过滤器请求。ListAdapter Filter记得删除TextWatcherin OnDestroy()!这是最终的解决方案:

private EditText filterText = null;
ArrayAdapter<String> adapter = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.filterable_listview);

    filterText = (EditText) findViewById(R.id.search_box);
    filterText.addTextChangedListener(filterTextWatcher);

    setListAdapter(new ArrayAdapter<String>(this,
                   android.R.layout.simple_list_item_1, 
                   getStringArrayList());
}

private TextWatcher filterTextWatcher = new TextWatcher() {

    public void afterTextChanged(Editable s) {
    }

    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
    }

    public void onTextChanged(CharSequence s, int start, int before,
            int count) {
        adapter.getFilter().filter(s);
    }

};

@Override
protected void onDestroy() {
    super.onDestroy();
    filterText.removeTextChangedListener(filterTextWatcher);
}
于 2009-11-15T09:04:30.850 回答
10

运行程序将导致强制关闭。

我换了行:

android:id="@+building_list/search_box"

android:id="@+id/search_box"

这可能是问题吗?'@+building_list' 是干什么用的?

于 2010-02-07T13:23:37.403 回答
4

我在过滤时遇到问题,结果已被过滤,但未恢复

所以在过滤(活动开始)之前,我创建了一个列表备份..(只是另一个列表,包含相同的数据)

在过滤时,过滤器和列表适配器连接到主列表。

但过滤器本身使用了备份列表中的数据。

这确保了在我的情况下,列表会立即更新,甚至在删除搜索词字符时,列表在每种情况下都会成功恢复:)

无论如何感谢这个解决方案。

于 2011-08-17T08:48:21.433 回答