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

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

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