En la lección anterior, creaste un navegador de catálogos, implementado en un fragmento de navegación, que muestra una lista de elementos multimedia. En esta lección, crearás las vistas de tarjetas para tus elementos multimedia y las presentarás en el fragmento del navegador.
La clase y las subclases BaseCardView
muestran los metadatos asociados con un elemento multimedia. La clase ImageCardView
que se usa en esta lección muestra una imagen para el contenido junto con el título del elemento multimedia.
Consulta también la implementación de muestra en la app de ejemplo de Leanback.
Cómo crear un presentador de tarjetas
Un Presenter
genera vistas y vincula objetos a ellas a pedido. En el fragmento del navegador en el que tu app presenta su contenido al usuario, crea una Presenter
para las tarjetas de contenido y pásala al adaptador que agrega el contenido a la pantalla. En el siguiente código, se crea CardPresenter
en la devolución de llamada onLoadFinished()
de 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(); }
Cómo crear una vista de tarjetas
En este paso, compilarás el presentador de tarjetas con un contenedor de vistas para la vista de tarjetas que describe tus elementos de contenido multimedia. Ten en cuenta que cada presentador debe crear solo un tipo de vista. Si tienes dos tipos de vistas de tarjetas, necesitarás dos presentadores de tarjetas.
En el Presenter
, implementa una devolución de llamada onCreateViewHolder()
que cree un contenedor de vistas que se pueda usar para mostrar un elemento de contenido:
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); ...
En el método onCreateViewHolder()
, crea una vista de tarjetas para los elementos de contenido. En el siguiente ejemplo, se usa un ImageCardView
.
Cuando se selecciona una tarjeta, el comportamiento predeterminado la expande a un tamaño mayor. Si quieres designar un color diferente para la tarjeta seleccionada, llama a setSelected()
como se muestra a continuación:
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); } }; ...
Cuando el usuario abre tu app, Presenter.ViewHolder
muestra los objetos CardView
de tus elementos de contenido. Debes configurarlas para que reciban el foco del control de pad direccional llamando a setFocusable(true)
y setFocusableInTouchMode(true)
, como se muestra en el siguiente código:
Kotlin
... cardView.isFocusable = true cardView.isFocusableInTouchMode = true return ViewHolder(cardView) }
Java
... cardView.setFocusable(true); cardView.setFocusableInTouchMode(true); return new ViewHolder(cardView); }
Cuando el usuario selecciona el objeto ImageCardView
, este se expande para mostrar su área de texto con el color de fondo que especifiques, como se muestra en la figura 1.