Media3 предоставляет стандартный PlayerView , который предлагает некоторые параметры настройки.
Переопределить ресурсы отрисовки
PlayerView использует PlayerControlView для отображения элементов управления воспроизведением и индикатора выполнения. Используемые PlayerControlView графические ресурсы могут быть переопределены ресурсами с теми же именами, определенными в вашем приложении. Список переопределенных графических ресурсов для элементов управления см. в документации PlayerControlView .
Для дальнейшей настройки разработчики приложений должны самостоятельно реализовывать компоненты пользовательского интерфейса. Однако вот несколько рекомендаций, которые помогут вам начать.
Передовые методы
При разработке пользовательского интерфейса для работы с медиафайлами, подключающегося к Player Media3 (например, ExoPlayer , MediaController или собственной реализации Player ), приложениям рекомендуется следовать этим рекомендациям для обеспечения наилучшего пользовательского опыта.
Кнопка воспроизведения/паузы
Кнопки воспроизведения и паузы не соответствуют напрямую состоянию отдельного проигрывателя. Например, пользователь должен иметь возможность возобновить воспроизведение после его завершения или сбоя, даже если проигрыватель не находится на паузе.
Для упрощения реализации Media3 предоставляет вспомогательные методы для определения того, какую кнопку отображать ( Util.shouldShowPlayButton ), и для обработки нажатий кнопок ( Util.handlePlayPauseButtonAction ):
Котлин
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));
Слушайте обновления из штата
Компонент пользовательского интерфейса должен добавить обработчик Player.Listener , чтобы получать уведомления об изменениях состояния, требующих соответствующего обновления пользовательского интерфейса. Подробнее см. в разделе «Прослушивание событий воспроизведения» .
Обновление пользовательского интерфейса может быть затратным процессом, и события, связанные с несколькими игроками, часто поступают одновременно. Чтобы избежать слишком частого обновления интерфейса за короткий промежуток времени, обычно лучше отслеживать только onEvents и запускать обновления интерфейса оттуда:
Котлин
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(); } } });
Обрабатывайте доступные команды
Универсальный компонент пользовательского интерфейса, которому может потребоваться работа с различными реализациями Player , должен проверять доступные команды проигрывателя для отображения или скрытия кнопок и во избежание вызова неподдерживаемых методов:
Котлин
nextButton.isEnabled = player.isCommandAvailable(COMMAND_SEEK_TO_NEXT)
Java
nextButton.setEnabled(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT));
Первый кадр, затвор и отображение изображения
Когда компонент пользовательского интерфейса отображает видео или изображения, он обычно использует временное окно затвора до тех пор, пока не станет доступен первый реальный кадр или изображение. Кроме того, при воспроизведении видео и изображений необходимо скрывать и отображать окно изображения в соответствующие моменты.
Распространенный подход к обработке таких обновлений заключается в отслеживании изменений в выбранных дорожках ( EVENT_TRACKS_CHANGED ) и после рендеринга первого видеокадра ( EVENT_RENDERED_FIRST_FRAME ) с помощью Player.Listener.onEvents() , а также после появления нового изображения с ImageOutput.onImageAvailable() .
Котлин
override fun onEvents(player: Player, events: Player.Events) { if (events.contains(Player.EVENT_TRACKS_CHANGED)) { // If no video or image track: show shutter, hide image view. // Otherwise: do nothing to wait for first frame or image. } if (events.contains(Player.EVENT_RENDERED_FIRST_FRAME)) { // Hide shutter, hide image view. } } override fun onImageAvailable(presentationTimeUs: Long, bitmap: Bitmap) { // Show shutter, set image and show image view. }
Java
@Override public void onEvents(Player player, Player.Events events) { if (events.contains(Player.EVENT_TRACKS_CHANGED)) { // If no video or image track: show shutter, hide image view. // Otherwise: do nothing to wait for first frame or image. } if (events.contains(Player.EVENT_RENDERED_FIRST_FRAME)) { // Hide shutter, hide image view. } } @Override public void onImageAvailable(long presentationTimeUs, Bitmap bitmap) { // Show shutter, set image and show image view. }