Cómo crear una interfaz de búsqueda

Si quieres agregar la funcionalidad de búsqueda a tu aplicación, Android te ayuda a implementar la interfaz de usuario con un diálogo de búsqueda que aparece en la parte superior de la ventana de actividad o un widget de búsqueda que puedes insertar en el diseño. Tanto el diálogo como el widget de búsqueda pueden entregar la búsqueda del usuario a una actividad específica en tu aplicación. De esta manera, el usuario puede iniciar una búsqueda desde cualquier actividad donde esté disponible el diálogo o widget de búsqueda, y el sistema inicia la actividad apropiada para realizar la búsqueda y presentar resultados.

Otras funciones disponibles para el diálogo y el widget de búsqueda incluyen las siguientes:

  • Búsqueda por voz
  • Sugerencias de búsqueda basadas en consultas recientes
  • Sugerencias de búsqueda que coinciden con resultados reales en los datos de tu aplicación

En esta guía, se muestra cómo configurar la aplicación para proporcionar una interfaz de búsqueda asistida por el sistema Android a fin de entregar consultas de búsqueda, utilizando el diálogo o el widget de búsqueda.

Recursos relacionados:

Conceptos básicos

Figura 1: Captura de pantalla del diálogo de búsqueda de una aplicación

Antes de comenzar, debes decidir si vas a implementar tu interfaz de búsqueda utilizando el diálogo o el widget de búsqueda. Ambos proporcionan las mismas funciones de búsqueda, pero de maneras ligeramente distintas:

  • El diálogo de búsqueda es un componente de IU que controla el sistema Android. Cuando el usuario lo activa, el diálogo de búsqueda aparece en la parte superior de la actividad, como se muestra en la figura 1.

    El sistema Android controla todos los eventos en el diálogo de búsqueda. Cuando el usuario envía una consulta, el sistema envía la consulta a la actividad que especificas para administrar las búsquedas. El diálogo también puede proporcionar sugerencias de búsqueda mientras el usuario escribe.

  • El widget de búsqueda es una instancia de SearchView que puedes colocar en cualquier lugar del diseño. De manera predeterminada, el widget de búsqueda se comporta como un widget EditText estándar y no hace nada, pero puedes configurarlo para que el sistema Android maneje todos los eventos de entrada, envíe consultas a la actividad apropiada y proporcione sugerencias de búsqueda (igual que el diálogo de búsqueda).

    Nota: Si quieres, puedes administrar todas las entradas de los usuarios en el widget de búsqueda mediante diversos métodos de devolución de llamada y objetos de escucha. Sin embargo, este documento se centra en cómo integrar el widget de búsqueda con el sistema para una implementación de búsqueda asistida. Si deseas manejar todas las entradas del usuario tú mismo, lee la documentación de referencia para SearchView y sus interfaces anidadas.

Cuando el usuario ejecuta una búsqueda desde el diálogo o widget de búsqueda, el sistema crea un Intent y almacena la consulta del usuario allí. Luego, el sistema inicia la actividad que declaraste para manejar las búsquedas (la "actividad de búsqueda") y entrega el intent. Si quieres configurar tu aplicación para este tipo de búsqueda asistida, necesitas lo siguiente:

  • Una configuración de búsqueda

    Un archivo XML que configura algunos ajustes para el diálogo o widget de búsqueda. Incluye configuraciones para funciones, como búsqueda por voz, sugerencia de búsqueda y texto de sugerencias para el cuadro de búsqueda.

  • Una actividad de búsqueda

    La Activity que recibe la búsqueda busca en tus datos y muestra los resultados de la búsqueda.

  • Una interfaz de búsqueda proporcionada por:
    • El diálogo de búsqueda

      De manera predeterminada, el cuadro de búsqueda está oculto, pero aparece en la parte superior de la pantalla cuando llamas a onSearchRequested() (cuando el usuario presiona tu botón de búsqueda).

    • O un widget SearchView

      El uso del widget de búsqueda permite colocar el cuadro de búsqueda en cualquier lugar de la actividad. En lugar de ponerlo en el diseño de la actividad, deberías usar SearchView como una vista de acción en la barra de la app.

