Le kit d'interface utilisateur Leanback comporte des commandes de lecture qui améliorent l'expérience utilisateur. Pour les applications vidéo, les commandes de transport sont compatibles avec le défilement vidéo à l'aide des commandes avant et arrière. Tout en frottant l'écran, vous verrez des miniatures pour faciliter la navigation dans la vidéo.
Cette bibliothèque inclut des classes abstraites ainsi que des implémentations prédéfinies et prêtes à l'emploi qui offrent un contrôle plus précis aux développeurs. Grâce aux implémentations prédéfinies, vous pouvez rapidement créer une application riche en fonctionnalités sans avoir à coder trop. Si vous avez besoin de plus de personnalisation, vous pouvez étendre n'importe quel composant prédéfini de la bibliothèque.
Commandes et lecteur
Le kit d'interface utilisateur Leanback sépare l'interface utilisateur des commandes de transport du lecteur qui lit la vidéo. Cette opération repose sur deux composants : un fragment de prise en charge de la lecture pour afficher les commandes de transport (et éventuellement la vidéo) et un adaptateur de lecteur pour encapsuler un lecteur multimédia.
Fragment de lecture
L'activité de l'interface utilisateur de votre application doit utiliser un PlaybackSupportFragment
ou un VideoSupportFragment
.
Tous deux contiennent les commandes de transport Leanback:
- Un
PlaybackSupportFragment
anime ses commandes de transport pour les masquer/les afficher si nécessaire. - Un
VideoSupportFragment
étendPlaybackSupportFragment
et comporte unSurfaceView
pour le rendu de la vidéo.
Vous pouvez personnaliser le ObjectAdapter
d'un fragment pour améliorer l'UI. Par exemple, utilisez setAdapter()
pour ajouter une ligne "vidéos similaires".
AdaptateurLecteur
PlayerAdapter
est une classe abstraite qui contrôle le lecteur multimédia sous-jacent. Les développeurs peuvent choisir l'implémentation MediaPlayerAdapter
prédéfinie ou écrire leur propre implémentation de cette classe.
Coller les pièces ensemble
Vous devez utiliser une "colle de contrôle" pour connecter le fragment de lecture au lecteur. La bibliothèque Leanback fournit deux types de colle:
PlaybackBannerControlGlue
dessine les commandes de transport dans l'"ancien style" dans le fragment de lecture et les place dans un arrière-plan opaque. (PlaybackBannerControlGlue
remplacePlaybackControlGlue
, qui est désormais obsolète.)PlaybackTransportControlGlue
utilise des commandes de "nouveau style" avec un arrière-plan transparent.
Si vous souhaitez que votre application soit compatible avec la barre de lecture vidéo, vous devez utiliser PlaybackTransportControlGlue
.
Vous devez également spécifier un "hôte Glue" qui lie la colle au fragment de lecture, dessine les commandes de transport dans l'interface utilisateur et conserve leur état, et transmet les événements de commande de transport à la colle. L'hôte doit correspondre au type de fragment de lecture. Utilisez PlaybackSupportFragmentGlueHost
avec un PlaybackFragment
et VideoSupportFragmentGlueHost
avec un VideoFragment
.
Voici une illustration montrant comment les éléments d'une commande de transport Leanback s'assemblent:
Le code qui colle votre application doit se trouver dans PlaybackSupportFragment
ou VideoSupportFragment
qui définit l'UI.
Dans l'exemple suivant, l'application construit une instance de PlaybackTransportControlGlue
, la nomme playerGlue
et connecte son VideoSupportFragment
à un MediaPlayerAdapter
nouvellement créé. Comme il s'agit d'un VideoSupportFragment
, le code de configuration appelle setHost()
pour associer un VideoSupportFragmentGlueHost
à playerGlue
. Le code est inclus dans la classe qui étend VideoSupportFragment
.
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)); } }
Notez que le code de configuration définit également un PlayerAdapter.Callback
pour gérer les événements du lecteur multimédia.
Personnaliser l'élément d'interface utilisateur
Vous pouvez personnaliser PlaybackBannerControlGlue
et PlaybackTransportControlGlue
pour modifier PlaybackControlsRow
.
Personnaliser le titre et la description
Pour personnaliser le titre et la description en haut des commandes de lecture, remplacez 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; }
Ajouter des commandes
L'élément "Control Glue" affiche les commandes des actions dans un PlaybackControlsRow
.
Les actions du PlaybackControlsRow
sont affectées à deux groupes: les actions principales et les actions secondaires. Les commandes du groupe principal s'affichent au-dessus de la barre de recherche, tandis que celles du groupe secondaire apparaissent sous la barre de recherche. Au départ, il n'y a qu'une seule action principale pour le bouton de lecture/pause, mais pas d'actions secondaires.
Vous pouvez ajouter des actions aux groupes principal et secondaire en remplaçant onCreatePrimaryActions()
et 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); }
Vous devez ignorer onActionClicked()
pour gérer les nouvelles actions.
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. }
Dans certains cas, vous pouvez implémenter votre propre PlaybackTransportRowPresenter
pour afficher des commandes personnalisées et répondre aux actions de recherche à l'aide de PlaybackSeekUi
.
Utiliser la barre de lecture
Si votre application utilise un VideoSupportFragment
et que vous souhaitez prendre en charge la barre de lecture vidéo
Vous devez fournir une implémentation de PlaybackSeekDataProvider
.
Ce composant fournit les miniatures de vidéos à utiliser lors du défilement.
Vous devez implémenter votre propre fournisseur en étendant PlaybackSeekDataProvider
.
Consultez l'exemple dans l'
application Leanback Showcase.