personalizar - Aplicación del widget de búsqueda de la barra de acción de Android en ListFragment
widget barra busqueda google android (1)
Actualmente tengo mi aplicación configurada con un ListFragment
a la izquierda y un DetailsFragment
a la derecha (similar al diseño en la tableta a continuación).
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 tengo problemas para obtener la búsqueda para actualizar la lista en la misma actividad.
Me las arreglé para 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 manera extraña (es decir, presionas hacia atrás y vas a la actividad anterior con el widget de búsqueda que aún muestra el término de búsqueda ).
He añadido las líneas de intención al manifiesto de la siguiente manera
<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 la barra de acción de búsqueda debería ser la parte que lo registra en general, ya que el widget se destruirá junto con ese fragmento.
Aquí está cómo atarlo correctamente:
en su ListFragment
déjele saber que tiene elementos de menú de opciones ...
@Override
public void onActivityCreated(Bundle savedInstanceState) {
..
setHasOptionsMenu(true);
..
}
luego, dentro del mismo ListFragment
cree su menú de opciones anulando la devolución de llamada, una vez que tenga la referencia del widget SearchView, registre 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);
}
cree su widget de búsqueda mediante 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, nuevamente en su ListFragment
, necesita crear el queryListener
que registramos anteriormente:
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 sabe cuándo se modifica o envía una consulta; en mi ejemplo, vuelvo a consultar cada vez que se presiona una tecla porque mi base de datos era pequeña y rápida con los resultados, es posible que deba cambiar esto ... pero notará cómo estoy solo uso el widget para establecer un campo de clase privado dentro de 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
solo 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 recortado pero es así porque hay más cosas que deben suceder, configurar el adaptador, iniciar el cargador en primer lugar usando getLoaderManager().initLoader(0, null, this);
y todo el resto de las devoluciones de llamada del cargador que deben manejarse ... pero si está siguiendo las mejores prácticas establecidas por la gente de Android, (usar LoaderManager
s en sus ListActivity
y ListFragments
s debería ser bastante fácil para usted. ..
Espero que esto ayude a no dudar en pedir una aclaración en los comentarios si necesita -ck