توفير طريقة عرض البطاقة

إنشاء تطبيقات أفضل باستخدام Compose
يمكنك إنشاء واجهات مستخدم رائعة بأقل قدر من الرموز البرمجية باستخدام Jetpack Compose لنظام التشغيل Android TV.

يركّز هذا الدليل على إنشاء طرق عرض البطاقات لعناصر الوسائط وتقديمها في جزء التصفّح باستخدام حزمة أدوات واجهة مستخدم Leanback المتوقّفة نهائيًا. يتم توضيح عملية تنفيذ متصفّح الكتالوج في جزء التصفّح بالتفصيل في دليل جزء التصفّح.

تعرض الفئة BaseCardView والفئات الفرعية البيانات الوصفية المرتبطة بعنصر وسائط. تعرض الفئة ImageCardView المستخدَمة في هذا الدرس صورة للمحتوى بالإضافة إلى عنوان عنصر الوسائط.

يمكنك أيضًا الاطّلاع على نموذج التنفيذ في تطبيق Leanback التجريبي الذي تم إيقافه نهائيًا.

عرض بطاقة التطبيق

الشكل 1. طريقة عرض بطاقة صورة تطبيق Leanback النموذجي عند تحديدها

إنشاء أداة عرض بطاقات

تنشئ Presenter طرق عرض وتربط العناصر بها عند الطلب. في جزء التصفّح الذي يعرض فيه تطبيقك المحتوى للمستخدم، يمكنك إنشاء Presenter لبطاقات المحتوى وتمريره إلى المحوّل الذي يضيف المحتوى إلى الشاشة. في الرمز التالي، يتم إنشاء CardPresenter في onLoadFinished() الذي يتم استدعاؤه من LoaderManager:

Kotlin

override fun onLoadFinished(loader: Loader<HashMap<String, List<Movie>>>, data: HashMap<String, List<Movie>>) {
    rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
    val cardPresenter = CardPresenter()

    var i = 0L

    data.entries.forEach { entry ->
        val listRowAdapter = ArrayObjectAdapter(cardPresenter).apply {
            entry.value.forEach { movie ->
                add(movie)
            }
        }

        val header = HeaderItem(i, entry.key)
        i++
        rowsAdapter.add(ListRow(header, listRowAdapter))
    }

    val gridHeader = HeaderItem(i, getString(R.string.more_samples))

    val gridRowAdapter = ArrayObjectAdapter(GridItemPresenter()).apply {
        add(getString(R.string.grid_view))
        add(getString(R.string.error_fragment))
        add(getString(R.string.personal_settings))
    }
    rowsAdapter.add(ListRow(gridHeader, gridRowAdapter))

    adapter = rowsAdapter

    updateRecommendations()
}

Java

@Override
public void onLoadFinished(Loader<HashMap<String, List<Movie>>> arg0,
                           HashMap<String, List<Movie>> data) {

    rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
    CardPresenter cardPresenter = new CardPresenter();

    int i = 0;

    for (Map.Entry<String, List<Movie>> entry : data.entrySet()) {
        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
        List<Movie> list = entry.getValue();

        for (int j = 0; j < list.size(); j++) {
            listRowAdapter.add(list.get(j));
        }
        HeaderItem header = new HeaderItem(i, entry.getKey());
        i++;
        rowsAdapter.add(new ListRow(header, listRowAdapter));
    }

    HeaderItem gridHeader = new HeaderItem(i, getString(R.string.more_samples));

    GridItemPresenter gridPresenter = new GridItemPresenter();
    ArrayObjectAdapter gridRowAdapter = new ArrayObjectAdapter(gridPresenter);
    gridRowAdapter.add(getString(R.string.grid_view));
    gridRowAdapter.add(getString(R.string.error_fragment));
    gridRowAdapter.add(getString(R.string.personal_settings));
    rowsAdapter.add(new ListRow(gridHeader, gridRowAdapter));

    setAdapter(rowsAdapter);

    updateRecommendations();
}

إنشاء عرض بطاقة

في هذه الخطوة، يمكنك إنشاء أداة عرض البطاقات باستخدام حاوية عرض لعرض البطاقة التي تصف عناصر المحتوى الإعلامي. يُرجى العِلم أنّه يجب أن ينشئ كل مقدّم نوع عرض واحدًا فقط. إذا كان لديك نوعان من طرق عرض البطاقات، ستحتاج إلى نوعَين من أدوات عرض البطاقات.

في Presenter، نفِّذ onCreateViewHolder() دالة ردّ الاتصال التي تنشئ عنصر نائب للعرض يمكن استخدامه لعرض عنصر محتوى:

Kotlin

private const val CARD_WIDTH = 313
private const val CARD_HEIGHT = 176

class CardPresenter : Presenter() {

    private lateinit var mContext: Context
    private lateinit var defaultCardImage: Drawable

    override fun onCreateViewHolder(parent: ViewGroup): Presenter.ViewHolder {
        mContext = parent.context
        defaultCardImage = mContext.resources.getDrawable(R.drawable.movie)
        ...

Java

@Override
public class CardPresenter extends Presenter {

    private Context context;
    private static int CARD_WIDTH = 313;
    private static int CARD_HEIGHT = 176;
    private Drawable defaultCardImage;

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent) {
        context = parent.getContext();
        defaultCardImage = context.getResources().getDrawable(R.drawable.movie);
...

في طريقة onCreateViewHolder()، أنشئ عرض بطاقة لعناصر المحتوى. يستخدم المثال التالي ImageCardView.

عند اختيار بطاقة، يؤدي السلوك التلقائي إلى توسيعها إلى حجم أكبر. إذا أردت تحديد لون مختلف للبطاقة المحدّدة، استخدِم الدالة setSelected() كما هو موضّح هنا:

Kotlin

    ...
    val cardView = object : ImageCardView(context) {
        override fun setSelected(selected: Boolean) {
            val selected_background = context.resources.getColor(R.color.detail_background)
            val default_background = context.resources.getColor(R.color.default_background)
            val color = if (selected) selected_background else default_background
            findViewById<View>(R.id.info_field).setBackgroundColor(color)
            super.setSelected(selected)
        }
    }
    ...

Java

...
    ImageCardView cardView = new ImageCardView(context) {
        @Override
        public void setSelected(boolean selected) {
            int selected_background = context.getResources().getColor(R.color.detail_background);
            int default_background = context.getResources().getColor(R.color.default_background);
            int color = selected ? selected_background : default_background;
            findViewById(R.id.info_field).setBackgroundColor(color);
            super.setSelected(selected);
        }
    };
...

عندما يفتح المستخدم تطبيقك، تعرض Presenter.ViewHolder عناصر CardView الخاصة بعناصر المحتوى. يجب ضبط هذه القيم لتلقّي التركيز من وحدة التحكّم باستخدام لوحة الاتجاهات من خلال استدعاء setFocusable(true) وsetFocusableInTouchMode(true)، كما هو موضّح في الرمز التالي:

Kotlin

    ...
    cardView.isFocusable = true
    cardView.isFocusableInTouchMode = true
    return ViewHolder(cardView)
}

Java

...
    cardView.setFocusable(true);
    cardView.setFocusableInTouchMode(true);
    return new ViewHolder(cardView);
}

عندما ينقر المستخدم على ImageCardView، يتم توسيعه لعرض مساحة النص مع لون الخلفية الذي تحدّده، كما هو موضّح في الشكل 1.