Steuerelemente für die Übertragung verwenden

Bessere Apps mit Compose entwickeln
Mit Jetpack Compose für Android TV OS können Sie mit minimalem Code schöne Benutzeroberflächen erstellen.

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:

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 ersetzt PlaybackControlGlue, das eingestellt wurde.)
  • PlaybackTransportControlGlue verwendet Steuerelemente im „neuen Stil“ mit einem transparenten Hintergrund.

Leanback-Transportsteuerelemente

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:

Leanback-Transportsteuerelemente

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.

scheuern

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.