Oferecer uma visualização de card

Criar da melhor forma com o Compose
Crie interfaces incríveis com o mínimo de código usando o Jetpack Compose para o SO do Android TV.

Na lição anterior, você criou um navegador de catálogo, implementado em um fragmento de navegação, que exibe uma lista de itens de mídia. Nesta aula, você vai criar visualizações de card para seus itens de mídia e apresentá-los no fragmento de navegação.

O BaseCardView A classe e as subclasses exibem os metadados associados a um item de mídia. A ImageCardView usada nesta lição exibe uma imagem para o conteúdo junto com o título do item de mídia.

Consulte também o exemplo de implementação na App de amostra do Leanback ,

Visualização de card de apps

Figura 1. Visualização de card do app de amostra de Leanback quando selecionado.

Criar uma apresentação de card

Um Presenter gera visualizações e vincula objetos a elas sob demanda. No fragmento de navegação em que seu aplicativo apresenta o conteúdo ao usuário, você cria um Presenter para os cards de conteúdo e transmiti-los para o adaptador. que adiciona o conteúdo à tela. No código abaixo, o CardPresenter é criado em onLoadFinished() callback do 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();
}

Criar uma visualização de card

Nesta etapa, você vai criar o apresentador de card com um armazenador de visualização que descreve seus itens de conteúdo de mídia. Observe que cada apresentador precisa criar apenas um tipo de visualização. Se você tiver duas de visualização de card, serão necessários dois apresentadores de card.

No Presenter, implemente uma onCreateViewHolder() callback que cria um armazenador de visualização que pode ser usado para exibir um item de conteúdo:

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

No método onCreateViewHolder(), criar uma visualização de card para itens de conteúdo. O exemplo a seguir usa uma ImageCardView:

Quando um card é selecionado, o comportamento padrão o expande para um tamanho maior. Se você quiser designar uma cor diferente para o cartão selecionado, chame setSelected() conforme mostrado aqui:

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

Quando o usuário abre o app, o Presenter.ViewHolder exibe os objetos CardView dos itens de conteúdo. Você precisa defini-los para receber o foco do controlador de botão direcional chamando setFocusable(true) e setFocusableInTouchMode(true), conforme mostrado no código a seguir:

Kotlin

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

Java

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

Quando o usuário seleciona a ImageCardView, ela se expande para revelar a área de texto com a cor de fundo que você especificar, conforme mostrado na figura 1.