این راهنما بر ایجاد نماهای کارت برای آیتمهای رسانهای شما و ارائه آنها در قطعه مرور با استفاده از ابزار منسوخشده Leanback UI تمرکز دارد. پیادهسازی مرورگر کاتالوگ در یک قطعه مرور در راهنمای قطعه مرور به تفصیل شرح داده شده است.
کلاس BaseCardView و زیرکلاسهای آن، متادیتای مرتبط با یک آیتم رسانهای را نمایش میدهند. کلاس ImageCardView که در این درس استفاده شده است، تصویری را برای محتوا به همراه عنوان آیتم رسانهای نمایش میدهد.
همچنین پیادهسازی نمونه را در برنامه نمونه منسوخشده Leanback ببینید.

شکل ۱. نمای کارت تصویر برنامه نمونه Leanback هنگام انتخاب.
یک ارائه دهنده کارت ایجاد کنید
یک Presenter نماها (views) را تولید میکند و اشیاء را بر اساس تقاضا به آنها متصل میکند. در بخش مرور (browse fragment) که برنامه شما محتوای خود را به کاربر ارائه میدهد، شما یک 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 ، یک فراخوانی onCreateViewHolder() پیادهسازی کنید که یک view holder ایجاد میکند که میتواند برای نمایش یک آیتم محتوا استفاده شود:
کاتلین
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 را برای آیتمهای محتوایی شما نمایش میدهد. شما باید این موارد را طوری تنظیم کنید که با فراخوانی setFocusable(true) و setFocusableInTouchMode(true) ، همانطور که در کد زیر نشان داده شده است، فوکوس را از کنترلر D-pad دریافت کنند:
کاتلین
... cardView.isFocusable = true cardView.isFocusableInTouchMode = true return ViewHolder(cardView) }
جاوا
... cardView.setFocusable(true); cardView.setFocusableInTouchMode(true); return new ViewHolder(cardView); }
وقتی کاربر ImageCardView انتخاب میکند، همانطور که در شکل ۱ نشان داده شده است، باز میشود تا ناحیه متنی خود را با رنگ پسزمینهای که شما مشخص میکنید، نشان دهد.
