如何在 Android 上动态更新 ListView [英] How to dynamically update a ListView on Android
问题描述
在 Android 上,我如何才能根据用户输入过滤 ListView
,其中显示的项目根据 TextView
值动态更新?
On Android, how can I a ListView
that filters based on user input, where the items shown are updated dynamically based on the TextView
value?
我正在寻找这样的东西:
I'm looking for something like this:
-------------------------
| Text View |
-------------------------
| List item |
| List item |
| List item |
| List item |
| |
| |
| |
| |
-------------------------
推荐答案
首先,您需要创建一个包含 EditText 和 ListView 的 XML 布局.
First, you need to create an XML layout that has both an EditText, and a ListView.
<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,但在 onCreate()
方法中添加一个 setContentView()
调用,以便我们使用我们最近声明的布局.请记住,我们特别使用 android:id="@android:id/list"
对 ListView
进行了 ID.这允许 ListActivity
知道我们想在我们声明的布局中使用哪个 ListView
.
This will lay everything out properly, with a nice EditText above the ListView. Next, create a ListActivity as you would normally, but add a setContentView()
call in the onCreate()
method so we use our recently declared layout. Remember that we ID'ed the ListView
specially, with android:id="@android:id/list"
. This allows the ListActivity
to know which ListView
we want to use in our declared layout.
@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
对象可用于自动执行过滤.我们只需要将来自 EditText
的输入通过管道传输到 Filter
.事实证明这很容易.要运行快速测试,请将此行添加到您的 onCreate()
调用
Running the app now should show your previous ListView
, with a nice box above. In order to make that box do something, we need to take the input from it, and make that input filter the list. While a lot of people have tried to do this manually, most ListView
Adapter
classes come with a Filter
object that can be used to perform the filtering automagically. We just need to pipe the input from the EditText
into the Filter
. Turns out that is pretty easy. To run a quick test, add this line to your onCreate()
call
adapter.getFilter().filter(s);
请注意,您需要将 ListAdapter
保存到一个变量中才能完成这项工作 - 我已将我之前的 ArrayAdapter
保存到一个名为adapter"的变量中'.
Notice that you will need to save your ListAdapter
to a variable to make this work - I have saved my ArrayAdapter<String>
from earlier into a variable called 'adapter'.
下一步是从 EditText
获取输入.这实际上需要一些思考.您可以将 OnKeyListener()
添加到您的 EditText
.然而,这个监听器只接收一些关键事件.例如,如果用户输入wyw",则预测文本可能会推荐eye".在用户选择 'wyw' 或 'eye' 之前,您的 OnKeyListener
将不会收到按键事件.有些人可能更喜欢这个解决方案,但我发现它令人沮丧.我想要每个关键事件,所以我可以选择过滤或不过滤.解决方案是 TextWatcher
.只需创建一个 TextWatcher
并将其添加到 EditText
中,并在每次输入文本时向 ListAdapter
Filter
传递一个过滤器请求变化.记得移除 OnDestroy()
中的 TextWatcher
!这是最终的解决方案:
Next step is to get the input from the EditText
. This actually takes a bit of thought. You could add an OnKeyListener()
to your EditText
. However, this listener only receives some key events. For example, if a user enters 'wyw', the predictive text will likely recommend 'eye'. Until the user chooses either 'wyw' or 'eye', your OnKeyListener
will not receive a key event. Some may prefer this solution, but I found it frustrating. I wanted every key event, so I had the choice of filtering or not filtering. The solution is a TextWatcher
. Simply create and add a TextWatcher
to the EditText
, and pass the ListAdapter
Filter
a filter request every time the text changes. Remember to remove the TextWatcher
in OnDestroy()
! Here is the final solution:
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);
}
这篇关于如何在 Android 上动态更新 ListView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!