Udostępnianie widoku kart

Ulepszaj dzięki funkcji tworzenia wiadomości
Dzięki Jetpack Compose na system operacyjny Android TV możesz tworzyć atrakcyjne interfejsy użytkownika przy użyciu minimalnej ilości pisania.

Na poprzedniej lekcji utworzyliśmy przeglądarkę katalogów zaimplementowaną we fragmencie przeglądania, który wyświetla listę elementów multimedialnych. W tej lekcji utworzysz widoki kart dla swoich elementów multimedialnych i przedstawisz je we fragmencie przeglądania.

Klasa i podklasy BaseCardView wyświetlają metadane powiązane z elementem multimedialnym. Klasa ImageCardView użyta w tej lekcji wyświetla obraz treści wraz z tytułem elementu multimedialnego.

Zapoznaj się również z przykładową implementacją w przykładowej aplikacji Leanback.

Widok kart aplikacji

Rysunek 1. Widok karty obrazu przykładowej aplikacji Leanback po wybraniu.

Utwórz prezentację kart

Presenter generuje widoki danych i wiąże z nimi obiekty na żądanie. We fragmencie przeglądania, w którym Twoja aplikacja prezentuje treść użytkownikowi, tworzysz plik Presenter dla kart treści i przekazujesz go do adaptera, który dodaje treść do ekranu. W tym kodzie CardPresenter jest tworzony w wywołaniu zwrotnym 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();
}

Tworzenie widoku kart

W tym kroku utworzysz prezentację z widokiem kart, który opisuje Twoje elementy treści multimedialnych. Pamiętaj, że każdy prowadzący może utworzyć tylko jeden typ widoku. Jeśli masz 2 rodzaje widoku kart, potrzebujesz 2 prezenterów.

W Presenter zaimplementuj wywołanie zwrotne onCreateViewHolder(), które tworzy element widoku danych, którego można użyć do wyświetlenia elementu treści:

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

W metodzie onCreateViewHolder() utwórz widok kart dla elementów treści. W przykładzie poniżej użyto ImageCardView.

Po wybraniu karty domyślnie wyświetla się ona w większym rozmiarze. Aby dla wybranej karty wyznaczyć inny kolor, wywołaj setSelected() w następujący sposób:

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

Gdy użytkownik otworzy aplikację, Presenter.ViewHolder wyświetli obiekty CardView dla Twoich elementów treści. Musisz je skonfigurować, aby uaktywniać sterowanie padem kierunkowym przez wywołanie funkcji setFocusable(true) i setFocusableInTouchMode(true), jak pokazano w tym kodzie:

Kotlin

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

Java

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

Gdy użytkownik wybierze ImageCardView, rozwinie się, pokazując obszar tekstowy z określonym kolorem tła, jak widać na ilustracji 1.