O kit de ferramentas de interface do usuário do YouTube tem controles de reprodução que oferecem uma interface experiência do usuário. Para apps de vídeo, os controles de transporte são compatíveis com a barra de progressão de vídeo. com os controles para frente e para trás. Ao arrastar o marcador, a tela mostra miniaturas para ajudar a navegar pelo vídeo.
A biblioteca inclui classes abstratas, bem como implementações pré-criadas e prontas para uso. que oferecem controle mais granular para os desenvolvedores. Usando o modelo você pode criar rapidamente um app repleto de recursos sem muita programação. Se precisar de mais personalização, você pode estender qualquer um dos componentes de solução.
Controles e player
O kit de ferramentas de interface do Leanback separa a interface de controles de transporte da o player que reproduz o vídeo. Isso é realizado com dois componentes: um fragmento de suporte à reprodução para exibir os controles de transporte (e opcionalmente o vídeo) e um adaptador de player para encapsular um player de mídia.
Fragmento de reprodução
A atividade da interface do seu app precisa usar uma
PlaybackSupportFragment
ou um
VideoSupportFragment
.
Ambos contêm os controles de transporte da leanback:
- Um
PlaybackSupportFragment
cria animações para ocultar/exibir os controles de transporte conforme necessário. - Um
VideoSupportFragment
estendePlaybackSupportFragment
e tem umSurfaceView
para renderizar vídeo.
É possível personalizar a
ObjectAdapter
para aprimorar a interface. Por exemplo, use
setAdapter()
para adicionar um "vídeos relacionados" linha de comando.
PlayerAdapter
PlayerAdapter
é uma classe abstrata que
controla o player de mídia subjacente. Os desenvolvedores podem escolher
a implementação pré-criada de MediaPlayerAdapter
ou
a própria implementação dessa classe.
Agrupar as partes
Use um "cola de controle" para conectar o fragmento de reprodução ao player. O botão de relaxamento fornece dois tipos de cola:
PlaybackBannerControlGlue
desenha o controles de transporte no fragmento de reprodução no "estilo antigo", colocando-os dentro de um fundo opaco. (PlaybackBannerControlGlue
) substituiPlaybackControlGlue
, que foi descontinuada.PlaybackTransportControlGlue
usa "novo estilo" com um plano de fundo transparente.
Se você quiser que seu app ofereça suporte à barra de progressão de vídeo, use
PlaybackTransportControlGlue
:
Você também precisa especificar um "host cola" que
vincula a cola à reprodução
de imagens, desenha os controles de transporte na IU e mantém o estado deles e
transmite os eventos de controle de transporte de volta para o agrupador. O host precisa corresponder ao tipo do fragmento de reprodução. Usar
PlaybackSupportFragmentGlueHost
com
um PlaybackFragment
e
VideoSupportFragmentGlueHost
com um
VideoFragment
.
Esta é uma ilustração que mostra como as peças do controle de transporte do Flix se encaixam:
O código que une seu aplicativo deve estar dentro da
PlaybackSupportFragment
ou VideoSupportFragment
que define a interface.
Nos seguintes
exemplo, o app cria uma instância de PlaybackTransportControlGlue
,
dê o nome playerGlue
a ele.
e conecta o VideoSupportFragment
a um MediaPlayerAdapter
recém-criado. Como
este é um VideoSupportFragment
. O código de configuração chama setHost()
para anexar um
VideoSupportFragmentGlueHost
para playerGlue
. O código é incluído na classe
que estende o 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)); } }
O código de configuração também define um PlayerAdapter.Callback
para processar eventos do
o player de mídia.
Personalizar o agrupador da IU
Você pode personalizar
PlaybackBannerControlGlue
e PlaybackTransportControlGlue
para alterar
PlaybackControlsRow
Personalizar o título e a descrição
Para personalizar o título e a descrição na parte superior do
controles de mídia, substituir
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; }
Adicionar controles
O agrupador de controles exibe controles para ações em uma PlaybackControlsRow
.
as ações no PlaybackControlsRow
;
são atribuídas a dois grupos: ações principais e secundárias
ações personalizadas. Os controles para o grupo principal aparecem acima da barra de busca e dos controles do
grupo secundário aparecem abaixo da barra de busca. Inicialmente, há apenas uma ação principal
para o botão reproduzir/pausar e nenhuma ação secundária.
Para adicionar ações aos grupos principal e secundário, substitua
onCreatePrimaryActions()
e
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); }
Você deve substituir
onActionClicked()
para processar as novas ações.
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. }
Em casos especiais, convém implementar seus próprios
PlaybackTransportRowPresenter
para renderizar controles personalizados e responder a ações de busca usando o
PlaybackSeekUi
.
Barra de progressão de vídeo
Se seu app usa um VideoSupportFragment
e você quer compatibilizar com barra de progressão de vídeo.
Você
precisa fornecer uma implementação de PlaybackSeekDataProvider
.
Esse componente exibe miniaturas no vídeo que são usadas ao mover a barra.
Você precisa implementar seu próprio provedor, estendendo
PlaybackSeekDataProvider
:
Confira o exemplo na
App Leanback Showcase (link em inglês).
,