En el resto de este documento, se muestra cómo crear la configuración de búsqueda, realizar la actividad de búsqueda e implementar una interfaz de búsqueda con el diálogo o widget de búsqueda.

Cómo crear una configuración de búsqueda

Lo primero que necesitas es un archivo XML llamado configuración de búsqueda. Este archivo configura ciertos aspectos de la IU del diálogo o widget de búsqueda, y define la forma en que se comportan las funciones, como las sugerencias y la búsqueda por voz. Suele denominarse searchable.xml y debe guardarse en el directorio del proyecto res/xml/.

Nota: El sistema usa este archivo para crear instancias de un objeto SearchableInfo, pero no puedes crear ese objeto en el entorno de ejecución. Debes declarar la configuración de búsqueda en XML.

El archivo de configuración de búsqueda debe incluir el elemento <searchable> como el nodo raíz y especificar uno o más atributos. Por ejemplo:

    <?xml version="1.0" encoding="utf-8"?>
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/app_label"
        android:hint="@string/search_hint" >
    </searchable>
    

El atributo android:label es el único atributo requerido. Apunta a un recurso de string, que debe ser el nombre de la aplicación. Esta etiqueta no está visible para el usuario hasta que habilitas las sugerencias de búsqueda para el cuadro de búsqueda rápida. En ese momento, la etiqueta aparece en la lista de elementos de búsqueda en la configuración del sistema.

Aunque no es obligatorio, recomendamos que siempre incluyas el atributo android:hint, que proporciona una string de sugerencia en el cuadro de búsqueda antes de que los usuarios ingresen una consulta. La sugerencia es importante porque proporciona pistas importantes a los usuarios sobre lo que pueden buscar.

Sugerencia: A fin de lograr la coherencia entre otras aplicaciones para Android, debes darle formato a la string de android:hint como "Buscar <content-or-product>". Por ejemplo, "Buscar canciones y artistas" o "Buscar en YouTube".

El elemento <searchable> acepta varios otros atributos. Sin embargo, no necesitarás la mayoría de los atributos hasta que agregues funciones como sugerencias de búsqueda y búsqueda por voz. Para obtener información detallada sobre el archivo de configuración de búsqueda, consulta el documento de referencia Configuración de búsqueda.

Cómo crear una actividad de búsqueda

Una actividad de búsqueda es la Activity en tu aplicación que realiza búsquedas basadas en una string de consulta y presenta los resultados de la búsqueda.

Cuando el usuario ejecuta una búsqueda en el diálogo o widget de búsqueda, el sistema inicia la actividad de búsqueda y le envía la búsqueda en un Intent con la acción ACTION_SEARCH. La actividad de búsqueda recupera la consulta del elemento adicional de QUERY del intent, busca en los datos y presenta los resultados.

Debido a que puedes incluir el diálogo o widget de búsqueda en cualquier otra actividad en tu aplicación, el sistema debe saber cuál es la actividad de búsqueda para poder entregar la búsqueda correctamente. Por lo tanto, primero debes declarar tu actividad de búsqueda en el archivo de manifiesto de Android.

Cómo declarar una actividad de búsqueda

Si todavía no tienes una, crea una Activity que realice búsquedas y presente resultados. No es necesario que implementes la funcionalidad de búsqueda; solo crea una actividad que puedas declarar en el manifiesto. Dentro del elemento <activity> del manifiesto:

  1. Declara la actividad para aceptar el intent ACTION_SEARCH, en un elemento <intent-filter>.
  2. Especifica la configuración de búsqueda para usar, en un elemento <meta-data>.

Por ejemplo:

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

El elemento <meta-data> debe incluir el atributo android:name con un valor de "android.app.searchable" y el atributo android:resource con una referencia al archivo de configuración de búsqueda (en este ejemplo, se refiere al archivo res/xml/searchable.xml).

Nota: El <intent-filter> no necesita una <category> con el valor DEFAULT (que normalmente se ve en elementos <activity>), porque el sistema entrega el intent ACTION_SEARCH de manera explícita a la actividad de búsqueda y utiliza su nombre de componente.

Cómo realizar una búsqueda

Una vez que hayas declarado la actividad de búsqueda en el manifiesto, para realizar una búsqueda en la actividad de búsqueda, debes completar tres pasos:

  1. Recepción de la consulta
  2. Búsqueda en los datos
  3. Presentación de los resultados

