Media3 یک PlayerView پیشفرض ارائه میدهد که برخی گزینههای سفارشیسازی را در اختیار قرار میدهد.
نادیده گرفتن drawableها
PlayerView از PlayerControlView برای نمایش کنترلهای پخش و نوار پیشرفت استفاده میکند. drawableهای مورد استفاده توسط PlayerControlView میتوانند توسط drawableهایی با همان نامهای تعریف شده در برنامه شما بازنویسی شوند. برای مشاهده لیستی از drawableهای کنترلی که میتوانند بازنویسی شوند، به مستندات PlayerControlView مراجعه کنید.
برای هرگونه سفارشیسازی بیشتر، انتظار میرود توسعهدهندگان برنامه، اجزای رابط کاربری خود را پیادهسازی کنند. با این حال، در اینجا چند روش برتر وجود دارد که میتواند به شما در شروع کار کمک کند.
بهترین شیوهها
هنگام پیادهسازی رابط کاربری رسانهای که به یک Player Media3 متصل میشود (برای مثال ExoPlayer ، MediaController یا یک پیادهسازی Player سفارشی)، به برنامهها توصیه میشود که برای بهترین تجربه رابط کاربری، از این بهترین شیوهها پیروی کنند.
دکمه پخش/مکث
دکمههای پخش و مکث مستقیماً به وضعیت یک بازیکن اشاره ندارند. برای مثال، کاربر باید بتواند پس از پایان یا عدم موفقیت پخش، حتی اگر پخش متوقف نشده باشد، آن را مجدداً شروع کند.
برای سادهسازی پیادهسازی، Media3 متدهای util را برای تصمیمگیری در مورد نمایش دکمه ( 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));
به آخرین اخبار ایالت گوش دهید
کامپوننت رابط کاربری برای اطلاع از تغییرات وضعیتی که نیاز به بهروزرسانی رابط کاربری مربوطه دارند، باید یک Player.Listener اضافه کند. برای جزئیات بیشتر به رویدادهای Listen to playback مراجعه کنید.
بهروزرسانی رابط کاربری میتواند پرهزینه باشد و رویدادهای متعدد بازیکن اغلب با هم اتفاق میافتند. برای جلوگیری از بهروزرسانی مکرر رابط کاربری در مدت زمان کوتاه، معمولاً بهتر است فقط به 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, 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. }