Media3 menyediakan PlayerView
default yang menyediakan beberapa
opsi penyesuaian. Untuk penyesuaian lebih lanjut, developer aplikasi
diharapkan menerapkan komponen UI-nya sendiri.
Praktik terbaik
Saat menerapkan UI media yang terhubung ke Player
Media3 (misalnya
ExoPlayer
, MediaController
, atau implementasi Player
kustom), aplikasi
dianjurkan untuk mengikuti praktik terbaik ini untuk pengalaman UI terbaik.
Tombol Putar/Jeda
Tombol putar dan jeda tidak langsung sesuai dengan status satu pemain. Misalnya, pengguna harus dapat memulai ulang pemutaran setelah berakhir atau gagal meskipun pemutar tidak dijeda.
Untuk menyederhanakan implementasi, Media3 menyediakan metode utilitas untuk menentukan tombol
mana yang akan ditampilkan (Util.shouldShowPlayButton
) dan untuk menangani penekanan tombol
(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));
Memproses pembaruan status
Komponen UI harus menambahkan Player.Listener
untuk diberi tahu tentang perubahan
status yang memerlukan update UI yang sesuai. Lihat
Memproses peristiwa pemutaran untuk mengetahui detailnya.
Memuat ulang UI dapat menghabiskan banyak biaya dan beberapa peristiwa pemain sering kali
datang bersamaan. Agar tidak terlalu sering memuat ulang UI dalam waktu yang singkat, umumnya lebih baik memproses onEvents
saja dan memicu update UI dari sana:
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(); } } });
Menangani perintah yang tersedia
Komponen UI tujuan umum yang mungkin perlu berfungsi dengan implementasi Player
yang berbeda harus memeriksa perintah pemutar yang tersedia untuk menampilkan atau menyembunyikan
tombol dan menghindari memanggil metode yang tidak didukung:
Kotlin
nextButton.isEnabled = player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT)
Java
nextButton.setEnabled(player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT));
Shutter frame pertama dan tampilan gambar
Saat komponen UI menampilkan video atau gambar, komponen UI biasanya menggunakan tampilan shutter placeholder hingga frame atau gambar pertama yang sebenarnya tersedia. Selain itu, pemutaran video dan gambar campuran memerlukan tindakan menyembunyikan dan menampilkan tampilan gambar pada waktu yang tepat.
Pola umum untuk menangani update ini adalah memproses
Player.Listener.onEvents
untuk setiap perubahan pada trek yang dipilih
(EVENT_TRACKS_CHANGED
) dan saat frame video pertama telah
dirender (EVENT_RENDERED_FIRST_FRAME
), serta
ImageOutput.onImageAvailable
untuk saat gambar baru tersedia:
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. }