ค้นหาภายในแอป TV

ผู้ใช้มักจะมีเนื้อหาที่ต้องการในใจเมื่อใช้แอปสื่อบนทีวี หากแอปของคุณมี แคตตาล็อกเนื้อหาขนาดใหญ่ การเรียกดูชื่อที่เฉพาะเจาะจงอาจไม่ใช่วิธีที่มีประสิทธิภาพที่สุดสำหรับ ผู้ใช้ในการค้นหาสิ่งที่ต้องการ อินเทอร์เฟซการค้นหาจะช่วยให้ผู้ใช้เข้าถึงเนื้อหาที่ต้องการได้เร็วกว่าการเรียกดู

ไลบรารี androidx.leanback มีคลาสต่างๆ ที่ช่วยให้คุณเปิดใช้อินเทอร์เฟซการค้นหามาตรฐาน ภายในแอปซึ่งสอดคล้องกับฟังก์ชันการค้นหาอื่นๆ บนทีวี และมีฟีเจอร์ต่างๆ เช่น การป้อนข้อมูลด้วยเสียง

คู่มือนี้จะอธิบายวิธีจัดเตรียมอินเทอร์เฟซการค้นหาในแอปโดยใช้คลาสไลบรารีการสนับสนุน Leanback

เพิ่มการดำเนินการค้นหา

เมื่อใช้คลาส BrowseFragment สำหรับอินเทอร์เฟซการเรียกดูสื่อ คุณจะเปิดใช้อินเทอร์เฟซการค้นหาเป็นส่วนมาตรฐานของอินเทอร์เฟซผู้ใช้ ได้ อินเทอร์เฟซการค้นหาเป็นไอคอนที่ปรากฏในเลย์เอาต์เมื่อคุณตั้งค่า View.OnClickListener ในออบเจ็กต์ BrowseFragment โค้ดตัวอย่างต่อไปนี้แสดงเทคนิคนี้

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

หมายเหตุ: คุณสามารถตั้งค่าสีของไอคอนค้นหาได้โดยใช้วิธี setSearchAffordanceColor(int)

เพิ่มช่องป้อนข้อมูลและผลการค้นหา

เมื่อผู้ใช้เลือกไอคอนค้นหา ระบบจะเรียกใช้กิจกรรมการค้นหาโดยใช้ Intent ที่กำหนดไว้ สำหรับกิจกรรมการค้นหา ให้ใช้เลย์เอาต์เชิงเส้นที่มี SearchFragment นอกจากนี้ Fragment นี้ต้องใช้ SearchFragment.SearchResultProvider อินเทอร์เฟซเพื่อแสดงผลการค้นหาด้วย

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีขยายคลาส SearchFragment เพื่อจัดเตรียมอินเทอร์เฟซการค้นหาและผลการค้นหา

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

โค้ดตัวอย่างก่อนหน้านี้มีไว้เพื่อใช้กับคลาส SearchRunnable ที่เรียกใช้คําค้นหาในเธรดแยกต่างหาก เทคนิคนี้จะป้องกันไม่ให้คําค้นหาที่อาจใช้เวลานานในการทํางาน บล็อกเธรดอินเทอร์เฟซผู้ใช้หลัก