如何在 Android 上动态更新 ListView
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1737009/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to dynamically update a ListView on Android
提问by Hamy
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?
在 Android 上,如何ListView
根据用户输入进行过滤,其中显示的项目根据TextView
值动态更新?
I'm looking for something like this:
我正在寻找这样的东西:
-------------------------
| Text View |
-------------------------
| List item |
| List item |
| List item |
| List item |
| |
| |
| |
| |
-------------------------
回答by Hamy
First, you need to create an XML layout that has both an EditText, and a ListView.
首先,您需要创建一个同时具有 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>
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.
这将正确布置所有内容,在 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());
}
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, mostListView
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
现在运行应用程序应该会显示你之前的ListView
,上面有一个漂亮的框。为了让那个盒子做某事,我们需要从中获取输入,并使该输入过滤列表。虽然很多人都尝试过手动执行此操作,但大多数ListView
Adapter
类都带有一个Filter
可用于自动执行过滤的对象。我们只需要将输入从 管道传输EditText
到Filter
. 事实证明这很容易。要运行快速测试,请将此行添加到您的onCreate()
呼叫中
adapter.getFilter().filter(s);
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'.
请注意,您需要将您ListAdapter
的变量保存到一个变量中才能完成这项工作 - 我已经将ArrayAdapter<String>
之前的变量保存到一个名为“适配器”的变量中。
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:
下一步是从EditText
. 这实际上需要一些思考。你可以OnKeyListener()
在你的EditText
. 然而,这个监听器只接收一些关键事件。例如,如果用户输入“wyw”,则预测文本可能会推荐“eye”。在用户选择“wyw”或“eye”之前,您OnKeyListener
将不会收到关键事件。有些人可能更喜欢这个解决方案,但我发现它令人沮丧。我想要每个关键事件,所以我可以选择过滤或不过滤。解决方案是一个TextWatcher
. 只需创建并添加 aTextWatcher
到EditText
,并在ListAdapter
Filter
每次文本更改时传递过滤器请求。记得把TextWatcher
in去掉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);
}
回答by j7nn7k
running the programm will cause a force close.
运行程序将导致强制关闭。
I swaped the line:
我换了线:
android:id="@+building_list/search_box"
android:id="@+building_list/search_box"
with
和
android:id="@+id/search_box"
android:id="@+id/search_box"
could that be the problem? What is the '@+building_list' for?
这可能是问题吗?'@+building_list' 是干什么用的?
回答by cV2
i had a problem with filtering, that results have been filtered, but not restored!
我在过滤时遇到问题,结果已被过滤,但未恢复!
so before filtering (activity start) i created a list backup.. (just another list, containing the same data)
所以在过滤(活动开始)之前,我创建了一个列表备份..(只是另一个列表,包含相同的数据)
on filtering, the filter and listadapter is connected to the primary list.
在过滤时,过滤器和列表适配器连接到主列表。
but the filter itself used the data from the backuped list.
但是过滤器本身使用了备份列表中的数据。
this ensured in my case, that the list was updated immediately and even on deleting search-term-characters the list gets restored successfully in every case :)
这确保在我的情况下,列表会立即更新,即使删除搜索词字符,列表也会在每种情况下成功恢复:)
thanks for this solution anyways.
无论如何,感谢这个解决方案。