Detailansicht erstellen

Die Klassen für das Browsen von Medien, die von der Leanback-Androidx-Bibliothek bereitgestellt werden, enthalten Klassen zum Anzeigen zusätzlicher Informationen zu einem Medienelement, z. B. einer Beschreibung oder Rezensionen. Sie umfassen auch Klassen, mit denen Aktionen in Bezug auf dieses Element ausgeführt werden können, z. B. das Kaufen oder Abspielen von Inhalten.

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

Hinweis: Im hier gezeigten Implementierungsbeispiel wird eine zusätzliche Aktivität verwendet, um das DetailsSupportFragment zu enthalten. Sie können jedoch das Erstellen einer zweiten Aktivität vermeiden, indem Sie BrowseSupportFragment mithilfe von Fragmenttransaktionen durch einen DetailsSupportFragment innerhalb derselben Aktivität ersetzen. Weitere Informationen zum Verwenden von Fragmenttransaktionen finden Sie unter Fragmente erstellen.

Detailpräsentation erstellen

Im Media Browsing-Framework, das von der Leanback-Bibliothek bereitgestellt wird, steuern Sie mit Presenter-Objekten die Anzeige von Daten auf dem Bildschirm, einschließlich Details zu Medienelementen. Zu diesem Zweck stellt das Framework die Klasse AbstractDetailsDescriptionPresenter bereit, bei der es sich um eine fast vollständige Implementierung des Präsentierenden für Details zu Medienelementen handelt. 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 zum Anzeigen der Details Ihres Medienelements verwenden, erweitern Sie diese Klasse, um zusätzliche Inhalte wie ein Vorschaubild und Aktionen für das Medienelement bereitzustellen. Sie können auch zusätzliche Inhalte zur Verfügung stellen, z. B. eine Liste zugehöriger Medienelemente.

Der folgende Beispielcode zeigt, wie Sie mit der im vorherigen Abschnitt gezeigten Presenter-Klasse ein Vorschaubild und Aktionen für das angezeigte Medienelement hinzufügen. In diesem Beispiel wird auch eine Zeile mit zugehörigen Medienelementen hinzugefügt, die unter der Detailliste 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 unabhängig von der Suchaktivität eine Aktivität für die Detailansicht erstellen, können Sie die Detailansicht mit einer 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“ und erstellen Sie ein Layout, 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ätsgruppe, 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 zum Manifest hinzu. Wenden Sie das Leanback-Design an, um sicherzustellen, dass die Benutzeroberfläche der Mediensuche entspricht.

<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, ändere die Hauptansicht für die Mediensuche so, dass zur Detailansicht gewechselt wird, 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 ein Listener implementiert wird, um die Detailansicht zu starten, wenn ein Nutzer in der primären Medien-Browseraktivität auf ein Medienelement 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);
                }
            });
    }
}