Cómo actualizar dinámicamente una vista de lista en Android [cerrado]


En Android, ¿cómo puedo un ListView que se filtra en función de la entrada del usuario, donde los elementos que se muestran se actualizan dinámicamente en función del valor TextView?

Estoy buscando algo como esto:

-------------------------
| Text View             |
-------------------------
| List item             |
| List item             |
| List item             |
| List item             |
|                       |
|                       |
|                       |
|                       |
-------------------------
Author: Hamy, 2009-11-15

3 answers

Primero, debe crear un diseño XML que tenga un EditText y una 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 colocará todo correctamente, con un bonito EditText encima de la ListView. A continuación, cree una ListActivity como lo haría normalmente, pero agregue una llamada setContentView() en el método onCreate() para que utilicemos nuestro diseño declarado recientemente. Recuerda que identificamos el ListView especialmente, con android:id="@android:id/list". Esto permite a 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());
    }

Ejecutando la aplicación ahora debe mostrar su anterior ListView, con un buen cuadro de arriba. Para hacer que esa caja haga algo, necesitamos tomar la entrada de ella y hacer que esa entrada filtre la lista. Mientras que mucha gente ha intentado hacer esto manualmente, la mayoría ListView Adapter las clases vienen con un objeto Filter que se puede usar para realizar el filtrado automáticamente. Solo necesitamos canalizar la entrada desde el EditText en el Filter. Resulta que es bastante fácil. Para ejecutar una prueba rápida, agregue esta línea a su onCreate() call

adapter.getFilter().filter(s);

Observe que necesitará guardar su ListAdapter en una variable para que esto funcione - He guardado mi ArrayAdapter<String> de antes en una variable llamada 'adapter'.

El siguiente paso es obtener la entrada de EditText. Esto realmente toma un poco de pensamiento. Podrías añadir 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' o 'eye', su 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 un TextWatcher. Simplemente cree y agregue un TextWatcher al EditText, y pase el ListAdapter Filter una solicitud de filtro cada vez que cambia el texto. Recuerde eliminar el TextWatcher en 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);
}
 286
Author: Hamy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-15 10:52:26

Ejecutar el programa causará un cierre de fuerza.

Cambié la línea:

Android: id = "@ + building_list / search_box"

Con

Android: id = "@ + id / search_box "

¿Podría ser ese el problema? ¿Para qué sirve la '@+building_list'?

 10
Author: j7nn7k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-15 11:29:46

Tuve un problema con el filtrado, que los resultados se han filtrado, pero no restaurado!

Así que antes de filtrar (inicio de la actividad) he creado una copia de seguridad de la lista.. (solo otra lista, que contiene los mismos datos)

Al filtrar, el filtro y listadapter están conectados a la lista primaria.

Pero el propio filtro utilizó los datos de la lista de copia de seguridad.

Esto aseguró en mi caso, que la lista se actualizó inmediatamente e incluso al eliminar los caracteres de búsqueda-término la lista se restaura con éxito en todos los casos:)

Gracias por esta solución de todos modos.

 4
Author: cV2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-17 08:48:21