Das Leanback-UI-Toolkit verfügt über Steuerelemente für die Wiedergabe, die eine verbesserte User Experience ausmacht. Bei Video-Apps unterstützen die Transportsteuerungen das Überspringen von Videoinhalten mit den Steuerelementen „Vorwärts“ und „Rückwärts“. Während des Scrubbings werden auf dem Display Thumbnails angezeigt, die die Navigation durch das Video erleichtern.
Die Bibliothek enthält abstrakte Klassen sowie vorgefertigte, sofort einsatzbereite Implementierungen, die Entwicklern eine detailliertere Kontrolle bieten. Vordefinierte Implementierungen können Sie schnell und ohne Programmieraufwand eine App mit vielen Funktionen erstellen. Wenn Sie weitere Anpassungen benötigen, können Sie alle vordefinierten Komponenten.
Steuerelemente und Player
Das Leanback-UI-Toolkit trennt die UI für Transportsteuerelemente von der dem Player, der das Video wiedergibt. Dies wird durch zwei Komponenten erreicht: ein Wiedergabe-Unterstützungsfragment zum Anzeigen der Transportsteuerelemente (und optional das Video) und einen Player-Adapter zum kapseln eines Mediaplayers.
Wiedergabefragment
Für die UI-Aktivität Ihrer App sollte ein
PlaybackSupportFragment
oder
VideoSupportFragment
.
Beide enthalten die Steuerelemente für den Leanback-Transport:
- Ein
PlaybackSupportFragment
animiert die Transportsteuerung, um sie bei Bedarf auszublenden oder einzublenden. - Ein
VideoSupportFragment
erweitertPlaybackSupportFragment
und hat eineSurfaceView
zum Rendern von Videos.
Sie können die
ObjectAdapter
um die Benutzeroberfläche zu verbessern. Verwenden Sie beispielsweise
setAdapter()
um ein ähnliches Video Zeile.
Player-Adapter
PlayerAdapter
ist eine abstrakte Klasse, die den zugrunde liegenden Mediaplayer steuert. Entwickler können die vordefinierte MediaPlayerAdapter
-Implementierung auswählen oder eine eigene Implementierung dieser Klasse schreiben.
Die Teile zusammenkleben
Du musst „Kontrollkleber“ verwenden zum Verbinden des Wiedergabefragments für den Player. Die Leanback-Bibliothek bietet zwei Arten von Klebemitteln:
PlaybackBannerControlGlue
zieht die Transportsteuerelementen im Wiedergabefragment im "alten Stil", in einem undurchsichtigen Hintergrund. (PlaybackBannerControlGlue
ersetztPlaybackControlGlue
, das eingestellt wurde.)PlaybackTransportControlGlue
verwendet „new style“ die Steuerelemente vor einem transparenten Hintergrund.
Wenn deine App Video-Scrubbing unterstützen soll, musst du
PlaybackTransportControlGlue
Sie müssen auch einen „Glue Host“ angeben das
bindet den Klebstoff an die Wiedergabe
fragmentiert, zeichnet die Transportsteuerelemente in der Benutzeroberfläche auf und behält ihren Status bei
Transportsteuerungsereignisse zurück an den Kleber. Der Host muss dem Wiedergabefragmenttyp entsprechen. Verwende PlaybackSupportFragmentGlueHost
mit PlaybackFragment
und VideoSupportFragmentGlueHost
mit VideoFragment
.
Hier ist eine Abbildung, die zeigt, wie die einzelnen Elemente einer zusammenpassen:
Der Code, der Ihre App zusammenhält, sollte sich in der PlaybackSupportFragment
oder VideoSupportFragment
befinden, die die Benutzeroberfläche definiert.
Im folgenden Beispiel erstellt die App eine Instanz von PlaybackTransportControlGlue
, benennt sie playerGlue
und verbindet ihre VideoSupportFragment
mit einer neu erstellten MediaPlayerAdapter
. Da es sich um ein VideoSupportFragment
handelt, ruft der Einrichtungscode setHost()
auf, um playerGlue
eine VideoSupportFragmentGlueHost
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 ist auch ein PlayerAdapter.Callback
definiert, um Ereignisse aus
im Mediaplayer an.
UI-Kleber anpassen
Sie können anpassen
PlaybackBannerControlGlue
und PlaybackTransportControlGlue
zum Ändern der
PlaybackControlsRow
Titel und Beschreibung anpassen
Wenn du den Titel und die Beschreibung oben in den Wiedergabesteuerungen anpassen möchtest, überschreibe 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
Der Steuerelement-Glue zeigt Steuerelemente für Aktionen in einer PlaybackControlsRow
an.
Die Aktionen in PlaybackControlsRow
sind zwei Gruppen zugewiesen: primäre Aktionen und sekundär.
Aktionen. Die Steuerelemente für die primäre Gruppe werden über der Suchleiste angezeigt und die Steuerelemente für die sekundäre Gruppe werden unterhalb der Suchleiste angezeigt. Anfangs gibt es nur eine primäre Aktion
für die Schaltfläche für Wiedergabe/Pause und keine sekundären Aktionen.
Sie können der primären und sekundären Gruppe Aktionen hinzufügen, indem Sie
onCreatePrimaryActions()
und
onCreateSecondaryActions()
.
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 bestimmten Fällen kann es sinnvoll sein, eine eigene PlaybackTransportRowPresenter
zu implementieren, um benutzerdefinierte Steuerelemente zu rendern und mit der PlaybackSeekUi
auf Suchaktionen zu reagieren.
Video-Scrubbing
Ob deine App ein VideoSupportFragment
verwendet und das Video-Scrubbing unterstützen möchtest.
Sie müssen eine Implementierung von PlaybackSeekDataProvider
bereitstellen.
Diese Komponente enthält die Video-Thumbnails, die beim Scrollen verwendet werden.
Sie müssen Ihren eigenen Anbieter implementieren,
PlaybackSeekDataProvider
Sehen Sie sich das Beispiel in der Leanback Showcase App an.