Los resultados de la búsqueda suelen presentarse en una ListView. Por eso, quizás quieras que la actividad de búsqueda extienda la ListActivity. Incluye un diseño predeterminado con una sola ListView y proporciona varios métodos convenientes para trabajar con la ListView.

Recepción de la consulta

Cuando un usuario ejecuta una búsqueda desde el widget o diálogo de búsqueda, el sistema inicia la actividad de búsqueda y le envía un intent ACTION_SEARCH. Este intent lleva la búsqueda en la string de QUERY adicional. Debes verificar este intent cuando comience la actividad y extraer la string. Por ejemplo, a continuación, se muestra cómo puedes obtener la búsqueda cuando comienza la actividad de búsqueda:

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.search)

        // Verify the action and get the query
        if (Intent.ACTION_SEARCH == intent.action) {
            intent.getStringExtra(SearchManager.QUERY)?.also { query ->
                doMySearch(query)
            }
        }
    }
    

Java

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.search);

        // Get the intent, verify the action and get the query
        Intent intent = getIntent();
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
          String query = intent.getStringExtra(SearchManager.QUERY);
          doMySearch(query);
        }
    }
    

La string de QUERY siempre se incluye con el intent ACTION_SEARCH. En este ejemplo, se recupera la consulta y se pasa a un método doMySearch() local donde se realiza la operación de búsqueda real.

Búsqueda en los datos

El proceso de almacenar y buscar datos es único para tu aplicación. Puedes almacenar y buscar datos de muchas maneras, pero en esta guía no se muestra cómo hacerlo. Almacenar y buscar datos es algo que debes analizar con atención en función de tus necesidades y tu formato de datos. Sin embargo, a continuación, se incluyen algunas sugerencias que puedes aplicar:

  • Si los datos se almacenan en una base de datos SQLite en el dispositivo, realizar una búsqueda en el texto completo (mediante FTS3, en lugar de una consulta LIKE) puede proporcionar una búsqueda más sólida en los datos de texto y producir resultados considerablemente más rápido. Consulta sqlite.org para obtener información sobre FTS3 y la clase SQLiteDatabase a fin de obtener información sobre SQLite en Android.
  • Si los datos se almacenan en línea, el rendimiento de búsqueda percibido puede estar inhibido por la conexión de datos del usuario. Tal vez quieras mostrar una rueda giratoria de progreso hasta que aparezcan los resultados de la búsqueda. Consulta android.net para obtener una referencia de las API de red y Cómo crear un diálogo de progreso para obtener información acerca de cómo mostrar una rueda de progreso.

Presentación de los resultados

Independientemente de dónde se encuentren tus datos y cómo los busques, te recomendamos que muestres los resultados de la búsqueda en la actividad de búsqueda con un Adapter. De esta manera, puedes presentar con facilidad todos los resultados de búsqueda en una ListView. Si tus datos provienen de una consulta de base de datos SQLite, puedes aplicar los resultados a una ListView usando un CursorAdapter. Si tus datos vienen en otro tipo de formato, puedes crear una extensión de BaseAdapter.

Un Adapter vincula cada elemento de un conjunto de datos a un objeto View. Cuando se aplica el Adapter a una ListView, cada dato se inserta como una vista individual en la lista. Adapter es solo una interfaz, por lo que se necesitan implementaciones como CursorAdapter (para vincular datos de un Cursor). Si ninguna de las implementaciones existentes funciona para tus datos, puedes implementar una propia desde BaseAdapter.

Tal vez quieras que tu actividad de búsqueda extienda ListActivity. Puedes llamar a setListAdapter() y pasarle un Adapter que esté vinculado a tus datos. De esa manera, se inyectan todos los resultados de la búsqueda en la ListView de la actividad.

Si quieres obtener más ayuda para presentar los resultados en una lista, consulta la documentación de ListActivity.

Cómo usar el diálogo de búsqueda

