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