Das Leanback-UI-Toolkit enthält Wiedergabesteuerelemente, die für eine bessere Nutzerfreundlichkeit sorgen. Bei Video-Apps unterstützen die Transportsteuerelemente das Scrubbing von Videos mit den Vorwärts- und Rückwärtssteuerelementen. Beim Scrubben werden auf dem Display Thumbnails angezeigt, die die Navigation im Video erleichtern.
Die Bibliothek enthält abstrakte Klassen sowie vorgefertigte Implementierungen, die Entwicklern eine detailliertere Steuerung ermöglichen. Mit den vorgefertigten Implementierungen können Sie schnell eine funktionsreiche App erstellen, ohne viel programmieren zu müssen. Wenn Sie weitere Anpassungen benötigen, können Sie die vorgefertigten Komponenten der Bibliothek erweitern.
Steuerelemente und Player
Das Leanback UI-Toolkit trennt die Benutzeroberfläche der Transportsteuerelemente vom Player, der Videos wiedergibt. Dies wird mit zwei Komponenten erreicht: einem Fragment zur Wiedergabeunterstützung zum Anzeigen der Transportsteuerelemente (und optional des Videos) und einem Player-Adapter zum Kapseln eines Media-Players.
Wiedergabefragment
Die UI-Aktivität Ihrer App sollte ein PlaybackSupportFragment
oder ein VideoSupportFragment
verwenden.
Beide enthalten die Leanback-Transportsteuerelemente:
- Ein
PlaybackSupportFragment
animiert die Transportsteuerelemente, um sie bei Bedarf ein- oder auszublenden. - Ein
VideoSupportFragment
erstreckt sich überPlaybackSupportFragment
und hat einenSurfaceView
zum Rendern von Videos.
Sie können das ObjectAdapter
eines Fragments anpassen, um die Benutzeroberfläche zu optimieren. Verwenden Sie beispielsweise setAdapter()
, um eine Zeile mit ähnlichen Videos hinzuzufügen.
PlayerAdapter
PlayerAdapter
ist eine abstrakte Klasse, die den zugrunde liegenden Media Player steuert. Entwickler können die vorgefertigte MediaPlayerAdapter
-Implementierung auswählen oder eine eigene Implementierung dieser Klasse schreiben.
Die Teile zusammenfügen
Sie müssen eine Art „Kontrollkleber“ verwenden, um das Wiedergabefragment mit dem Player zu verbinden. Die Leanback-Bibliothek bietet zwei Arten von Glue:
- Mit
PlaybackBannerControlGlue
werden die Transportsteuerelemente im Wiedergabefragment im „alten Stil“ gezeichnet und in einem undurchsichtigen Hintergrund platziert. (PlaybackBannerControlGlue
ersetztPlaybackControlGlue
, das eingestellt wurde.) PlaybackTransportControlGlue
verwendet Steuerelemente im „neuen Stil“ mit einem transparenten Hintergrund.
Wenn Ihre App das Scrubbing von Videos unterstützen soll, müssen Sie PlaybackTransportControlGlue
verwenden.
Außerdem müssen Sie einen „Glue-Host“ angeben, der den Glue an das Wiedergabefragment bindet, die Transportsteuerelemente in der Benutzeroberfläche rendert und ihren Status beibehält und Transportsteuerelementereignisse an den Glue zurückgibt. Der Host muss mit dem Typ des Wiedergabefragments übereinstimmen. Verwende PlaybackSupportFragmentGlueHost
mit einem PlaybackFragment
und VideoSupportFragmentGlueHost
mit einem VideoFragment
.
Hier sehen Sie eine Abbildung, die zeigt, wie die einzelnen Teile einer Leanback-Transportsteuerung zusammenpassen:
Der Code, der Ihre App zusammenfügt, sollte sich in der PlaybackSupportFragment
oder VideoSupportFragment
befinden, die die Benutzeroberfläche definiert.
Im folgenden Beispiel erstellt die App eine Instanz von PlaybackTransportControlGlue
mit dem Namen playerGlue
und verbindet deren VideoSupportFragment
mit einem neu erstellten MediaPlayerAdapter
. Da es sich um ein VideoSupportFragment
handelt, ruft der Einrichtungscode setHost()
auf, um ein VideoSupportFragmentGlueHost
an playerGlue
anzuhängen. Der Code ist in der Klasse enthalten, die VideoSupportFragment
erweitert.
Kotlin
class MyVideoFragment : VideoSupportFragment() { fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) val playerGlue = PlaybackTransportControlGlue(getActivity(), MediaPlayerAdapter(getActivity())) playerGlue.setHost(VideoSupportFragmentGlueHost(this)) playerGlue.addPlayerCallback(object : PlaybackGlue.PlayerCallback() { override fun onPreparedStateChanged(glue: PlaybackGlue) { if (glue.isPrepared()) { playerGlue.seekProvider = MySeekProvider() playerGlue.play() } } }) playerGlue.setSubtitle("Leanback artist") playerGlue.setTitle("Leanback team at work") val uriPath = "android.resource://com.example.android.leanback/raw/video" playerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath)) } }
Java
public class MyVideoFragment extends VideoSupportFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final PlaybackTransportControlGlue<MediaPlayerAdapter> playerGlue = new PlaybackTransportControlGlue(getActivity(), new MediaPlayerAdapter(getActivity())); playerGlue.setHost(new VideoSupportFragmentGlueHost(this)); playerGlue.addPlayerCallback(new PlaybackGlue.PlayerCallback() { @Override public void onPreparedStateChanged(PlaybackGlue glue) { if (glue.isPrepared()) { playerGlue.setSeekProvider(new MySeekProvider()); playerGlue.play(); } } }); playerGlue.setSubtitle("Leanback artist"); playerGlue.setTitle("Leanback team at work"); String uriPath = "android.resource://com.example.android.leanback/raw/video"; playerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath)); } }
Im Einrichtungscode wird auch ein PlayerAdapter.Callback
definiert, um Ereignisse vom Media-Player zu verarbeiten.
UI-Glue anpassen
Sie können das PlaybackBannerControlGlue
und PlaybackTransportControlGlue
anpassen, um das PlaybackControlsRow
zu ändern.
Titel und Beschreibung anpassen
Wenn Sie den Titel und die Beschreibung oben in den Wiedergabesteuerelementen anpassen möchten, überschreiben Sie onCreateRowPresenter()
:
Kotlin
override fun onCreateRowPresenter(): PlaybackRowPresenter { return super.onCreateRowPresenter().apply { (this as? PlaybackTransportRowPresenter) ?.setDescriptionPresenter(MyCustomDescriptionPresenter()) } }
Java
@Override protected PlaybackRowPresenter onCreateRowPresenter() { PlaybackTransportRowPresenter presenter = (PlaybackTransportRowPresenter) super.onCreateRowPresenter(); presenter.setDescriptionPresenter(new MyCustomDescriptionPresenter()); return presenter; }
Steuerelemente hinzufügen
Im Control-Glue werden Steuerelemente für Aktionen in einem PlaybackControlsRow
angezeigt.
Die Aktionen in PlaybackControlsRow
sind zwei Gruppen zugewiesen: primäre Aktionen und sekundäre Aktionen. Die Steuerelemente für die primäre Gruppe werden über der Suchleiste und die Steuerelemente für die sekundäre Gruppe unter der Suchleiste angezeigt. Anfangs gibt es nur eine primäre Aktion für die Schaltfläche „Wiedergabe/Pause“ und keine sekundären Aktionen.
Sie können den primären und sekundären Gruppen Aktionen hinzufügen, indem Sie onCreatePrimaryActions()
und onCreateSecondaryActions()
überschreiben.
Kotlin
private lateinit var repeatAction: PlaybackControlsRow.RepeatAction private lateinit var pipAction: PlaybackControlsRow.PictureInPictureAction private lateinit var thumbsUpAction: PlaybackControlsRow.ThumbsUpAction private lateinit var thumbsDownAction: PlaybackControlsRow.ThumbsDownAction private lateinit var skipPreviousAction: PlaybackControlsRow.SkipPreviousAction private lateinit var skipNextAction: PlaybackControlsRow.SkipNextAction private lateinit var fastForwardAction: PlaybackControlsRow.FastForwardAction private lateinit var rewindAction: PlaybackControlsRow.RewindAction override fun onCreatePrimaryActions(primaryActionsAdapter: ArrayObjectAdapter) { // Order matters, super.onCreatePrimaryActions() will create the play / pause action. // Will display as follows: // play/pause, previous, rewind, fast forward, next // > /|| |< << >> >| super.onCreatePrimaryActions(primaryActionsAdapter) primaryActionsAdapter.apply { add(skipPreviousAction) add(rewindAction) add(fastForwardAction) add(skipNextAction) } } override fun onCreateSecondaryActions(adapter: ArrayObjectAdapter?) { super.onCreateSecondaryActions(adapter) adapter?.apply { add(thumbsDownAction) add(thumbsUpAction) } }
Java
private PlaybackControlsRow.RepeatAction repeatAction; private PlaybackControlsRow.PictureInPictureAction pipAction; private PlaybackControlsRow.ThumbsUpAction thumbsUpAction; private PlaybackControlsRow.ThumbsDownAction thumbsDownAction; private PlaybackControlsRow.SkipPreviousAction skipPreviousAction; private PlaybackControlsRow.SkipNextAction skipNextAction; private PlaybackControlsRow.FastForwardAction fastForwardAction; private PlaybackControlsRow.RewindAction rewindAction; @Override protected void onCreatePrimaryActions(ArrayObjectAdapter primaryActionsAdapter) { // Order matters, super.onCreatePrimaryActions() will create the play / pause action. // Will display as follows: // play/pause, previous, rewind, fast forward, next // > /|| |< << >> >| super.onCreatePrimaryActions(primaryActionsAdapter); primaryActionsAdapter.add(skipPreviousAction); primaryActionsAdapter.add(rewindAction); primaryActionsAdapter.add(fastForwardAction); primaryActionsAdapter.add(skipNextAction); } @Override protected void onCreateSecondaryActions(ArrayObjectAdapter adapter) { super.onCreateSecondaryActions(adapter); adapter.add(thumbsDownAction); adapter.add(thumbsUpAction); }
Sie müssen onActionClicked()
überschreiben, um die neuen Aktionen zu verarbeiten.
Kotlin
override fun onActionClicked(action: Action) { when(action) { rewindAction -> { // Handle Rewind } fastForwardAction -> { // Handle FastForward } thumbsDownAction -> { // Handle ThumbsDown } thumbsUpAction -> { // Handle ThumbsUp } else -> // The superclass handles play/pause and delegates next/previous actions to abstract methods, // so those two methods should be overridden rather than handling the actions here. super.onActionClicked(action) } } override fun next() { // Skip to next item in playlist. } override fun previous() { // Skip to previous item in playlist. }
Java
@Override public void onActionClicked(Action action) { if (action == rewindAction) { // Handle Rewind } else if (action == fastForwardAction ) { // Handle FastForward } else if (action == thumbsDownAction) { // Handle ThumbsDown } else if (action == thumbsUpAction) { // Handle ThumbsUp } else { // The superclass handles play/pause and delegates next/previous actions to abstract methods, // so those two methods should be overridden rather than handling the actions here. super.onActionClicked(action); } } @Override public void next() { // Skip to next item in playlist. } @Override public void previous() { // Skip to previous item in playlist. }
In besonderen Fällen möchten Sie möglicherweise Ihre eigene PlaybackTransportRowPresenter
implementieren, um benutzerdefinierte Steuerelemente zu rendern und mit der PlaybackSeekUi
auf Suchvorgänge zu reagieren.
Video-Scrubbing
Wenn Ihre App VideoSupportFragment
verwendet und Sie das Vorspulen von Videos unterstützen möchten.
Sie müssen eine Implementierung von PlaybackSeekDataProvider
bereitstellen.
Diese Komponente stellt die Video-Thumbnails bereit, die beim Scrollen verwendet werden.
Sie müssen Ihren eigenen Anbieter implementieren, indem Sie PlaybackSeekDataProvider
erweitern.
Ein Beispiel finden Sie in der
Leanback Showcase App.