El diálogo de búsqueda proporciona un cuadro de búsqueda flotante en la parte superior de la pantalla, con el ícono de la aplicación a la izquierda. El diálogo de búsqueda puede proporcionar sugerencias de búsqueda a medida que el usuario escribe y, cuando el usuario ejecuta una búsqueda, el sistema envía la búsqueda a una actividad de búsqueda que realiza la búsqueda. Sin embargo, si estás desarrollando tu aplicación para dispositivos que ejecutan Android 3.0, deberías considerar usar el widget de búsqueda en su lugar (consulta la sección Cómo usar el widget de búsqueda).

De manera predeterminada, el diálogo de búsqueda siempre está oculto hasta que el usuario lo activa. Tu aplicación puede activar el diálogo de búsqueda llamando a onSearchRequested(). Sin embargo, este método no funciona hasta que habilitas el diálogo de búsqueda para la actividad.

Para habilitar el diálogo de búsqueda, debes indicar al sistema qué actividad de búsqueda debe recibir búsquedas del diálogo de búsqueda para poder realizarlas. Por ejemplo, en la sección anterior sobre Cómo crear una actividad de búsqueda, se creó una actividad de búsqueda llamada SearchableActivity. Si quieres que una actividad separada, llamada OtherActivity, muestre el diálogo de búsqueda y entregue búsquedas a SearchableActivity, debes declarar en el manifiesto que SearchableActivity es la actividad de búsqueda que se usará para el diálogo de búsqueda en OtherActivity.

Para declarar la actividad de búsqueda del diálogo de búsqueda de una actividad, agrega un elemento <meta-data> dentro del elemento <activity> de la actividad correspondiente. El elemento <meta-data> debe incluir el atributo android:value que especifica el nombre de clase de la actividad de búsqueda y el atributo android:name con un valor de "android.app.default_searchable".

Por ejemplo, a continuación, se incluye la declaración para una actividad de búsqueda, SearchableActivity, y otra actividad, OtherActivity, que utiliza para realizar búsquedas ejecutadas desde su diálogo de búsqueda:

    <application ... >
        <!-- this is the searchable activity; it performs searches -->
        <activity android:name=".SearchableActivity" >
            <intent-filter>
                <action android:name="android.intent.action.SEARCH" />
            </intent-filter>
            <meta-data android:name="android.app.searchable"
                       android:resource="@xml/searchable"/>
        </activity>

        <!-- this activity enables the search dialog to initiate searches
             in the SearchableActivity -->
        <activity android:name=".OtherActivity" ... >
            <!-- enable the search dialog to send searches to SearchableActivity -->
            <meta-data android:name="android.app.default_searchable"
                       android:value=".SearchableActivity" />
        </activity>
        ...
    </application>
    

Debido a que OtherActivity ahora incluye un elemento de <meta-data> para declarar qué actividad de búsqueda usar para las búsquedas, la actividad habilitó el diálogo de búsqueda. Mientras el usuario está en esta actividad, el método onSearchRequested() activa el diálogo de búsqueda. Cuando el usuario ejecuta la búsqueda, el sistema inicia SearchableActivity y le entrega el intent ACTION_SEARCH.

Nota: La actividad de búsqueda en sí misma proporciona el diálogo de búsqueda de forma predeterminada, por lo que no necesitas agregar esta declaración a SearchableActivity.

Si deseas que todas las actividades de tu aplicación proporcionen el diálogo de búsqueda, inserta el elemento <meta-data> anterior como elemento secundario del elemento <application> en lugar de cada <activity>. De esta manera, cada actividad hereda el valor, proporciona el diálogo de búsqueda y entrega búsquedas a la misma actividad de búsqueda. (Si tienes varias actividades de búsqueda, puedes anular la opción predeterminada. Para ello, coloca una declaración <meta-data> diferente dentro de las actividades individuales).

Con el diálogo de búsqueda habilitado para tus actividades, tu aplicación está lista para realizar búsquedas.

Cómo invocar el diálogo de búsqueda

Aunque algunos dispositivos proporcionan un botón de búsqueda exclusivo, el comportamiento del botón puede variar entre dispositivos y muchos no proporcionan ninguno. Por lo tanto, cuando uses el diálogo de búsqueda, deberás proporcionar un botón de búsqueda en la IU que active el diálogo de búsqueda llamando al onSearchRequested().

