سفارشی‌سازی‌های میانای کاربر

Media3 یک PlayerView پیش‌فرض ارائه می‌دهد که برخی گزینه‌های سفارشی‌سازی را فراهم می‌کند.

لغو کردن قابل‌رسم‌ها

PlayerView از PlayerControlView برای نمایش کنترل‌های بازپخش و نوار پیشرفت استفاده می‌کند. ترسیم‌شدنی‌های استفاده‌شده توسط PlayerControlView را می‌توان با ترسیم‌شدنی‌های دارای نام‌های یکسان تعریف‌شده در برنامه‌تان لغو کرد. برای مشاهده فهرست کنترل‌های قابل‌ترسیم که می‌توانند لغو شوند، به سند PlayerControlView مراجعه کنید.

برای هرگونه سفارشی‌سازی بیشتر، انتظار می‌رود توسعه‌دهندگان نرم‌افزار مؤلفه‌های واسط کاربر خودشان را پیاده‌سازی کنند. باوجوداین، در اینجا چند روال مطلوب آورده شده است که می‌تواند به شما در شروع کار کمک کند.

روال‌های مطلوب

هنگام پیاده‌سازی واسط کاربر رسانه‌ای که به Media3 Player متصل می‌شود (برای مثال 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) }

جاوا

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

گوش دادن به به‌روزرسانی‌های وضعیت

مؤلفه UI باید Player.Listener را اضافه کند تا از تغییرات وضعیت که نیاز به به‌روزرسانی UI مربوطه دارند مطلع شود. برای جزئیات، گوش دادن به رویدادهای بازپخش را ببینید.

بازآوری واسط کاربر می‌تواند پرهزینه باشد و رویدادهای چندبازیکنی اغلب باهم می‌رسند. برای جلوگیری از بازآوری بیش‌ازحد واسط کاربر در مدت‌زمان کوتاه، بهتر است فقط به 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()
      }
    }
  }
)

جاوا

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)

جاوا

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

شاتر قاب اول و نمایش تصویر

وقتی مؤلفه میانای کاربر ویدیو یا تصویر نمایش می‌دهد، معمولاً از نمای شاتر جای‌بان استفاده می‌کند تا زمانی که اولین قاب یا تصویر واقعی دردسترس قرار گیرد. علاوه‌براین، بازپخش ترکیبی ویدیو و تصویر مستلزم پنهان کردن و نمایش دادن نمای تصویر در زمان‌های مناسب است.

الگوی رایج برای مدیریت این به‌روزرسانی‌ها این است که Player.Listener.onEvents() را برای هرگونه تغییر در قطعه‌های انتخاب‌شده (EVENT_TRACKS_CHANGED) و برای زمانی که اولین فریم ویدیو رندر شده است (EVENT_RENDERED_FIRST_FRAME) گوش دهید، و همچنین 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.
}

جاوا

@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.
}