Detailansicht erstellen

Bessere Apps mit Compose entwickeln
Mit Jetpack Compose für Android TV OS können Sie mit minimalem Code schöne Benutzeroberflächen erstellen.

Die von der eingestellten androidx.leanback-Bibliothek bereitgestellten Klassen für die Medienübersicht enthalten Klassen zum Anzeigen zusätzlicher Informationen zu einem Media-Element, z. B. einer Beschreibung oder Rezensionen. Sie enthalten auch Klassen für Aktionen, die für das Element ausgeführt werden können, z. B. zum Kaufen oder Abspielen der Inhalte.

In diesem Leitfaden wird beschrieben, wie Sie eine Presenter-Klasse für Details zu Media-Elementen erstellen und wie Sie die Klasse DetailsSupportFragment erweitern, um eine Detailansicht für ein Media-Element zu implementieren, wenn der Nutzer es auswählt.

Hinweis:Im hier gezeigten Implementierungsbeispiel wird eine zusätzliche Aktivität verwendet, um die DetailsSupportFragment zu enthalten. Es ist jedoch möglich, die Erstellung einer zweiten Aktivität zu vermeiden, indem Sie die BrowseSupportFragment durch eine DetailsSupportFragment innerhalb derselben Aktivität ersetzen. Verwenden Sie dazu Fragmenttransaktionen. Weitere Informationen zur Verwendung von Fragment-Transaktionen finden Sie unter Fragment erstellen.

Details-Presenter erstellen

Im Framework für das Durchsuchen von Medien, das vom Leanback UI-Toolkit bereitgestellt wird, verwenden Sie Presenter-Objekte, um die Anzeige von Daten auf dem Bildschirm zu steuern, einschließlich der Details zu Media-Elementen. Dazu stellt das Framework die Klasse AbstractDetailsDescriptionPresenter bereit, die eine nahezu vollständige Implementierung des Presenters für die Details von Media-Elementen ist. Sie müssen lediglich die Methode onBindDescription() implementieren, um die Ansichtsfelder an Ihre Datenobjekte zu binden, wie im folgenden Codebeispiel gezeigt:

Kotlin

class DetailsDescriptionPresenter : AbstractDetailsDescriptionPresenter() {

    override fun onBindDescription(viewHolder: AbstractDetailsDescriptionPresenter.ViewHolder, itemData: Any) {
        val details = itemData as MyMediaItemDetails
        // In a production app, the itemData object contains the information
        // needed to display details for the media item:
        // viewHolder.title.text = details.shortTitle

        // Here we provide static data for testing purposes:
        viewHolder.apply {
            title.text = itemData.toString()
            subtitle.text = "2014   Drama   TV-14"
            body.text = ("Lorem ipsum dolor sit amet, consectetur "
                    + "adipisicing elit, sed do eiusmod tempor incididunt ut labore "
                    + " et dolore magna aliqua. Ut enim ad minim veniam, quis "
                    + "nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
                    + "commodo consequat.")
        }
    }
}

Java

public class DetailsDescriptionPresenter
        extends AbstractDetailsDescriptionPresenter {

    @Override
    protected void onBindDescription(ViewHolder viewHolder, Object itemData) {
        MyMediaItemDetails details = (MyMediaItemDetails) itemData;
        // In a production app, the itemData object contains the information
        // needed to display details for the media item:
        // viewHolder.getTitle().setText(details.getShortTitle());

        // Here we provide static data for testing purposes:
        viewHolder.getTitle().setText(itemData.toString());
        viewHolder.getSubtitle().setText("2014   Drama   TV-14");
        viewHolder.getBody().setText("Lorem ipsum dolor sit amet, consectetur "
                + "adipisicing elit, sed do eiusmod tempor incididunt ut labore "
                + " et dolore magna aliqua. Ut enim ad minim veniam, quis "
                + "nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
                + "commodo consequat.");
    }
}

Detailfragment erweitern

Wenn Sie die Klasse DetailsSupportFragment verwenden, um die Details Ihres Media-Elements anzuzeigen, erweitern Sie diese Klasse, um zusätzliche Inhalte wie ein Vorschaubild und Aktionen für das Media-Element bereitzustellen. Sie können auch zusätzliche Inhalte wie eine Liste mit zugehörigen Media-Elementen angeben.

Der folgende Beispielcode zeigt, wie Sie mit der im vorherigen Abschnitt gezeigten Präsentationsklasse ein Vorschaubild und Aktionen für das angezeigte Media-Element hinzufügen. In diesem Beispiel wird auch eine Zeile mit zugehörigen Media-Elementen hinzugefügt, die unter der Detailauflistung angezeigt wird.

Kotlin

private const val TAG = "MediaItemDetailsFragment"

class MediaItemDetailsFragment : DetailsSupportFragment() {
    private lateinit var rowsAdapter: ArrayObjectAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        Log.i(TAG, "onCreate")
        super.onCreate(savedInstanceState)

        buildDetails()
    }

    private fun buildDetails() {
        val selector = ClassPresenterSelector().apply {
            // Attach your media item details presenter to the row presenter:
            FullWidthDetailsOverviewRowPresenter(DetailsDescriptionPresenter()).also {
                addClassPresenter(DetailsOverviewRow::class.java, it)
            }
            addClassPresenter(ListRow::class.java, ListRowPresenter())
        }
        rowsAdapter = ArrayObjectAdapter(selector)

        val res = activity.resources
        val detailsOverview = DetailsOverviewRow("Media Item Details").apply {

            // Add images and action buttons to the details view
            imageDrawable = res.getDrawable(R.drawable.jelly_beans)
            addAction(Action(1, "Buy $9.99"))
            addAction(Action(2, "Rent $2.99"))
        }
        rowsAdapter.add(detailsOverview)

        // Add a related items row
        val listRowAdapter = ArrayObjectAdapter(StringPresenter()).apply {
            add("Media Item 1")
            add("Media Item 2")
            add("Media Item 3")
        }
        val header = HeaderItem(0, "Related Items")
        rowsAdapter.add(ListRow(header, listRowAdapter))

        adapter = rowsAdapter
    }
}