Por ejemplo, debes agregar un botón de búsqueda en el menú de opciones o un diseño de IU que llame a onSearchRequested(). Para mantener la coherencia con el sistema Android y otras apps, debes etiquetar el botón con el ícono de búsqueda de Android que está disponible en el paquete de íconos de la barra de acciones.

Nota: Si tu app usa una barra de la app, no debes usar el diálogo de búsqueda para la interfaz de búsqueda. En su lugar, usa el widget de búsqueda como una vista que se puede contraer en la barra de la app.

También puedes habilitar la función "escribir para buscar", que activa el diálogo de búsqueda cuando el usuario comienza a escribir en el teclado para insertar las combinaciones de teclas en el diálogo de búsqueda. Puedes habilitar la función de escribir para buscar en tu actividad llamando a setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL) durante el método onCreate() de tu actividad.

El impacto del diálogo de búsqueda en el ciclo de vida de la actividad

El diálogo de búsqueda es un Dialog que flota en la parte superior de la pantalla. No provoca ningún cambio en la pila de actividades, por lo que, cuando aparece el diálogo de búsqueda, no se llama a ningún método de ciclo de vida (como onPause()). La actividad simplemente pierde el enfoque de entrada, ya que pasa al diálogo de búsqueda.

Si deseas recibir una notificación cuando el diálogo de búsqueda esté activado, anula el método onSearchRequested(). Cuando el sistema llama a este método, es una indicación de que la actividad perdió el enfoque de entrada con el diálogo de búsqueda. Por eso, puedes realizar cualquier trabajo apropiado para el evento (como pausar un juego). A menos que estés transmitiendo datos de contexto de búsqueda (este tema se analiza a continuación), debes finalizar el método. Para ello, llama a la implementación de superclase. Por ejemplo:

Kotlin

    override fun onSearchRequested(): Boolean {
        pauseSomeStuff()
        return super.onSearchRequested()
    }
    

Java

    @Override
    public boolean onSearchRequested() {
        pauseSomeStuff();
        return super.onSearchRequested();
    }
    

Si el usuario cancela la búsqueda presionando el botón Atrás, se cierra el diálogo de búsqueda y la actividad vuelve a obtener el enfoque de entrada. Puedes registrarte para recibir una notificación cuando se cierra el diálogo de búsqueda con setOnDismissListener() o setOnCancelListener(). Solo deberías registrar el OnDismissListener, ya que se llama cada vez que se cierra el diálogo de búsqueda. El OnCancelListener solo corresponde a eventos en los que el usuario cerró de manera explícita el diálogo de búsqueda. Por lo tanto, no se llama cuando se ejecuta una búsqueda (en ese caso, el diálogo de búsqueda desaparece).

Si la actividad actual no es la de búsqueda, se activan los eventos del ciclo de vida normal de la actividad una vez que el usuario ejecuta una búsqueda (la actividad actual recibe onPause() y así sucesivamente, como se describe en el documento Actividades). Sin embargo, si la actividad actual es la de búsqueda, ocurre una de dos cosas:

  1. De manera predeterminada, la actividad de búsqueda recibe el intent ACTION_SEARCH con una llamada a onCreate() y se lleva una instancia nueva de la actividad a la parte superior de la pila de actividades. Ahora, hay dos instancias de tu actividad de búsqueda en la pila de actividades (por lo que, al presionar el botón Atrás, se vuelve a la instancia anterior de la actividad de búsqueda, en lugar de salir de la actividad de búsqueda).
  2. Si configuras android:launchMode en "singleTop", la actividad de búsqueda recibe el intent ACTION_SEARCH con una llamada a onNewIntent(Intent), pasando el intent ACTION_SEARCH nuevo aquí. Por ejemplo, a continuación, se muestra cómo puedes manejar este caso, en el que el modo de inicio de la actividad de búsqueda es "singleTop":

    Kotlin

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.search)
            handleIntent(intent)
        }
    
        override fun onNewIntent(intent: Intent) {
            setIntent(intent)
            handleIntent(intent)
        }
    
        private fun handleIntent(intent: Intent) {
            if (Intent.ACTION_SEARCH == intent.action) {
                intent.getStringExtra(SearchManager.QUERY)?.also { query ->
                    doMySearch(query)
                }
            }
        }
        

    Java

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.search);
            handleIntent(getIntent());
        }
    
        @Override
        protected void onNewIntent(Intent intent) {
            setIntent(intent);
            handleIntent(intent);
        }
    
        private void handleIntent(Intent intent) {
            if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
              String query = intent.getStringExtra(SearchManager.QUERY);
              doMySearch(query);
            }
        }
        

    En comparación con el código de ejemplo en la sección sobre Cómo realizar una búsqueda, todo el código para manejar el intent de búsqueda ahora está en el método handleIntent(). Por eso, tanto onCreate() como onNewIntent() pueden ejecutarlo.

    Cuando el sistema llama a onNewIntent(Intent), la actividad no se reinició, por lo que el método getIntent() muestra el mismo intent que se recibió con onCreate(). Por esa razón, debes llamar a setIntent(Intent) dentro de onNewIntent(Intent) (para que se actualice el intent que guarda la actividad en caso de que llames a getIntent() en el futuro).

