Ответ 1
Сначала вам нужно создать 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", предсказательный текст, скорее всего, порекомендует "глаз". Пока пользователь не выберет "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);
}