חיפוש באפליקציות לטלוויזיה

לעיתים קרובות, המשתמשים חושבים על תוכן ספציפי כשהם משתמשים באפליקציית מדיה בטלוויזיה. אם האפליקציה כוללת קטלוג גדול של תוכן, ייתכן שעיון בכותרת ספציפית לא יהיה הדרך היעילה ביותר המשתמשים כדי למצוא את מה שהם מחפשים. ממשק חיפוש יכול לעזור למשתמשים לקבל גישה התוכן שהם רוצים מהר יותר מאשר גלישה.

ספריית 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) .

הוספה של קלט חיפוש ותוצאות

כשמשתמש לוחץ על סמל החיפוש, המערכת מפעילה פעילות חיפוש באמצעות כוונה מוגדרת. לפעילות החיפוש שלכם, יש להשתמש בפריסה ליניארית שכוללת SearchFragment בקטע הזה צריך גם להטמיע את 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 שמריצה את שאילתת החיפוש בשרשור נפרד. השיטה הזו עלולה להמשיך לפעול באיטיות למנוע שאילתות מחסימת ה-thread הראשי של ממשק המשתמש.