El segundo escenario que utiliza el modo de inicio "singleTop" suele ser ideal, porque hay muchas posibilidades de que, una vez que se realice una búsqueda, el usuario haga búsquedas adicionales, y no es una buena experiencia si la aplicación crea múltiples instancias de la actividad de búsqueda. Por lo tanto, te recomendamos que configures la actividad de búsqueda en el modo de inicio "singleTop", en el manifiesto de la aplicación. Por ejemplo:

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

Cómo pasar datos de contexto de búsqueda

En algunos casos, puedes realizar las mejoras necesarias en la búsqueda dentro de la actividad de búsqueda para cada búsqueda realizada. Sin embargo, si deseas refinar los criterios de búsqueda en función de la actividad desde la cual el usuario realiza una búsqueda, puedes proporcionar datos adicionales en el intent que el sistema envía a la actividad de búsqueda. Puedes pasar los datos adicionales en el Bundle APP_DATA, que se incluye en el intent ACTION_SEARCH.

Para pasar este tipo de datos a tu actividad de búsqueda, anula el método onSearchRequested() para la actividad desde la que el usuario puede realizar una búsqueda. Luego, crea un Bundle con los datos adicionales y llama a startSearch() para activar el diálogo de búsqueda. Por ejemplo:

Kotlin

    override fun onSearchRequested(): Boolean {
        val appData = Bundle().apply {
            putBoolean(JARGON, true)
        }
        startSearch(null, false, appData, false)
        return true
    }
    

Java

    @Override
    public boolean onSearchRequested() {
         Bundle appData = new Bundle();
         appData.putBoolean(SearchableActivity.JARGON, true);
         startSearch(null, false, appData, false);
         return true;
     }
    

Si se muestra "true", significa que procesaste correctamente este evento de devolución de llamada y llamaste a startSearch() para activar el diálogo de búsqueda. Una vez que el usuario envía una consulta, se envía a la actividad de búsqueda junto con los datos que agregaste. Puedes extraer los datos adicionales del Bundle APP_DATA para refinar la búsqueda. Por ejemplo:

Kotlin

    val jargon: Boolean = intent.getBundleExtra(SearchManager.APP_DATA)?.getBoolean(JARGON) ?: false
    

Java

    Bundle appData = getIntent().getBundleExtra(SearchManager.APP_DATA);
    if (appData != null) {
        boolean jargon = appData.getBoolean(SearchableActivity.JARGON);
    }
    

Precaución: Nunca llames al método startSearch() desde fuera del método de devolución de llamada onSearchRequested(). Para activar el diálogo de búsqueda en tu actividad, llama siempre a onSearchRequested(). De lo contrario, no se llama a onSearchRequested() y se pierden las personalizaciones (como la adición de appData en el ejemplo anterior).

Cómo usar el widget de búsqueda

Figura 2: El widget SearchView como una "vista de acción" en la barra de acciones

El widget SearchView está disponible en Android 3.0 y versiones posteriores. Si estás desarrollando tu aplicación para Android 3.0 y decidiste usar el widget de búsqueda, te recomendamos que lo insertes como una vista de acción en la barra de la app, en lugar de usar el diálogo de búsqueda (o colocar el widget en el diseño de tu actividad). Por ejemplo, en la figura 2, se muestra el widget de búsqueda en la barra de la app.

