Media3 提供預設的 PlayerView
,可提供一些自訂選項。
覆寫可繪項目
PlayerView
使用 PlayerControlView
顯示播放控制項和進度列。PlayerControlView
使用的可繪項目可由應用程式中定義的相同名稱可繪項目覆寫。如需可覆寫的控制項可繪項目清單,請參閱 PlayerControlView
說明文件。
如需進一步自訂,應用程式開發人員應實作自己的 UI 元件。不過,以下提供一些最佳做法,協助您開始使用。
最佳做法
在實作連結至 Media3 Player
的媒體 UI (例如 ExoPlayer
、MediaController
或自訂 Player
實作) 時,建議應用程式遵循下列最佳做法,以提供最佳 UI 體驗。
播放/暫停按鈕
播放和暫停按鈕並未直接對應單一播放器狀態。舉例來說,即使播放器未暫停,使用者仍應能在播放結束或失敗後重新開始播放。
為了簡化實作方式,Media3 提供實用方法,用於決定要顯示哪個按鈕 (Util.shouldShowPlayButton
) 以及處理按鈕按下動作 (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));
監聽狀態更新
UI 元件需要新增 Player.Listener
,才能得知需要對應 UI 更新的狀態變更。詳情請參閱「聆聽播放事件」。
重新整理 UI 的成本可能很高,而且通常會同時發生多個玩家事件。為避免在短時間內過度頻繁重新整理 UI,建議您只監聽 onEvents
,並從中觸發 UI 更新:
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(); } } });
處理可用的指令
通用 UI 元件可能需要與不同的 Player
實作搭配運作,因此應檢查可用的播放器指令,以便顯示或隱藏按鈕,並避免呼叫不支援的方法:
Kotlin
nextButton.isEnabled = player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT)
Java
nextButton.setEnabled(player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT));
第一個影格快門和圖片顯示
當 UI 元件顯示影片或圖片時,通常會使用預留位置快門檢視畫面,直到實際的第一個影格或圖片可供使用為止。此外,混合式影片和圖片播放功能需要在適當時間隱藏和顯示圖片檢視畫面。
處理這些更新的常見模式是監聽 Player.Listener.onEvents()
,以便在選取的音軌 (EVENT_TRACKS_CHANGED
) 發生任何變更時,以及在第一個影片影格完成轉譯 (EVENT_RENDERED_FIRST_FRAME
) 時收到通知,以及在 ImageOutput.onImageAvailable()
可用時收到通知:
Kotlin
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, 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. }