Biblioteka Leanback na Androidax zawiera nowe elementy sterujące odtwarzaniem, które zwiększają wygodę użytkowników. W aplikacjach wideo elementy sterujące transportem umożliwiają przewijanie filmu za pomocą elementów sterujących do przodu i do tyłu. Podczas przewijania ekranu widać miniatury ułatwiające poruszanie się po filmie.
Biblioteka obejmuje klasy abstrakcyjne, a także gotowe implementacje, które zapewniają programistom bardziej szczegółową kontrolę. Korzystając z gotowych implementacji, możesz szybko stworzyć aplikację oferującą wiele funkcji bez konieczności kodowania. Jeśli potrzebujesz większych możliwości dostosowywania, możesz rozszerzyć dowolne z gotowych komponentów biblioteki.
Sterowanie i odtwarzacz
Biblioteka leanback oddziela interfejs użytkownika od elementów sterujących odtwarzaniem treści wideo. Odbywa się to za pomocą 2 komponentów: fragmentu obsługującego odtwarzanie, który wyświetla elementy sterujące przesyłaniem (i opcjonalnie filmu), oraz adaptera odtwarzacza do umieszczania w nim odtwarzacza.
Fragment odtwarzania
Aktywność w interfejsie aplikacji powinna używać parametru PlaybackSupportFragment
lub VideoSupportFragment
.
Oba typy konfiguracji obejmują ustawienia funkcji leanback transport:
- Element
PlaybackSupportFragment
animuje swoje elementy sterujące transportem, aby je ukrywać i wyświetlać w razie potrzeby. - Element
VideoSupportFragment
rozszerzaPlaybackSupportFragment
i zawieraSurfaceView
do renderowania wideo.
Możesz dostosować ObjectAdapter
fragmentu, aby ulepszyć jego interfejs. Na przykład wpisz setAdapter()
, aby dodać wiersz „podobne filmy”.
AdapterAdapter
PlayerAdapter
to klasa abstrakcyjna, która steruje podstawowym odtwarzaczem. Deweloperzy mogą wybrać gotową implementację MediaPlayerAdapter
lub napisać własną implementację.
Sklejanie kawałków
Musisz użyć jakiegoś „kleju kontrolnego”, by połączyć fragment odtwarzania z odtwarzaczem. Biblioteka leanback zawiera 2 rodzaje kleju:
PlaybackBannerControlGlue
rysuje we fragmencie odtwarzania elementy sterujące transportem w „starym stylu”, umieszczając je na nieprzezroczystym tle. (PlaybackBannerControlGlue
zastępuje komponentPlaybackControlGlue
, który został wycofany).PlaybackTransportControlGlue
używa elementów sterujących nowego stylu z przezroczystym tłem.
Jeśli chcesz, aby aplikacja obsługiwała przewijanie wideo, musisz użyć właściwości PlaybackTransportControlGlue
.
Musisz też określić „host glue”, który wiąże klej z fragmentem odtwarzania, rysuje w interfejsie użytkownika elementy sterujące transportu i zachowuje ich stan oraz przekazuje zdarzenia sterowania transportem z powrotem do kleju. Host musi pasować do typu fragmentu odtwarzania. Użyj właściwości PlaybackSupportFragmentGlueHost
z atrybutem PlaybackFragment
, a VideoSupportFragmentGlueHost
– VideoFragment
.
Ilustracja pokazująca, jak elementy systemu leanback transport dopasowują się do siebie:
Kod, który łączy aplikację, powinien znajdować się wewnątrz obszaru PlaybackSupportFragment
lub VideoSupportFragment
, który określa interfejs użytkownika.
W poniższym przykładzie aplikacja tworzy wystąpienie PlaybackTransportControlGlue
o nazwie playerGlue
i łączy swoje VideoSupportFragment
z nowo utworzonym elementem MediaPlayerAdapter
. Ponieważ jest to VideoSupportFragment
, kod konfiguracji wywołuje metodę setHost()
, aby dołączyć VideoSupportFragmentGlueHost
do playerGlue
. Kod jest zawarty w klasie, która rozszerza 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)); } }
Pamiętaj, że kod konfiguracji określa też element PlayerAdapter.Callback
do obsługi zdarzeń z odtwarzacza.
Dostosowywanie kleju interfejsu
Możesz dostosować PlaybackBannerControlGlue
i PlaybackTransportControlGlue
, aby zmienić PlaybackControlsRow
.
Dostosowywanie tytułu i opisu
Aby dostosować tytuł i opis u góry elementów sterujących odtwarzaniem, zastąp 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; }
Dodawanie elementów sterujących
Klej kontrolny wyświetla elementy sterujące działaniami w elemencie PlaybackControlsRow
.
Działania w PlaybackControlsRow
są przypisywane do 2 grup: działań głównych i działań dodatkowych. Elementy sterujące grupy podstawowej znajdują się nad paskiem przewijania, a elementy sterujące grupy dodatkowej – pod paskiem przewijania. Na początku jest tylko jedno działanie główne
dla przycisku odtwarzania/wstrzymania. Nie są dostępne żadne działania dodatkowe.
Możesz dodać działania do grupy podstawowej i dodatkowej. W tym celu zastąp onCreatePrimaryActions()
i 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); }
Aby obsługiwać nowe działania, musisz zastąpić właściwość onActionClicked()
.
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. }
W szczególnych przypadkach możesz zaimplementować własne PlaybackTransportRowPresenter
, aby renderować niestandardowe elementy sterujące i reagować na działania związane z wyszukiwaniem za pomocą PlaybackSeekUi
.
Przewijanie filmu
Jeśli aplikacja korzysta z urządzenia VideoSupportFragment
i chcesz obsługiwać przewijanie wideo.
Musisz udostępnić implementację PlaybackSeekDataProvider
.
Ten komponent dostarcza miniatury filmów używane podczas przewijania.
Musisz wdrożyć własnego dostawcę, rozszerzając PlaybackSeekDataProvider
.
Zobacz ten przykład w
aplikacji Polecane Showcase.