Primero, debe crear un diseño XML que tenga un EditText y un 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>
Esto mostrará todo correctamente, con un agradable EditText encima de ListView. A continuación, cree una ListActivity como lo haría normalmente, pero agregue una setContentView()
llamada en el onCreate()
método para que usemos nuestro diseño recientemente declarado. Recuerde que identificamos el ListView
especialmente, con android:id="@android:id/list"
. Esto permite ListActivity
saber qué ListView
queremos usar en nuestro diseño declarado.
@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());
}
Ejecutar la aplicación ahora debería mostrar tu anterior ListView
, con un bonito cuadro arriba. Para hacer que esa caja haga algo, necesitamos tomar la entrada de ella y hacer que esa entrada filtre la lista. Si bien muchas personas han intentado hacer esto manualmente, la mayoría de las ListView
Adapter
clases vienen con un Filter
objeto que se puede usar para realizar el filtrado de forma automática. Solo necesitamos canalizar la entrada desde EditText
el Filter
. Resulta que es bastante fácil. Para ejecutar una prueba rápida, agregue esta línea a su onCreate()
llamada
adapter.getFilter().filter(s);
Tenga en cuenta que tendrá que guardarlo ListAdapter
en una variable para que esto funcione: he guardado mi ArrayAdapter<String>
de antes en una variable llamada 'adaptador'.
El siguiente paso es obtener la entrada de EditText
. Esto realmente requiere un poco de reflexión. Podrías agregar un OnKeyListener()
a tu EditText
. Sin embargo, este oyente solo recibe algunos eventos clave . Por ejemplo, si un usuario ingresa 'wyw', el texto predictivo probablemente recomendará 'eye'. Hasta que el usuario elija 'wyw' u 'eye', OnKeyListener
no recibirá un evento clave. Algunos pueden preferir esta solución, pero me pareció frustrante. Quería cada evento clave, así que tuve la opción de filtrar o no filtrar. La solución es a TextWatcher
. Simplemente cree y agregue un TextWatcher
a EditText
, y pase ListAdapter
Filter
una solicitud de filtro cada vez que cambie el texto. Recuerde que debe retirar el TextWatcher
de OnDestroy()
! Aquí está la solución final:
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);
}