在Android的,哪能一个的ListView
,基于用户的输入,其中显示的项目动态更新的基础上的TextView 价值?
我在寻找这样的事情:
-------------------------
|文本视图|
-------------------------
|列表项|
|列表项|
|列表项|
|列表项|
| |
| |
| |
| |
-------------------------
解决方案
首先,你需要创建一个XML的布局,同时具有一个EditText和一个ListView。
<的LinearLayout
的xmlns:机器人=http://schemas.android.com/apk/res/android
机器人:layout_width =FILL_PARENT
机器人:layout_height =FILL_PARENT
机器人:方向=垂直>
< - !pretty的提示文本,并MAXLINES - >
< EditText上机器人:ID =@ + building_list / search_box
机器人:layout_width =FILL_PARENT
机器人:layout_height =WRAP_CONTENT
机器人:提示=类型过滤
机器人:inputType =文本
机器人:MAXLINES =1/>
<! - 设置高度为0,并让重量参数展开 - >
<! - 请注意,使用默认的ID!这可以让我们使用
ListActivity仍然! - >
< ListView的机器人:ID =@机器人:ID /列表
机器人:layout_width =FILL_PARENT
机器人:layout_height =0dip
机器人:layout_weight =1
/>
< / LinearLayout中>
这将为所有的方法正确,用一个漂亮的EditText在ListView以上。接下来,创建一个ListActivity,你会正常,但在的onCreate()
方法中添加一个的setContentView()
通话等等我们用我们最近宣布的布局。请记住,我们ID'ed的的ListView
特殊,与机器人:ID =@机器人:ID /列表
。这使得 ListActivity
来知道哪些的ListView
我们希望在我们宣布布局时使用。
@覆盖
保护无效的onCreate(包savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.filterable_listview);
setListAdapter(新ArrayAdapter<字符串>(这一点,
android.R.layout.simple_list_item_1,
getStringArrayList());
}
运行应用程序现在应该显示您previous 的ListView
,上面一个漂亮的盒子。为了使该盒子做一些事情,我们需要从它的输入,使该输入过滤列表。虽然很多人都尝试过这样做手工,最的的ListView
适配器
班来了与过滤器
对象,可以用来自动地执行过滤。我们只需要管从的EditText
输入到过滤器
。原来,是pretty的方便。要运行一个快速测试,该行添加到您的的onCreate()
通话
adapter.getFilter()过滤器(S);
请注意,您将需要保存 ListAdapter
给一个变量,使这项工作 - 我救了我的 ArrayAdapter<字符串>
从早期到一个名为适配器的变量。
下一步是从的EditText
获得输入。这实际上需要多一点心思。您可以添加一个 OnKeyListener()
您的EditText
。然而,这种监听器只接收的的一些关键事件的。例如,如果用户输入wyw'时,predictive文本可能会建议眼。直到用户选择或者'wyw'或'眼',你的 OnKeyListener
将不会收到一个关键事件。有些人可能preFER这个解决方案,但我发现它令人沮丧。我想每一个关键事件,让我有过滤或不过滤的选择。该解决方案是一个 TextWatcher
。只需创建并添加 TextWatcher
到的EditText
,并通过 ListAdapter
过滤器
每一次过滤器要求的文字修改。请记住删除 TextWatcher
在的OnDestroy()
!下面是最终的解决方案:
私人的EditText filterText = NULL;
ArrayAdapter<字符串>适配器= NULL;
@覆盖
保护无效的onCreate(包savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.filterable_listview);
filterText =(EditText上)findViewById(R.id.search_box);
filterText.addTextChangedListener(filterTextWatcher);
setListAdapter(新ArrayAdapter<字符串>(这一点,
android.R.layout.simple_list_item_1,
getStringArrayList());
}
私人TextWatcher filterTextWatcher =新TextWatcher(){
公共无效afterTextChanged(编辑S){
}
公共无效beforeTextChanged(CharSequence中,诠释开始,诠释计数,
之后INT){
}
公共无效onTextChanged(CharSequence中,诠释开始,诠释之前,
诠释计数){
。adapter.getFilter()过滤器(S);
}
};
@覆盖
保护无效的onDestroy(){
super.onDestroy();
filterText.removeTextChangedListener(filterTextWatcher);
}
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 |
| |
| |
| |
| |
-------------------------
解决方案
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>
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());
}
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);
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'.
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);
}