Leanback-Transportsteuerelemente verwenden

Die Leanback-Androidx-Bibliothek verfügt über neue Wiedergabesteuerungen, die eine verbesserte Nutzererfahrung bieten. Bei Video-Apps unterstützen die Transportsteuerelemente das Video-Scrubbing mit den Vorwärts- und Rückwärtssteuerelementen. Beim Scrubbing werden Thumbnails angezeigt, die die Navigation durch das Video erleichtern.

Die Bibliothek enthält abstrakte Klassen sowie vorkonfigurierte Implementierungen, die Entwicklern eine detailliertere Kontrolle ermöglichen. Mithilfe der vordefinierten Implementierungen können Sie schnell und ohne viel Programmierung eine App mit vielen Funktionen erstellen. Wenn Sie weitere Anpassungen vornehmen möchten, können Sie die vordefinierten Komponenten der Bibliothek erweitern.

Steuerelemente und Player

Die Leanback-Bibliothek trennt die UI mit den Transportsteuerelementen vom Player, der das Video abspielt. Dies wird mit zwei Komponenten erreicht: einem Wiedergabeunterstützungsfragment zum Anzeigen der Transportsteuerelemente (und optional des Videos) und einem Playeradapter zum Kapseln eines Mediaplayers.

Wiedergabefragment

Die UI-Aktivitäten Ihrer App sollten PlaybackSupportFragment oder VideoSupportFragment verwenden. Beide beinhalten die Leanback-Transportsteuerelemente:

Sie können die ObjectAdapter eines Fragments anpassen, um die UI zu optimieren. Verwenden Sie beispielsweise setAdapter(), um eine Zeile „Ähnliche Videos“ hinzuzufügen.

PlayerAdapter

PlayerAdapter ist eine abstrakte Klasse, die den zugrunde liegenden Mediaplayer steuert. Entwickler können die vordefinierte MediaPlayerAdapter-Implementierung auswählen oder ihre eigene Implementierung dieser Klasse schreiben.

Die Teile zusammenkleben

Du musst etwas Kontrollkleber verwenden, um das Wiedergabefragment mit dem Player zu verbinden. Die Leanback-Bibliothek bietet zwei Arten von Klebstoff:

Leanback Transport Control Kleber

Wenn deine App das Video-Scrubbing unterstützen soll, musst du PlaybackTransportControlGlue verwenden.

Außerdem müssen Sie einen „Glue Host“ angeben, der den Glue an das Wiedergabefragment bindet, die Transportsteuerelemente in der UI zieht, ihren Status beibehält und Transportsteuerungsereignisse zurück an den Klee übergibt. Der Host muss dem Wiedergabefragmenttyp entsprechen. Verwenden Sie PlaybackSupportFragmentGlueHost mit einem PlaybackFragment und VideoSupportFragmentGlueHost mit einem VideoFragment.

In der folgenden Abbildung wird gezeigt, wie die einzelnen Teile eines Leanback-Steuerelements zusammenpassen:

Leanback Transport Control Kleber

Der Code, mit dem die App verbunden wird, sollte sich innerhalb des PlaybackSupportFragment- oder VideoSupportFragment-Elements befinden, das die UI definiert.

Im folgenden Beispiel erstellt die Anwendung eine Instanz von PlaybackTransportControlGlue und nennt diese playerGlue und verbindet ihre VideoSupportFragment mit einer neu erstellten MediaPlayerAdapter. Da dies ein VideoSupportFragment ist, ruft der Einrichtungscode setHost() auf, um eine VideoSupportFragmentGlueHost an playerGlue anzuhängen. Der Code ist in der Klasse enthalten, die 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));
  }
}

Der Einrichtungscode definiert auch einen PlayerAdapter.Callback, um Ereignisse aus dem Mediaplayer zu verarbeiten.

UI-Glue anpassen

Sie können PlaybackBannerControlGlue und PlaybackTransportControlGlue anpassen, um PlaybackControlsRow zu ändern.

Titel und Beschreibung anpassen

Wenn du den Titel und die Beschreibung oben in den Wiedergabesteuerelementen 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

Mit dem Steuerelement werden Steuerelemente für Aktionen in einem PlaybackControlsRow angezeigt.

Die Aktionen in der PlaybackControlsRow sind zwei Gruppen zugewiesen: primären Aktionen und sekundären Aktionen. Die Steuerelemente für die primäre Gruppe werden über der Suchleiste angezeigt, die für die sekundäre Gruppe darunter. Zu Beginn gibt es nur eine einzige primäre Aktion für die Wiedergabe-/Pausenschaltfläche. 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 Sonderfällen kann es sinnvoll sein, einen eigenen PlaybackTransportRowPresenter zu implementieren, um benutzerdefinierte Steuerelemente zu rendern und mit PlaybackSeekUi auf Suchaktionen zu reagieren.

Video-Scrubbing

Wenn deine App VideoSupportFragment verwendet und du Video-Scrubbing unterstützen möchtest

scheuern

Sie müssen eine Implementierung von PlaybackSeekDataProvider angeben. Diese Komponente stellt die Video-Thumbnails bereit, die beim Scrollen verwendet werden. Sie müssen Ihren eigenen Anbieter implementieren und dazu PlaybackSeekDataProvider erweitern. Sehen Sie sich dazu das Beispiel in der Leanback Showcase-App an.