Melakukan penelusuran di dalam aplikasi TV

Pengguna sering mengangankan konten tertentu saat menggunakan aplikasi media di TV. Jika aplikasi Anda memuat katalog konten yang sangat panjang, mencari judul tertentu mungkin bukanlah cara paling efisien untuk menemukan konten yang diinginkan. Antarmuka penelusuran dapat membantu pengguna menemukan konten yang mereka inginkan lebih cepat daripada melakukan pencarian.

Library Leanback androidx menyediakan serangkaian class untuk mengaktifkan antarmuka penelusuran standar dalam aplikasi Anda yang konsisten dengan fungsi penelusuran lainnya di TV dan menyediakan berbagai fitur seperti masukan suara.

Pelajaran ini membahas cara menyediakan antarmuka penelusuran di aplikasi Anda menggunakan class support library Leanback.

Menambahkan tindakan penelusuran

Saat menggunakan class BrowseFragment untuk antarmuka penjelajahan media, Anda dapat mengaktifkan antarmuka penelusuran sebagai bagian standar dari antarmuka pengguna. Antarmuka penelusuran adalah ikon yang terlihat di tata letak saat Anda menyetel View.OnClickListener pada objek BrowseFragment. Contoh kode berikut mendemonstrasikan teknik ini.

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());
    }
    

Catatan: Anda dapat menyetel warna ikon penelusuran menggunakan setSearchAffordanceColor(int).

Menambahkan input penelusuran dan hasil

Saat pengguna mengklik ikon penelusuran, sistem akan memanggil aktivitas penelusuran melalui intent yang ditentukan. Aktivitas penelusuran Anda harus menggunakan tata letak linier yang memuat SearchFragment. Fragmen ini juga harus mengimplementasikan antarmuka SearchFragment.SearchResultProvider untuk menampilkan hasil penelusuran.

Contoh kode berikut menunjukkan cara meluaskan class SearchFragment untuk menyediakan antarmuka penelusuran dan hasil:

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;
        }
    }
    

Contoh kode yang ditunjukkan di atas dimaksudkan untuk digunakan dengan class SearchRunnable terpisah yang menjalankan kueri pencarian pada thread terpisah. Dengan teknik ini, kueri yang berpotensi berjalan lambat tidak akan memblokir thread antarmuka pengguna utama.