การปรับแต่ง UI

Media3 มี PlayerView เริ่มต้นซึ่งมีตัวเลือกการปรับแต่งบางอย่าง

ลบล้าง Drawable

รหัสทรัพยากรที่มีเครื่องหมาย "ส่วนตัว"

PlayerView ใช้ PlayerControlView เพื่อแสดงตัวควบคุมการเล่นและ แถบความคืบหน้า PlayerControlView สามารถลบล้าง Drawable ที่ใช้ได้โดย Drawable ที่มีชื่อเดียวกันซึ่งกำหนดไว้ในแอปพลิเคชัน ดูรายการ Drawable ของตัวควบคุมที่สามารถ ลบล้างได้ในเอกสารประกอบของ PlayerControlView

หากต้องการปรับแต่งเพิ่มเติม นักพัฒนาแอปจะต้องใช้คอมโพเนนต์ UI ของตนเอง อย่างไรก็ตาม แนวทางปฏิบัติแนะนำต่อไปนี้จะช่วยให้คุณเริ่มต้นใช้งานได้

แนวทางปฏิบัติแนะนำ

เมื่อติดตั้งใช้งาน UI ของสื่อที่เชื่อมต่อกับ Player ของ Media3 (เช่น ExoPlayer, MediaController หรือการติดตั้งใช้งาน Player ที่กำหนดเอง) เราขอแนะนำให้แอปทำตามแนวทางปฏิบัติแนะนำเหล่านี้เพื่อให้ได้ประสบการณ์ UI ที่ดีที่สุด

ปุ่มเล่น/หยุดชั่วคราว

ปุ่มเล่นและหยุดชั่วคราวไม่ได้สอดคล้องกับสถานะของเพลเยอร์เดียวโดยตรง เช่น ผู้ใช้ควรรีสตาร์ทการเล่นได้หลังจากที่เล่นจบหรือเล่นไม่สำเร็จ แม้ว่าโปรแกรมเล่นจะไม่ได้หยุดชั่วคราวก็ตาม

Media3 มีเมธอด Util เพื่อช่วยในการตัดสินใจว่าจะแสดงปุ่มใด (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 อาจมีค่าใช้จ่ายสูง และเหตุการณ์ของผู้เล่นหลายคนมักจะเกิดขึ้นพร้อมกัน โดยทั่วไปแล้ว การฟังแค่ onEvents และทริกเกอร์การอัปเดต UI จากที่นั่นจะดีกว่าเพื่อหลีกเลี่ยงการรีเฟรช 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(COMMAND_SEEK_TO_NEXT)

Java

nextButton.setEnabled(player.isCommandAvailable(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.
}