20

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 a continuación).Implementación del widget de Android Actionbar Search En ListFragment

layout

En la barra de acciones que tienen 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 algún tipo 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, presiona hacia atrás y va a la actividad anterior con el widget de búsqueda todavía mostrando el término de búsqueda).

He añadido las líneas 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?

Respuesta

46

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

Así es como atar correctamente hacia arriba:

en su ListFragment Que se sepa que tiene elementos de menú de opciones ...

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

continuación, dentro de la misma ListFragment crear su menú de opciones anulando la devolución de llamada, una vez que tenga la referencia Reproductor 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 sus s earch widget de vía mediante programación (Java) o de forma declarativa (XML) aquí es XML (llamado grid_default.xml, de antes):

<?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 de nuevo en su ListFragment que necesita para crear el queryListener se registró 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 cuando se cambia o se 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 resultados, puede necesitar cambiar esto ... pero usted ' Notaré que solo estoy usando el widget para establecer un campo de clase privado dentro del ListFragment en el texto actual del sear Reproductor ch (grid_currentQuery) y luego sólo estoy llamando getLoaderManager().restartLoader(0, null, MyListFragment.this); donde dentro de mi onCreateLoader Estoy actualizando la consulta utilicé como esto:

@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 tiene que hacer, que dan cuenta de esto es una especie de picada 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 llamadas del cargador que deben ser manejadas ...pero si usted está siguiendo las mejores prácticas establecidas hacia adelante por la gente androide, (usando LoaderManager s en sus ListActivity s y ListFragments s debería ser bastante fácil para usted ...

espero que esto ayude a sentirse libre de pedir una aclaración en los comentarios si necesita -ck

+0

Muchas gracias por la explicación detallada. Trataré de implementarlo en los próximos días y le haré saber si tengo algún problema. – bencallis

+0

Gracias he logrado obtenerlo trabajo una respuesta muy informativa. Una cosa que me preguntaba: por defecto en la aplicación tengo 3 pestañas cada una representando una categoría cuando busco eliminar estas pestañas. Eso no es un problema, el problema que tengo es cómo lo sé cuando el usuario tiene finalizó la búsqueda (regresó) para volver a agregar las pestañas. – bencallis

+0

@bencallis lo que más le gustaría es utilizar el oyente setOnCloseListener (SearchView.OnCloseListener) en el SearchView ... – ckozl