Como configurar a interface de pesquisa

A partir do Android 3.0, usar o widget SearchView como um item na barra de apps é a maneira preferencial para oferecer o recurso de pesquisa no seu app. Assim como em todos os itens da barra de apps, você pode definir que a SearchView seja exibida apenas quando houver espaço ou como uma ação recolhível, que exibe a SearchView como um ícone inicialmente e depois ocupa toda a barra de apps como um campo de pesquisa quando o usuário clica no ícone.

Observação: mais adiante nesta aula, você saberá como tornar seu app compatível com o Android 2.1 (API nível 7) para dispositivos não compatíveis com a SearchView.

Adicionar a exibição de pesquisa à barra de apps

Para adicionar um widget SearchView à barra de apps, crie um arquivo chamado res/menu/options_menu.xml em seu projeto e adicione o seguinte código a esse arquivo. Esse código define como criar o item de pesquisa, como o ícone a ser usado e o título do item. O atributo collapseActionView permite que a SearchView seja expandida para ocupar toda a barra de apps e volte a ser um item normal da barra de apps quando não estiver em uso. Devido ao espaço limitado da barra de apps nos dispositivos móveis, é recomendável usar o atributo collapsibleActionView para oferecer uma experiência melhor ao usuário.

    <?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="android.widget.SearchView" />
    </menu>
    

Observação: se você já tem um arquivo XML para os itens de menu, pode adicionar o elemento <item> a esse arquivo.

Para exibir o SearchView na barra de apps, infle o recurso de menu XML (res/menu/options_menu.xml) no método onCreateOptionsMenu() da atividade:

Kotlin

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

        return true
    }
    

Java

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.options_menu, menu);

        return true;
    }
    

Se você executar o app agora, a SearchView aparecerá na barra do app, mas não funcionará. É preciso definir como a SearchView se comporta.

Criar uma configuração pesquisável

Uma configuração pesquisável define como a SearchView se comporta e é definida em um arquivo res/xml/searchable.xml. Uma configuração pesquisável precisa conter no mínimo um atributo android:label que tenha o mesmo valor que o atributo android:label do elemento <application> ou <activity> no manifesto do Android. No entanto, também recomendamos adicionar um atributo android:hint para que o usuário tenha noção do que inserir na caixa de pesquisa:

    <?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" />
    

No arquivo de manifesto do aplicativo, declare um elemento <meta-data> que aponte para o arquivo res/xml/searchable.xml, para que o aplicativo saiba onde encontrá-lo. Declare o elemento na <activity> em que você quer exibir a SearchView:

    <activity ... >
        ...
        <meta-data android:name="android.app.searchable"
                android:resource="@xml/searchable" />

    </activity>
    

No método onCreateOptionsMenu() que você criou anteriormente, associe a configuração pesquisável à SearchView chamando setSearchableInfo(SearchableInfo):

Kotlin

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

        // Associate searchable configuration with the SearchView
        val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
        (menu.findItem(R.id.search).actionView as SearchView).apply {
            setSearchableInfo(searchManager.getSearchableInfo(componentName))
        }

        return true
    }
    

Java

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.options_menu, menu);

        // Associate searchable configuration with the SearchView
        SearchManager searchManager =
               (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView =
                (SearchView) menu.findItem(R.id.search).getActionView();
        searchView.setSearchableInfo(
                searchManager.getSearchableInfo(getComponentName()));

        return true;
    }
    

A chamada para getSearchableInfo() resulta em um objeto SearchableInfo criado a partir do arquivo XML de configuração pesquisável. Quando a configuração pesquisável é associada corretamente à SearchView, a SearchView inicia uma atividade com a intent ACTION_SEARCH quando um usuário envia uma consulta. Agora você precisa de uma atividade que possa filtrar essa intent e processar a consulta de pesquisa.

Criar uma atividade pesquisável

Uma SearchView tenta iniciar uma atividade com o ACTION_SEARCH quando o usuário envia uma consulta de pesquisa. Uma atividade pesquisável filtra a intent ACTION_SEARCH e pesquisa a consulta em algum tipo de conjunto de dados. Para criar uma atividade pesquisável, declare uma atividade da sua escolha para filtrar a intent ACTION_SEARCH:

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

Na atividade pesquisável, processe a intent ACTION_SEARCH, procurando-a no método onCreate().

Observação: se a atividade pesquisável for iniciada no modo superior único (android:launchMode="singleTop"), processe também a intent ACTION_SEARCH no método onNewIntent(). No modo superior único, apenas uma instância é criada e as chamadas subsequentes para iniciar a atividade não criam uma nova atividade na pilha. Esse modo de inicialização é útil para que os usuários possam realizar pesquisas na mesma atividade, sem criar uma nova instância de atividade todas as vezes.

Kotlin

    class SearchResultsActivity : Activity() {

        override fun onCreate(savedInstanceState: Bundle?) {
            ...
            handleIntent(intent)
        }

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

        private fun handleIntent(intent: Intent) {

            if (Intent.ACTION_SEARCH == intent.action) {
                val query = intent.getStringExtra(SearchManager.QUERY)
                //use the query to search your data somehow
            }
        }
        ...
    }
    

Java

    public class SearchResultsActivity extends Activity {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            ...
            handleIntent(getIntent());
        }

        @Override
        protected void onNewIntent(Intent intent) {
            ...
            handleIntent(intent);
        }

        private void handleIntent(Intent intent) {

            if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
                String query = intent.getStringExtra(SearchManager.QUERY);
                //use the query to search your data somehow
            }
        }
        ...
    }
    

Se você executar o app agora, a SearchView poderá aceitar a consulta do usuário e iniciar sua atividade pesquisável com a intent ACTION_SEARCH. Agora cabe a você descobrir como armazenar e pesquisar seus dados a partir de uma consulta.