Cómo configurar la interfaz de búsqueda

Te recomendamos que uses el widget SearchView como un elemento de la barra de la app para proporcionar funcionalidad de búsqueda en tu app. Al igual que con todos los elementos de la barra de la app, puedes definir el SearchView para que se muestre en todo momento o solo cuando haya espacio. También puedes definirla como una acción contraíble, que muestra el SearchView como un ícono inicialmente y, luego, ocupa toda la barra de la app como un campo de búsqueda cuando el usuario presiona el ícono.

Cómo agregar SearchView a la barra de la app

Para agregar un widget de SearchView a la barra de la app, crea un archivo llamado res/menu/options_menu.xml en tu proyecto y agrega el siguiente código al archivo. Este código define cómo crear el elemento de búsqueda, por ejemplo, el ícono que se usará y el título del elemento. El atributo collapseActionView permite que tu SearchView se expanda para ocupar toda la barra de la app y contraerse como un elemento normal de la barra cuando no esté en uso. Debido al espacio limitado de la barra de la app en teléfonos celulares, te recomendamos usar el atributo collapsibleActionView para brindar una mejor experiencia del usuario.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/search"
        android:title="@string/search_title"
        android:icon="@drawable/ic_search"
        android:showAsAction="collapseActionView|ifRoom"
        android:actionViewClass="androidx.appcompat.widget.SearchView" />
</menu>

Si quieres un ícono de búsqueda más accesible, crea un archivo ic_search.xml en la carpeta /res/drawable y, luego, incluye el siguiente código:

<vector
    android:height="24dp"
    android:tint="#000000"
    android:viewportHeight="24"
    android:viewportWidth="24"
    android:width="24dp"
    xmlns:android="http://schemas.android.com/apk/res/android">
        <path android:fillColor="@android:color/white" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>

Para mostrar el SearchView en la barra de la app, aumenta el recurso del menú XML res/menu/options_menu.xml en el método onCreateOptionsMenu() de tu actividad:

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options_menu, menu)

    return true
}

Cuando se ejecuta la app, se genera algo similar a lo siguiente:

Imagen que muestra una pantalla vacía con un ícono de búsqueda en la barra superior de la app
Figura 1: Un ícono de búsqueda en la barra superior de la app

El SearchView aparece en la barra de la app de tu app, pero no funciona. Si presionas el ícono de búsqueda, obtienes algo como lo siguiente:

Una imagen que muestra la vista de búsqueda en acción
Figura 2: SearchView en acción.

Para que SearchView sea funcional, debes definir cómo se comporta SearchView.

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

Una configuración de búsqueda especifica el comportamiento de SearchView y se define en un archivo res/xml/searchable.xml. Una configuración de búsqueda debe contener, como mínimo, un atributo android:label que tenga el mismo valor que el atributo android:label del elemento <application> o <activity> en tu manifiesto de Android. Sin embargo, también recomendamos agregar un atributo android:hint para que el usuario tenga una idea de lo que debe ingresar en el cuadro de búsqueda.

<?xml version="1.0" encoding="utf-8"?>

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/app_name"
        android:hint="@string/search_hint" />

En el archivo de manifiesto de tu app, declara un elemento <meta-data> que apunte al archivo res/xml/searchable.xml. Declara el elemento en una <activity> en la que quieras mostrar el SearchView.

<activity
android:name=".SearchResultsActivity"
android:exported="false"
android:label="@string/title_activity_search_results"
android:launchMode="singleTop"
android:theme="@style/Theme.AppCompat.Light">
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    <meta-data
        android:name="android.app.searchable"
        android:resource="@xml/searchable" />
</activity>

En el método onCreateOptionsMenu() que crees, asocia la configuración de búsqueda con SearchView llamando a setSearchableInfo(SearchableInfo):

Kotlin

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.options_menu, menu)

    val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
    val searchView = menu.findItem(R.id.search).actionView as SearchView
    val component = ComponentName(this, SearchResultsActivity::class.java)
    val searchableInfo = searchManager.getSearchableInfo(component)
    searchView.setSearchableInfo(searchableInfo)
    return true
}

La llamada a getSearchableInfo() obtiene un objeto SearchableInfo que se crea a partir del archivo en formato XML de configuración de la búsqueda. Cuando la configuración de búsqueda está asociada de forma correcta con tu SearchView y el usuario envía una consulta, SearchView inicia una actividad con el intent ACTION_SEARCH. Luego, necesitas una actividad que pueda filtrar para este intent y manejar la búsqueda.

Cómo crear una actividad de búsqueda

Una actividad de búsqueda filtra el intent ACTION_SEARCH y busca la consulta en un conjunto de datos. Para crear una actividad de búsqueda, declara la actividad que quieras filtrar por el intent ACTION_SEARCH:

<activity android:name=".SearchResultsActivity" ... >
    ...
    <intent-filter>
        <action android:name="android.intent.action.SEARCH" />
    </intent-filter>
    ...
</activity>

En la actividad de búsqueda, controla el intent ACTION_SEARCH. Para ello, búscalo en tu método onCreate().

Kotlin

class SearchResultsActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_search_results)
        handleIntent(intent)
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        handleIntent(intent)
    }

    private fun handleIntent(intent: Intent) {
        if (Intent.ACTION_SEARCH == intent.action) {
            val query = intent.getStringExtra(SearchManager.QUERY)
            Log.d("SEARCH", "Search query was: $query")
        }
    }
}

Ahora, SearchView puede aceptar la consulta del usuario y, luego, iniciar la actividad de búsqueda con el intent ACTION_SEARCH.

Después de obtener la búsqueda, puedes pasarla a ViewModel, donde puedes usarla en otras capas de tu arquitectura para recuperar los resultados de la búsqueda que se mostrarán.