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 tiver um catálogo grande de conteúdo, procurar um título específico pode não ser a maneira mais eficiente de usuários encontrem o que procuram. Uma interface de pesquisa pode ajudar seus usuários a chegar conteúdo que procuram mais rápido do que a navegação.
A biblioteca androidx.androidx oferece um conjunto de classes para ativar uma interface de pesquisa padrão no app que seja consistente com outras funções de pesquisa na TV e ofereça recursos como entrada de texto por voz.
Este guia discute como fornecer uma interface de pesquisa no seu app usando a compatibilidade com o Leanback aulas de biblioteca.
Adicionar uma ação de pesquisa
Ao usar a classe BrowseFragment
para uma mídia
interface de navegação do usuário, é possível ativar uma interface de pesquisa como parte padrão do
interface gráfica do usuário. A interface de pesquisa é um ícone que aparece no layout quando View.OnClickListener
é definido no BrowseFragment
.
objeto. 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 definir a cor do ícone de pesquisa usando o
setSearchAffordanceColor(int)
.
Adicionar uma entrada de pesquisa e resultados
Quando um usuário seleciona o ícone de pesquisa, o sistema invoca uma atividade de pesquisa usando o
intent definida. Para sua atividade de pesquisa, use um layout linear que contenha um
SearchFragment
:
Esse fragmento também precisa implementar o SearchFragment.SearchResultProvider
.
para exibir os resultados de uma pesquisa.
O exemplo de código abaixo mostra como estender a classe SearchFragment
.
para fornecer 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 de exemplo anterior precisa ser usado com uma classe SearchRunnable
que executa a consulta de pesquisa em um thread separado. Essa técnica mantém uma execução potencialmente lenta
as consultas bloqueiem a linha de execução principal da interface do usuário.