El widget de búsqueda proporciona la misma funcionalidad que el diálogo de búsqueda. Inicia la actividad correspondiente cuando el usuario ejecuta una búsqueda y puede proporcionar sugerencias de búsqueda y realizar búsquedas por voz. Si no es una opción para ti colocar el widget de búsqueda en la barra de acciones, puedes colocar el widget de búsqueda en algún lugar del diseño de la actividad.

Nota: Cuando usas el widget de búsqueda como una vista de acción, es posible que igual necesites usar el diálogo de búsqueda para casos en los que el widget no entra en la barra de acciones. Consulta la siguiente sección acerca de cómo usar el widget y el diálogo.

Cómo configurar el widget de búsqueda

Después de crear una configuración de búsqueda y una actividad de búsqueda, como se analizó anteriormente, debes habilitar la búsqueda asistida para cada SearchView. Para ello, puedes llamar a setSearchableInfo() y pasarle el objeto SearchableInfo que representa la configuración de búsqueda.

Puedes obtener una referencia a la SearchableInfo llamando a getSearchableInfo() en SearchManager.

Por ejemplo, si usas una SearchView como una vista de acción en la barra de la app, debes habilitar el widget durante la devolución de llamada onCreateOptionsMenu():

Kotlin

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the options menu from XML
        val inflater = menuInflater
        inflater.inflate(R.menu.options_menu, menu)

        // Get the SearchView and set the searchable configuration
        val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
        (menu.findItem(R.id.menu_search).actionView as SearchView).apply {
            // Assumes current activity is the searchable activity
            setSearchableInfo(searchManager.getSearchableInfo(componentName))
            setIconifiedByDefault(false) // Do not iconify the widget; expand it by default
        }

        return true
    }
    

Java

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the options menu from XML
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.options_menu, menu);

        // Get the SearchView and set the searchable configuration
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
        // Assumes current activity is the searchable activity
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        searchView.setIconifiedByDefault(false); // Do not iconify the widget; expand it by default

        return true;
    }
    

¡Eso es todo lo que necesitas! El widget de búsqueda ya está configurado y el sistema enviará consultas a tu actividad de búsqueda. También puedes habilitar las sugerencias de búsqueda para el widget de búsqueda.

Nota: Si quieres administrar todas las entradas del usuario por tu cuenta, puedes hacerlo con métodos de devolución de llamada y objetos de escucha de eventos. Para obtener más información, consulta la documentación de referencia para SearchView y sus interfaces anidadas para los objetos de escucha de eventos apropiados.

Para obtener más información sobre las vistas de acción en la barra de acciones, consulta Vistas de acción y proveedores de acción.

Otras funciones del widget de búsqueda

El widget SearchView te permite agregar algunas funciones adicionales que podrían interesarte:

Un botón Enviar
Por defecto, no hay ningún botón para enviar una búsqueda, por lo que el usuario debe presionar la tecla "Volver" en el teclado para iniciar una búsqueda. Puedes agregar el botón "Enviar" llamando al setSubmitButtonEnabled(true).
Mejora en la definición de consultas para sugerencias de búsqueda
Cuando habilitas las sugerencias de búsqueda, por lo general, esperas que los usuarios simplemente seleccionen una sugerencia. Sin embargo, es posible que también quieran definir mejor la búsqueda sugerida. Puedes agregar un botón junto a cada sugerencia que inserte la sugerencia en el cuadro de búsqueda para que el usuario la defina mejor. Para ello, llama al setQueryRefinementEnabled(true).
La capacidad de activar o desactivar la visibilidad del cuadro de búsqueda
De manera predeterminada, el widget de búsqueda está "iconificado", es decir, representado solo por un ícono de búsqueda (una lupa) y se expande para mostrar el cuadro de búsqueda cuando el usuario lo toca. Como se explica arriba, puedes mostrar el cuadro de búsqueda de forma predeterminada, llamando al setIconifiedByDefault(false). También puedes alternar la apariencia del widget de búsqueda llamando a setIconified().

Hay varias otras API en la clase SearchView que permiten personalizar el widget de búsqueda. Sin embargo, la mayoría de ellas se usan solo cuando administras por tu cuenta todas las entradas de los usuarios en lugar de usar el sistema Android para entregar consultas y mostrar sugerencias de búsqueda.

