یک نمای کارت ارائه دهید

با Compose بهتر بسازید
با استفاده از Jetpack Compose برای سیستم عامل Android TV، رابط‌های کاربری زیبا با حداقل کد ایجاد کنید.

در درس قبلی، شما یک مرورگر کاتالوگ ایجاد کردید که در یک قطعه مرور پیاده سازی شده است که لیستی از آیتم های رسانه را نمایش می دهد. در این درس، نماهای کارت را برای آیتم های رسانه ای خود ایجاد می کنید و آنها را در قسمت مرور ارائه می دهید.

کلاس BaseCardView و زیر کلاس‌ها ابرداده مرتبط با یک آیتم رسانه را نمایش می‌دهند. کلاس ImageCardView مورد استفاده در این درس یک تصویر برای محتوا همراه با عنوان آیتم رسانه نمایش می دهد.

همچنین اجرای نمونه را در برنامه نمونه Leanback مشاهده کنید.

نمای کارت برنامه

شکل 1. نمای کارت تصویر برنامه Leanback در صورت انتخاب.

یک ارائه دهنده کارت ایجاد کنید

یک Presenter نماها را تولید می کند و اشیاء را در صورت درخواست به آنها متصل می کند. در قسمت مرور که برنامه شما محتوای خود را به کاربر ارائه می‌کند، یک Presenter برای کارت‌های محتوا ایجاد می‌کنید و آن را به آداپتوری که محتوا را به صفحه اضافه می‌کند، ارسال می‌کنید. در کد زیر، CardPresenter در پاسخ به تماس onLoadFinished() LoaderManager ایجاد می شود:

کاتلین

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

جاوا

@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 ، یک callback onCreateViewHolder() را پیاده سازی کنید که یک view دارنده ایجاد می کند که می تواند برای نمایش یک آیتم محتوا استفاده شود:

کاتلین

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)
        ...

جاوا

@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() را همانطور که در اینجا نشان داده شده است فراخوانی کنید:

کاتلین

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

جاوا

...
    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 را برای آیتم های محتوای شما نمایش می دهد. برای دریافت فوکوس از کنترلر D-pad با فراخوانی setFocusable(true) و setFocusableInTouchMode(true) نیاز دارید، همانطور که در کد زیر نشان داده شده است:

کاتلین

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

جاوا

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

هنگامی که کاربر ImageCardView را انتخاب می‌کند، آن را گسترش می‌دهد تا ناحیه متن خود را با رنگ پس‌زمینه‌ای که شما مشخص کرده‌اید نشان دهد، همانطور که در شکل 1 نشان داده شده است.