Utiliser les commandes de transport

Créez mieux avec Compose
Créez des interfaces utilisateur attrayantes avec un minimum de code à l'aide de Jetpack Compose pour l'OS Android TV.
<ph type="x-smartling-placeholder"></ph> Compose pour la télévision →

Le kit d'interface utilisateur Leanback propose des commandes de lecture qui améliorent l'expérience utilisateur. Pour les applications vidéo, les commandes de transport permettent de faire défiler la vidéo à l'aide des commandes de lecture et de retour en arrière. Lorsque vous utilisez la barre de lecture, des miniatures pour faciliter la navigation dans la vidéo.

La 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. L'utilisation du modèle vous pouvez créer rapidement une application riche en fonctionnalités, sans avoir à coder trop de code. 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 de le lecteur qui lit la vidéo. Cette opération repose sur deux éléments: un fragment de prise en charge de la lecture pour afficher les commandes de transport (et (ou éventuellement la vidéo) et un adaptateur pour lecteur encapsulant le 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:

Vous pouvez personnaliser ObjectAdapter pour améliorer l'UI. Par exemple, utilisez setAdapter() pour ajouter une ligne "Vidéos similaires".

PlayerAdapter

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 écrivez sa propre implémentation de cette classe.

Coller les pièces ensemble

Vous devez utiliser un "liant de contrôle" pour connecter le fragment de lecture au lecteur. Le Leanback propose deux types de colle:

colle de contrôle de transport Leanback

Si vous souhaitez que votre application prenne en charge le balayage vidéo, vous devez utiliser PlaybackTransportControlGlue.

Vous devez également spécifier un "hôte de liaison" qui lie la liaison au fragment de lecture, dessine les commandes de transport dans l'UI et maintient leur état, puis transmet les événements de contrôle de transport à la liaison. L'hôte doit correspondre au type de fragment de lecture. Utilisez PlaybackSupportFragmentGlueHost avec un PlaybackFragment VideoSupportFragmentGlueHost avec un VideoFragment

Voici une illustration montrant comment les éléments d'une commande de transport leanback s'imbriquent :

colle de contrôle de transport Leanback

Le code qui colle votre application doit se trouver dans le PlaybackSupportFragment ou le VideoSupportFragment qui définit l'UI.

Dans les exemple, l'application construit une instance de PlaybackTransportControlGlue, en la nommant playerGlue, et connecte son VideoSupportFragment à un MediaPlayerAdapter nouvellement créé. Depuis il s'agit d'un VideoSupportFragment. Le code de configuration appelle setHost() pour joindre un De 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és à deux groupes: les actions principales et les groupes secondaires actions. Les commandes du groupe principal apparaissent au-dessus de la barre de recherche. un groupe secondaire apparaît sous la barre de recherche. Au départ, il n'y a qu'une seule action principale pour le bouton de lecture/pause, et aucune action secondaire.

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 remplacer 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 mettre en œuvre PlaybackTransportRowPresenter pour afficher des commandes personnalisées et répondre aux actions de recherche à l'aide de PlaybackSeekUi

Barre de défilement de la vidéo

Si votre application utilise un VideoSupportFragment et que vous souhaitez prendre en charge le balayage de la vidéo.

frotter

Vous devez fournir une implémentation de PlaybackSeekDataProvider. Ce composant fournit les miniatures des vidéos utilisées lors du défilement. Vous devez implémenter votre propre fournisseur en étendant PlaybackSeekDataProvider. Consultez l'exemple dans l'application Showcase Leanback.