Personalizações da IU

A Media3 fornece um PlayerView padrão com algumas opções de personalização. Para qualquer outra personalização, os desenvolvedores de apps precisam implementar os próprios componentes de interface.

Práticas recomendadas

Ao implementar uma interface de mídia que se conecta a um Player da Media3 (por exemplo, ExoPlayer, MediaController ou uma implementação personalizada de Player), aconselhamos os apps a seguir estas práticas recomendadas para ter a melhor experiência da interface.

Botão "Reproduzir/pausar"

O botão para reproduzir e pausar não corresponde diretamente a um único estado de player. Por exemplo, o usuário precisa conseguir reiniciar a reprodução depois que ela terminar ou falhar, mesmo que o player não esteja pausado.

Para simplificar a implementação, a Media3 oferece métodos utilitários para decidir qual botão mostrar (Util.shouldShowPlayButton) e processar os pressionamentos de botão (Util.handlePlayPauseButtonAction):

Kotlin

val shouldShowPlayButton: Boolean = Util.shouldShowPlayButton(player)
playPauseButton.setImageDrawable(if (shouldShowPlayButton) playDrawable else pauseDrawable)
playPauseButton.setOnClickListener { Util.handlePlayPauseButtonAction(player) }

Java

boolean shouldShowPlayButton = Util.shouldShowPlayButton(player);
playPauseButton.setImageDrawable(shouldShowPlayButton ? playDrawable : pauseDrawable);
playPauseButton.setOnClickListener(view -> Util.handlePlayPauseButtonAction(player));

Detectar atualizações de estado

O componente de interface precisa adicionar um Player.Listener para ser informado sobre mudanças de estado que exigem uma atualização de interface correspondente. Consulte Ouvir eventos de reprodução para mais detalhes.

A atualização da interface pode ser cara, e vários eventos de jogadores geralmente chegam juntos. Para evitar a atualização da interface com muita frequência em um curto período, geralmente é melhor detectar apenas onEvents e acionar atualizações da interface:

Kotlin

player.addListener(object : Player.Listener{
  override fun onEvents(player: Player, events: Player.Events){
    if (events.containsAny(
        Player.EVENT_PLAY_WHEN_READY_CHANGED,
        Player.EVENT_PLAYBACK_STATE_CHANGED,
        Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED)) {
      updatePlayPauseButton()
    }
    if (events.containsAny(Player.EVENT_REPEAT_MODE_CHANGED)) {
      updateRepeatModeButton()
    }
  }
})

Java

player.addListener(new Player.Listener() {
  @Override
  public void onEvents(Player player, Player.Events events) {
    if (events.containsAny(
        Player.EVENT_PLAY_WHEN_READY_CHANGED,
        Player.EVENT_PLAYBACK_STATE_CHANGED,
        Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED)) {
      updatePlayPauseButton();
    }
    if (events.containsAny(Player.EVENT_REPEAT_MODE_CHANGED)) {
      updateRepeatModeButton();
    }
  }
});

Gerenciar comandos disponíveis

Um componente de interface de uso geral que pode precisar trabalhar com diferentes implementações de Player precisa verificar os comandos disponíveis do player para mostrar ou ocultar botões e evitar chamar métodos sem suporte:

Kotlin

nextButton.isEnabled = player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT)

Java

nextButton.setEnabled(player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT));