O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Pesquisar em apps para TV

Muitas vezes, os usuários têm um conteúdo específico em mente ao usar um app de mídia na TV. Se o app tem um catálogo grande de conteúdo, navegar até um título específico pode não ser a forma mais eficiente para o usuário encontrar o que ele está buscando. Uma interface de pesquisa pode ajudar o usuário a encontrar o conteúdo que ele busca de forma mais rápida do que a navegação.

A Biblioteca de androidx Leanback oferece um conjunto de classes para ativar uma interface de pesquisa padrão no seu app que é consistente com outras funções de pesquisa na TV e que disponibiliza recursos como entrada de texto por voz.

Esta lição explica como disponibilizar uma interface de pesquisa no seu app usando classes da Biblioteca de Suporte Leanback.

Adicionar uma ação de pesquisa

Ao usar a classe BrowseFragment para uma interface de navegação de mídia, é possível ativar uma interface de pesquisa como parte padrão da interface do usuário. A interface de pesquisa é um ícone exibido no layout quando View.OnClickListener é definido no objeto BrowseFragment. O código de amostra a seguir ilustra essa técnica.

Kotlin

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.browse_activity)
        browseFragment = fragmentManager.findFragmentById(R.id.browse_fragment) as BrowseFragment
        browseFragment.setOnSearchClickedListener { view ->
            val intent = Intent(this@BrowseActivity, SearchActivity::class.java)
            startActivity(intent)
        }

        browseFragment.setAdapter(buildAdapter())
    }
    

Java

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

        browseFragment = (BrowseFragment)
                getFragmentManager().findFragmentById(R.id.browse_fragment);

        ...

        browseFragment.setOnSearchClickedListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(BrowseActivity.this, SearchActivity.class);
                startActivity(intent);
            }
        });

        browseFragment.setAdapter(buildAdapter());
    }
    

Observação: é possível configurar a cor do ícone de pesquisa usando setSearchAffordanceColor(int).

Adicionar uma entrada de pesquisa e resultados

Quando o usuário seleciona o ícone de pesquisa, o sistema invoca uma atividade de pesquisa por meio da intent definida. Sua atividade de pesquisa precisa usar um layout linear que contém um SearchFragment. Esse fragmento também precisa implementar a interface SearchFragment.SearchResultProvider para exibir os resultados de uma pesquisa.

A amostra de código a seguir ilustra como estender a classe SearchFragment para oferecer uma interface de pesquisa e resultados:

Kotlin

    class MySearchFragment : SearchFragment(), SearchFragment.SearchResultProvider {
        private val rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
        private val handler = Handler()
        private val delayedLoad = SearchRunnable()

        val resultsAdapter: ObjectAdapter
        get() {
            return rowsAdapter
        }

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setSearchResultProvider(this)
            setOnItemClickedListener(getDefaultItemClickedListener())
        }

        fun onQueryTextChange(newQuery: String): Boolean {
            rowsAdapter.clear()
            if (!TextUtils.isEmpty(newQuery)) {
                delayedLoad.setSearchQuery(newQuery)
                handler.removeCallbacks(delayedLoad)
                handler.postDelayed(delayedLoad, SEARCH_DELAY_MS)
            }
            return true
        }

        fun onQueryTextSubmit(query: String): Boolean {
            rowsAdapter.clear()
            if (!TextUtils.isEmpty(query)) {
                delayedLoad.setSearchQuery(query)
                handler.removeCallbacks(delayedLoad)
                handler.postDelayed(delayedLoad, SEARCH_DELAY_MS)
            }
            return true
        }

        companion object {
            private val SEARCH_DELAY_MS = 300
        }
    }
    

Java

    public class MySearchFragment extends SearchFragment
            implements SearchFragment.SearchResultProvider {

        private static final int SEARCH_DELAY_MS = 300;
        private ArrayObjectAdapter rowsAdapter;
        private Handler handler = new Handler();
        private SearchRunnable delayedLoad;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
            setSearchResultProvider(this);
            setOnItemClickedListener(getDefaultItemClickedListener());
            delayedLoad = new SearchRunnable();
        }

        @Override
        public ObjectAdapter getResultsAdapter() {
            return rowsAdapter;
        }

        @Override
        public boolean onQueryTextChange(String newQuery) {
            rowsAdapter.clear();
            if (!TextUtils.isEmpty(newQuery)) {
                delayedLoad.setSearchQuery(newQuery);
                handler.removeCallbacks(delayedLoad);
                handler.postDelayed(delayedLoad, SEARCH_DELAY_MS);
            }
            return true;
        }

        @Override
        public boolean onQueryTextSubmit(String query) {
            rowsAdapter.clear();
            if (!TextUtils.isEmpty(query)) {
                delayedLoad.setSearchQuery(query);
                handler.removeCallbacks(delayedLoad);
                handler.postDelayed(delayedLoad, SEARCH_DELAY_MS);
            }
            return true;
        }
    }
    

O código acima é um exemplo de classe SearchRunnable separada, que executa a consulta de pesquisa em outra linha de execução. Essa técnica evita que consultas possivelmente lentas bloqueiem a linha de execução principal da interface do usuário.