Użytkownicy aplikacji do multimediów na telewizorze często mają na myśli konkretne treści. Jeśli Twoja aplikacja zawiera duży katalog treści, przeglądanie konkretnego tytułu może nie być najwydajniejszym sposobem na znalezienie tego, czego użytkownicy szukają. Dzięki interfejsowi wyszukiwania użytkownicy mogą szybciej znajdować potrzebne treści niż przeglądanie.
Biblioteka androidx.leanback zawiera zestaw klas, które umożliwiają korzystanie ze standardowego interfejsu wyszukiwania w aplikacji, który jest spójny z innymi funkcjami wyszukiwania na telewizorze oraz udostępnia takie funkcje jak głosowe wprowadzanie tekstu.
Ten przewodnik pokazuje, jak udostępnić interfejs wyszukiwania w aplikacji za pomocą klas biblioteki obsługi Leanback.
Dodaj działanie wyszukiwania
Jeśli do interfejsu przeglądania multimediów używasz klasy BrowseFragment
, możesz włączyć interfejs wyszukiwania jako standardową część interfejsu. Interfejs wyszukiwania to ikona, która pojawia się w układzie po ustawieniu atrybutu View.OnClickListener
w obiekcie BrowseFragment
. Poniższy przykładowy kod ilustruje tę metodę.
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()); }
Uwaga: kolor ikony wyszukiwania możesz ustawić za pomocą metody setSearchAffordanceColor(int)
.
Dodaj dane wejściowe i wyniki wyszukiwania
Gdy użytkownik wybierze ikonę wyszukiwania, system wywołuje działanie wyszukiwania z użyciem zdefiniowanej intencji. W przypadku aktywności związanej z wyszukiwaniem użyj układu liniowego zawierającego element SearchFragment
.
Ten fragment musi też implementować interfejs SearchFragment.SearchResultProvider
do wyświetlania wyników wyszukiwania.
Poniższy przykładowy kod pokazuje, jak rozszerzyć klasę SearchFragment
w celu udostępnienia interfejsu wyszukiwania i wyników:
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; } }
Poprzedni przykładowy kod jest przeznaczony do użycia z klasą SearchRunnable
, która uruchamia zapytanie w oddzielnym wątku. Ta technika sprawia, że zapytania, które trwają dłużej, nie blokują głównego wątku interfejsu użytkownika.