جستجو در برنامه های تلویزیون

کاربران اغلب هنگام استفاده از یک برنامه رسانه‌ای در تلویزیون، محتوای خاصی را در ذهن دارند. اگر برنامه شما حاوی فهرست بزرگی از محتوا است، جستجو برای یک عنوان خاص ممکن است کارآمدترین راه برای کاربران برای یافتن آنچه به دنبال آن هستند نباشد. یک رابط جستجو می‌تواند به کاربران شما کمک کند تا سریع‌تر از مرور، به محتوای مورد نظر خود برسند.

کتابخانه androidx.leanback مجموعه‌ای از کلاس‌ها را برای فعال کردن یک رابط جستجوی استاندارد در برنامه شما فراهم می‌کند که با سایر توابع جستجو در تلویزیون سازگار است و ویژگی‌هایی مانند ورودی صوتی را ارائه می‌دهد.

این راهنما نحوه ارائه رابط جستجو در برنامه شما با استفاده از کلاس‌های کتابخانه پشتیبانی Leanback را مورد بحث قرار می‌دهد.

افزودن یک اقدام جستجو

وقتی از کلاس BrowseFragment برای رابط مرور رسانه استفاده می‌کنید، می‌توانید یک رابط جستجو را به عنوان بخش استاندارد رابط کاربری فعال کنید. رابط جستجو نمادی است که هنگام تنظیم View.OnClickListener روی شیء BrowseFragment در طرح‌بندی ظاهر می‌شود. کد نمونه زیر این تکنیک را نشان می‌دهد.

کاتلین

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

جاوا

@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 تعریف‌شده، یک activity جستجو را فراخوانی می‌کند. برای activity جستجوی خود، از یک طرح‌بندی خطی حاوی SearchFragment استفاده کنید. این fragment همچنین باید رابط SearchFragment.SearchResultProvider را برای نمایش نتایج جستجو پیاده‌سازی کند.

نمونه کد زیر نحوه‌ی بسط دادن کلاس SearchFragment را برای ارائه‌ی رابط جستجو و نتایج نشان می‌دهد:

کاتلین

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

جاوا

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 استفاده شود که پرس‌وجوی جستجو را در یک نخ جداگانه اجرا می‌کند. این تکنیک از مسدود شدن نخ اصلی رابط کاربری توسط پرس‌وجوهای کند جلوگیری می‌کند.

،

کاربران اغلب هنگام استفاده از یک برنامه رسانه‌ای در تلویزیون، محتوای خاصی را در ذهن دارند. اگر برنامه شما حاوی فهرست بزرگی از محتوا است، جستجو برای یک عنوان خاص ممکن است کارآمدترین راه برای کاربران برای یافتن آنچه به دنبال آن هستند نباشد. یک رابط جستجو می‌تواند به کاربران شما کمک کند تا سریع‌تر از مرور، به محتوای مورد نظر خود برسند.

کتابخانه androidx.leanback مجموعه‌ای از کلاس‌ها را برای فعال کردن یک رابط جستجوی استاندارد در برنامه شما فراهم می‌کند که با سایر توابع جستجو در تلویزیون سازگار است و ویژگی‌هایی مانند ورودی صوتی را ارائه می‌دهد.

این راهنما نحوه ارائه رابط جستجو در برنامه شما با استفاده از کلاس‌های کتابخانه پشتیبانی Leanback را مورد بحث قرار می‌دهد.

افزودن یک اقدام جستجو

وقتی از کلاس BrowseFragment برای رابط مرور رسانه استفاده می‌کنید، می‌توانید یک رابط جستجو را به عنوان بخش استاندارد رابط کاربری فعال کنید. رابط جستجو نمادی است که هنگام تنظیم View.OnClickListener روی شیء BrowseFragment در طرح‌بندی ظاهر می‌شود. کد نمونه زیر این تکنیک را نشان می‌دهد.

کاتلین

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

جاوا

@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 تعریف‌شده، یک activity جستجو را فراخوانی می‌کند. برای activity جستجوی خود، از یک طرح‌بندی خطی حاوی SearchFragment استفاده کنید. این fragment همچنین باید رابط SearchFragment.SearchResultProvider را برای نمایش نتایج جستجو پیاده‌سازی کند.

نمونه کد زیر نحوه‌ی بسط دادن کلاس SearchFragment را برای ارائه‌ی رابط جستجو و نتایج نشان می‌دهد:

کاتلین

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

جاوا

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 استفاده شود که پرس‌وجوی جستجو را در یک نخ جداگانه اجرا می‌کند. این تکنیک از مسدود شدن نخ اصلی رابط کاربری توسط پرس‌وجوهای کند جلوگیری می‌کند.