Detailansicht erstellen

Besser lernen mit der Funktion „Schreiben“
Mit Jetpack Compose für Android TV OS lassen sich mit nur minimalem Code ansprechende UIs erstellen.

Die von der androidx.leanback-Bibliothek bereitgestellten Oberflächenklassen für das Durchsuchen von Medien enthalten Klassen zum Anzeigen zusätzlicher Informationen zu einem Medienelement, z. B. einer Beschreibung oder Rezensionen. Sie enthalten auch Klassen für die Durchführung von Aktionen im Zusammenhang mit diesem Artikel, wie etwa den Kauf oder die Wiedergabe seines Inhalts.

In diesem Leitfaden wird erläutert, wie Sie eine Vortragsklasse für Details zu Medienelementen erstellen und die Klasse DetailsSupportFragment erweitern, um eine Detailansicht für ein Medienelement zu implementieren, wenn der Nutzer diese auswählt.

Hinweis:In dem hier gezeigten Implementierungsbeispiel wird eine zusätzliche Aktivität zum Einbinden von DetailsSupportFragment verwendet. Sie können jedoch das Erstellen einer zweiten Aktivität vermeiden. Dazu ersetzen Sie BrowseSupportFragment durch einen DetailsSupportFragment innerhalb derselben Aktivität unter Verwendung von Fragmenttransaktionen. Weitere Informationen zur Verwendung von Fragmenttransaktionen finden Sie unter Fragment erstellen.

Detailpräsentation erstellen

Im Rahmen des Media Browsing-Frameworks, das vom Leanback-UI-Toolkit bereitgestellt wird, verwenden Sie Präsentationsobjekte, um die Anzeige von Daten auf dem Bildschirm zu steuern, einschließlich Details zu Medienelementen. Zu diesem Zweck stellt das Framework die Klasse AbstractDetailsDescriptionPresenter bereit, eine fast vollständige Implementierung des Presenters für Medienelementdetails. 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 du die DetailsSupportFragment-Klasse zum Anzeigen der Details deines Medienelements verwendest, erweitere diese Klasse, um zusätzliche Inhalte bereitzustellen, z. B. ein Vorschaubild und Aktionen für das Medienelement. Du kannst auch zusätzliche Inhalte bereitstellen, z. B. eine Liste ähnlicher Medienelemente.

Der folgende Beispielcode zeigt, wie mit der im vorherigen Abschnitt gezeigten Presenter-Klasse ein Vorschaubild und Aktionen für das wiedergegebene Medienelement hinzugefügt werden. In diesem Beispiel wird auch eine Zeile mit ähnlichen Medienelementen 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 das DetailsSupportFragment müssen in einer Aktivität enthalten sein, damit sie für die Anzeige verwendet werden können. Wenn Sie eine Aktivität für Ihre Detailansicht erstellen, die von der Suchaktivität getrennt ist, können Sie diese mit einem Intent aufrufen. In diesem Abschnitt wird erläutert, wie Sie eine Aktivität erstellen, die Ihre Implementierung der Detailansicht für Ihre Medienelemente enthält.

Erstellen Sie die Aktivität „Details“, 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. Denke daran, das Leanback-Design anzuwenden, um sicherzustellen, dass die Benutzeroberfläche mit der Mediensuche konsistent ist.

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

</application>

Listener für angeklickte Elemente definieren

Nachdem du DetailsSupportFragment implementiert hast, kannst du die Hauptansicht für die Mediensuche so ändern, dass sie zur Detailansicht wechselt, wenn ein Nutzer auf ein Medienelement klickt. Um dieses Verhalten zu aktivieren, fügen Sie dem BrowseSupportFragment ein OnItemViewClickedListener-Objekt hinzu, das einen Intent zum Starten der Aktivität zu den Elementdetails auslöst.

Das folgende Beispiel zeigt, wie du einen Listener implementierst, um die Detailansicht zu starten, wenn ein Nutzer auf ein Medienelement in der Hauptaktivität für die Mediensuche 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);
                }
            });
    }
}