Tìm kiếm trong các ứng dụng trên TV

Người dùng thường nghĩ đến nội dung cụ thể khi sử dụng ứng dụng đa phương tiện trên TV. Nếu ứng dụng của bạn chứa một danh mục nội dung khổng lồ, thì việc duyệt qua một tiêu đề cụ thể có thể không phải là cách hiệu quả nhất để tìm thấy thông tin họ đang tìm kiếm. Giao diện tìm kiếm có thể giúp người dùng của bạn truy cập vào nội dung họ muốn nhanh hơn việc duyệt qua.

Thư viện androidx.leanback cung cấp một tập hợp các lớp để hỗ trợ một giao diện tìm kiếm chuẩn trong ứng dụng của bạn sao cho phù hợp với các chức năng tìm kiếm khác trên TV và cung cấp các tính năng như nhập bằng giọng nói.

Hướng dẫn này thảo luận cách cung cấp giao diện tìm kiếm trong ứng dụng bằng sự hỗ trợ Leanback các lớp thư viện khác nhau.

Thêm một hành động tìm kiếm

Khi bạn sử dụng lớp BrowseFragment cho một nội dung nghe nhìn bạn có thể bật giao diện tìm kiếm làm thành phần tiêu chuẩn của người dùng . Giao diện tìm kiếm là một biểu tượng xuất hiện trong bố cục khi bạn đặt View.OnClickListener trên BrowseFragment . Mã mẫu sau đây minh hoạ kỹ thuật này.

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

Lưu ý: Bạn có thể đặt màu của biểu tượng tìm kiếm bằng cách sử dụng setSearchAffordanceColor(int) .

Thêm nội dung tìm kiếm và kết quả

Khi người dùng chọn biểu tượng tìm kiếm, hệ thống sẽ gọi một hoạt động tìm kiếm bằng cách sử dụng ý định đã xác định. Đối với hoạt động tìm kiếm của bạn, hãy sử dụng bố cục tuyến tính có chứa SearchFragment. Mảnh này cũng phải triển khai SearchFragment.SearchResultProvider để hiển thị kết quả tìm kiếm.

Mã mẫu sau đây cho biết cách mở rộng lớp SearchFragment để cung cấp giao diện tìm kiếm và kết quả:

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

Mã ví dụ trước dùng với lớp SearchRunnable chạy truy vấn tìm kiếm trên một chuỗi riêng. Kỹ thuật này có thể khiến thiết bị chạy chậm các truy vấn chặn luồng giao diện người dùng chính.