Во-первых, вам нужно создать макет XML, который имеет и EditText, и 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>
Это выложит все правильно, с хорошим EditText над ListView. Затем создайте 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
содержат объект, который можно использовать для автоматической фильтрации. Нам просто нужно передать данные из EditText
в Filter
. Оказывается, это довольно легко. Чтобы выполнить быстрый тест, добавьте эту строку в свой onCreate()
звонок
adapter.getFilter().filter(s);
Обратите внимание, что вам нужно сохранить вашу ListAdapter
переменную, чтобы сделать эту работу - я сохранил свой ArrayAdapter<String>
ранее в переменную под названием «адаптер».
Следующий шаг - получить информацию от EditText
. Это на самом деле занимает немного мысли. Вы можете добавить OnKeyListener()
к своему EditText
. Однако этот слушатель получает только некоторые ключевые события . Например, если пользователь вводит «wyw», предиктивный текст, скорее всего, порекомендует «eye». Пока пользователь не выберет «wyw» или «eye», вы OnKeyListener
не получите ключевое событие. Некоторые могут предпочесть это решение, но я нахожу это разочаровывающим. Я хотел каждое ключевое событие, поэтому у меня был выбор фильтрации или не фильтрации. Решение есть TextWatcher
. Просто создайте и добавьте TextWatcher
к EditText
, и передайте ListAdapter
Filter
запрос фильтра каждый раз, когда текст изменяется. Не забудьте удалить TextWatcher
в 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);
}