Java

public class MediaItemDetailsFragment extends DetailsSupportFragment {
    private static final String TAG = "MediaItemDetailsFragment";
    private ArrayObjectAdapter rowsAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "onCreate");
        super.onCreate(savedInstanceState);

        buildDetails();
    }

    private void buildDetails() {
        ClassPresenterSelector selector = new ClassPresenterSelector();
        // Attach your media item details presenter to the row presenter:
        FullWidthDetailsOverviewRowPresenter rowPresenter =
            new FullWidthDetailsOverviewRowPresenter(
                new DetailsDescriptionPresenter());

        selector.addClassPresenter(DetailsOverviewRow.class, rowPresenter);
        selector.addClassPresenter(ListRow.class,
                new ListRowPresenter());
        rowsAdapter = new ArrayObjectAdapter(selector);

        Resources res = getActivity().getResources();
        DetailsOverviewRow detailsOverview = new DetailsOverviewRow(
                "Media Item Details");

        // Add images and action buttons to the details view
        detailsOverview.setImageDrawable(res.getDrawable(R.drawable.jelly_beans));
        detailsOverview.addAction(new Action(1, "Buy $9.99"));
        detailsOverview.addAction(new Action(2, "Rent $2.99"));
        rowsAdapter.add(detailsOverview);

        // Add a related items row
        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
                new StringPresenter());
        listRowAdapter.add("Media Item 1");
        listRowAdapter.add("Media Item 2");
        listRowAdapter.add("Media Item 3");
        HeaderItem header = new HeaderItem(0, "Related Items", null);
        rowsAdapter.add(new ListRow(header, listRowAdapter));

        setAdapter(rowsAdapter);
    }
}

Detailaktivität erstellen

Fragmente wie DetailsSupportFragment müssen in einer Aktivität enthalten sein, damit sie angezeigt werden können. Wenn Sie eine Aktivität für die Detailansicht erstellen, die sich von der Browseraktivität unterscheidet, können Sie die Detailansicht mit einem Intent aufrufen. In diesem Abschnitt wird beschrieben, wie Sie eine Aktivität erstellen, die die Implementierung der Detailansicht für Ihre Media-Elemente enthält.

Erstellen Sie die Detailansicht, indem Sie ein Layout erstellen, das auf Ihre Implementierung von DetailsSupportFragment verweist:

<!-- file: res/layout/details.xml -->

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.example.android.mediabrowser.MediaItemDetailsFragment"
    android:id="@+id/details_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
/>

Erstellen Sie als Nächstes eine Aktivitätsklasse, die das im vorherigen Codebeispiel gezeigte Layout verwendet:

Kotlin

class DetailsActivity : FragmentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.details)
    }
}

Java

public class DetailsActivity extends FragmentActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.details);
    }
}

Fügen Sie diese neue Aktivität schließlich dem Manifest hinzu. Denken Sie daran, das Leanback-Theme anzuwenden, damit die Benutzeroberfläche mit der Medienbrowsing-Aktivität übereinstimmt.

<application>
  ...
  <activity android:name=".DetailsActivity"
    android:exported="true"
    android:theme="@style/Theme.Leanback"/>

</application>

Listener für angeklickte Elemente definieren

Nachdem Sie DetailsSupportFragment implementiert haben, ändern Sie die Hauptansicht für das Durchsuchen von Medien so, dass die Detailansicht aufgerufen wird, wenn ein Nutzer auf ein Media-Element klickt. Fügen Sie zum Aktivieren dieses Verhaltens dem BrowseSupportFragment ein OnItemViewClickedListener-Objekt hinzu, das einen Intent auslöst, um die Aktivität mit den Artikeldetails zu starten.

Im folgenden Beispiel wird gezeigt, wie Sie einen Listener implementieren, um die Detailansicht zu starten, wenn ein Nutzer in der Hauptaktivität zum Durchsuchen von Medien auf ein Media-Element klickt:

Kotlin

class BrowseMediaActivity : FragmentActivity() {
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Create the media item rows
        buildRowsAdapter()

        // Add a listener for selected items
        browseFragment.onItemViewClickedListener = OnItemViewClickedListener { _, item, _, _ ->
            println("Media Item clicked: ${item}")
            val intent = Intent(this@BrowseMediaActivity, DetailsActivity::class.java).apply {
                // Pass the item information
                extras.putLong("id", item.getId())
            }
            startActivity(intent)
        }
    }
}

Java

public class BrowseMediaActivity extends FragmentActivity {
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        // Create the media item rows
        buildRowsAdapter();

        // Add a listener for selected items
        browseFragment.OnItemViewClickedListener(
            new OnItemViewClickedListener() {
                @Override
                public void onItemClicked(Object item, Row row) {
                    System.out.println("Media Item clicked: " + item.toString());
                    Intent intent = new Intent(BrowseMediaActivity.this,
                            DetailsActivity.class);
                    // Pass the item information
                    intent.getExtras().putLong("id", item.getId());
                    startActivity(intent);
                }
            });
    }
}