Cómo usar el widget y el diálogo

Si insertas el widget de búsqueda en la barra de acciones como una vista de acción y habilitas que aparezca en la barra de acciones "si hay espacio" (configurando android:showAsAction="ifRoom"), hay posibilidades de que el widget de búsqueda no aparezca como una vista de acciones, pero el elemento de menú aparecerá en el menú ampliado. Por ejemplo, cuando tu aplicación se ejecuta en una pantalla más pequeña, es posible que no haya suficiente espacio en la barra de acciones para mostrar el widget de búsqueda junto con otros elementos de acción o de navegación. Por lo tanto, el elemento de menú aparecerá en el menú ampliado. Cuando se coloca en el menú ampliado, el elemento funciona como un elemento de menú normal y no muestra la vista de acción (el widget de búsqueda).

Para solucionar este problema, el elemento de menú al que adjuntaste el widget de búsqueda debe activar de diálogo de búsqueda cuando el usuario lo seleccione en el menú ampliado. Para ello, debes implementar onOptionsItemSelected() a fin de que maneje el elemento de menú "Buscar" y abra el diálogo de búsqueda llamando a onSearchRequested().

Para obtener más información sobre cómo funcionan los elementos de la barra de acciones y cómo manejar esta situación, consulta la guía para desarrolladores de barra de acciones.

Cómo agregar la búsqueda por voz

Puedes agregar la funcionalidad de búsqueda por voz al diálogo o widget de búsqueda. Para ello, agrega el atributo android:voiceSearchMode a la configuración de búsqueda. Esto agrega un botón de búsqueda por voz que inicia un mensaje de voz. Cuando el usuario haya terminado de hablar, la búsqueda transcrita se enviará a tu actividad de búsqueda.

Por ejemplo:

    <?xml version="1.0" encoding="utf-8"?>
    <searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/search_label"
        android:hint="@string/search_hint"
        android:voiceSearchMode="showVoiceSearchButton|launchRecognizer" >
    </searchable>
    

El valor showVoiceSearchButton es necesario para habilitar la búsqueda por voz, mientras que el segundo, launchRecognizer, especifica que el botón de búsqueda por voz debe iniciar un reconocedor que muestre el texto transcrito a la actividad de búsqueda.

Puedes proporcionar atributos adicionales para especificar el comportamiento de búsqueda por voz, como el idioma que se espera y el número máximo de resultados que se mostrarán. Consulta la referencia de Configuración de búsqueda para obtener más información sobre los atributos disponibles.

Nota: Considera detenidamente si la búsqueda por voz es adecuada para tu aplicación. Todas las búsquedas realizadas con el botón de búsqueda por voz se envían de inmediato a la actividad de búsqueda sin que el usuario tenga la oportunidad de revisar la consulta transcrita. Prueba de manera adecuada el reconocimiento de voz y asegúrate de que comprenda los tipos de consultas que el usuario puede enviar dentro de tu aplicación.

Cómo agregar sugerencias de búsqueda

Figura 3: Captura de pantalla de un diálogo de búsqueda con sugerencias personalizadas

Con la ayuda del sistema Android, tanto el diálogo como el widget de búsqueda pueden proporcionar sugerencias de búsqueda a medida que el usuario escribe. El sistema administra la lista de sugerencias y maneja el evento cuando el usuario selecciona una sugerencia.

Puedes proporcionar dos tipos de sugerencias de búsqueda:

Sugerencias de búsquedas recientes
Estas sugerencias son simplemente palabras que el usuario utilizó antes como búsquedas en la aplicación.

Consulta Cómo agregar sugerencias de búsquedas recientes.

Sugerencias de búsqueda personalizadas
Estas son sugerencias de búsqueda que proporcionas desde tu propia fuente de datos, para ayudar a los usuarios a seleccionar de inmediato la ortografía o el elemento correctos que están buscando. En la figura 3, se muestra un ejemplo de sugerencias personalizadas para una aplicación de diccionario; el usuario puede seleccionar una sugerencia para ir instantáneamente a la definición.

Consulta Cómo agregar sugerencias personalizadas