Implementación del widget de la barra de herramientas de Android en ListFragment

Actualmente tengo mi aplicación configurada con un ListFragment a la izquierda y un DetailsFragment a la derecha (similar al diseño de la tableta de abajo).

diseño

En la barra de acción tengo un widget de búsqueda que cuando se envía un término de búsqueda debe actualizar el contenido de la lista (en el ListFragment). He estado siguiendo la guía de búsqueda en android dev ( http://developer.android.com/guide/topics/search/search-dialog.html ) pero estoy teniendo problemas para obtener la búsqueda para actualizar la lista en la misma actividad.

He logrado obtener alguna forma de implementación trabajando llamando a una nueva actividad cuando se envía el término de búsqueda, pero esto hace que el botón de retroceso se comporte de forma extraña (es decir, presiona atrás y se pasa a la actividad anterior con el widget de búsqueda que muestra el término de búsqueda ).

He añadido las líneas de intención al manifiesto como sigue

 <intent-filter> <action android:name="android.intent.action.SEARCH" /> </intent-filter> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/> 

¿Es posible obtener el widget de búsqueda para actualizar la lista de la actividad actual?

Sí, de hecho, ese es el caso de uso "normal". Lo que hay que recordar es que el fragmento que utiliza el widget de barra de acción de búsqueda, debe ser la parte que lo registra en general, ya que el widget se destruirá junto con ese fragmento.

Aquí está cómo atarlo apropiadamente para arriba:

En su ListFragment que se sepa que tiene opciones de menú de opciones …

 @Override public void onActivityCreated(Bundle savedInstanceState) { .. setHasOptionsMenu(true); .. } 

A continuación, dentro del mismo ListFragment crear su menú de opciones mediante la sustitución de la devolución de llamada, una vez que tenga la referencia de widget SearchView, registrar una devolución de llamada QueryTextListener:

 @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.grid_default, menu); SearchView searchView = (SearchView)menu.findItem(R.id.grid_default_search).getActionView(); searchView.setOnQueryTextListener(queryListener); } 

Crear su widget de búsqueda a través de programación (Java) o declarativamente (XML) aquí es XML (llamado grid_default.xml, desde arriba):

 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/grid_default_search" android:icon="@android:drawable/ic_menu_search" android:title="search" android:showAsAction="always" android:actionViewClass="android.widget.SearchView" /> <!-- other items or whatever --> </menu> 

Ahora en tu ListFragment necesitas crear el queryListener registrado arriba:

 private String grid_currentQuery = null; // holds the current query... final private OnQueryTextListener queryListener = new OnQueryTextListener() { @Override public boolean onQueryTextChange(String newText) { if (TextUtils.isEmpty(newText)) { getActivity().getActionBar().setSubtitle("List"); grid_currentQuery = null; } else { getActivity().getActionBar().setSubtitle("List - Searching for: " + newText); grid_currentQuery = newText; } getLoaderManager().restartLoader(0, null, MyListFragment.this); return false; } @Override public boolean onQueryTextSubmit(String query) { Toast.makeText(getActivity(), "Searching for: " + query + "...", Toast.LENGTH_SHORT).show(); return false; } }; 

Ahora sabes cuando una consulta se cambia o se envía, en mi ejemplo, vuelvo a consultar en cualquier momento una tecla se presiona porque mi base de datos era pequeña y rápida con los resultados, es posible que tenga que cambiar esto .. pero te darás cuenta de cómo estoy Simplemente usando el widget para establecer un campo de clase privada dentro del ListFragment al texto actual del widget de búsqueda ( grid_currentQuery ) y luego solo llamo a getLoaderManager().restartLoader(0, null, MyListFragment.this); Donde dentro de mi onCreateLoader sólo estoy actualizando la consulta que usé así:

 @Override public Loader<Cursor> onCreateLoader(int id, Bundle bargs) { String sort = "SortColumn ASC"; String[] grid_columns = new String[] { "ColumnA", "ColumnB", "Etc..." }; String grid_whereClause = "ColumnToSearchBy LIKE ?" if (!TextUtils.isEmpty(grid_currentQuery)) { return new CursorLoader(getActivity(), DataProvider.CONTENT_URI, grid_columns, grid_whereClause, new String[] { grid_currentQuery + "%" }, sort); } return new CursorLoader(getActivity(), DataProvider.CONTENT_URI, grid_columns, null, null, sort); } 

Y eso es todo lo que realmente necesita hacer, me doy cuenta de que esto es un poco cortado, pero es así porque hay más cosas que tiene que suceder, la configuración del adaptador, empezando el cargador en primer lugar con getLoaderManager().initLoader(0, null, this); Y todo el resto de las devoluciones de llamada del cargador que necesitan ser manejadas … pero si usted está siguiendo las mejores prácticas fijadas por la gente del androide, (usar LoaderManager s en su ListActivity s y ListFragments s debe ser bastante fácil para usted. ..

Espero que esto ayude a sentirse libre de pedir aclaraciones en los comentarios si necesita -ck

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.