Media3 একটি ডিফল্ট PlayerView প্রদান করে যা কিছু কাস্টমাইজেশন
বিকল্প প্রদান করে।
ড্রয়েবল ওভাররাইড করুন
PlayerView, প্লেব্যাক কন্ট্রোল ও প্রোগ্রেস বার দেখানোর জন্য
PlayerControlView ব্যবহার করে। PlayerControlView-এর ব্যবহার করা ড্রয়েবল আপনার অ্যাপ্লিকেশনে একই নামে সংজ্ঞায়িত ড্রয়েবল দ্বারা
ওভাররাইড করা যেতে পারে। ওভাররাইড করা যেতে পারে এমন কন্ট্রোল ড্রয়েবেলের তালিকার জন্য
PlayerControlView ডকুমেন্টেশন দেখুন।
আরও কাস্টমাইজেশনের জন্য, অ্যাপ ডেভেলপারদের নিজস্ব UI কম্পোনেন্ট প্রয়োগ করতে হবে। তবে, শুরু করার জন্য এখানে কিছু পেশাদার পদ্ধতি দেওয়া হল।
পেশাদার পদ্ধতি
Media3 Player-এর সাথে কানেক্ট করে এমন মিডিয়া UI প্রয়োগ করার সময় (যেমন
ExoPlayer, MediaController বা কাস্টম Player প্রয়োগ), অ্যাপকে
সেরা UI অভিজ্ঞতা দেওয়ার জন্য এইসব পেশাদার পদ্ধতি অনুসরণ করার পরামর্শ দেওয়া হয়।
চালানো/পজ করার বোতাম
প্লে ও পজ বোতাম সরাসরি কোনও একটি প্লেয়ারের স্ট্যাটাসের সাথে সম্পর্কিত নয়। যেমন, প্লেব্যাক শেষ বা ব্যর্থ হওয়ার পরে ব্যবহারকারী যেন সেটি আবার চালু করতে পারেন, এমনকি প্লেয়ার পজ করা না থাকলেও।
প্রয়োগ করার পদ্ধতি সহজ করতে, Media3 কোন বোতাম দেখাতে হবে (Util.shouldShowPlayButton) এবং বোতাম প্রেস করা কীভাবে ম্যানেজ করতে হবে (Util.handlePlayPauseButtonAction) তা নির্ধারণ করার জন্য util পদ্ধতি প্রদান করে:
Kotlin
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 আপডেট করা যায়। আরও বিবরণের জন্য প্লেব্যাক ইভেন্ট
শুনুন বিকল্প দেখুন।
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() } } } )
জাভা
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)
জাভা
nextButton.setEnabled(player.isCommandAvailable(COMMAND_SEEK_TO_NEXT));
প্রথম ফ্রেম শাটার ও ছবি ডিসপ্লে
কোনও UI কম্পোনেন্ট ভিডিও বা ছবি দেখালে, আসল প্রথম ফ্রেম বা ছবি উপলভ্য না হওয়া পর্যন্ত এটি সাধারণত একটি প্লেসহোল্ডার শাটার ভিউ ব্যবহার করে। এছাড়াও, মিক্সড ভিডিও ও ছবি প্লেব্যাকের জন্য সঠিক সময়ে ছবির ভিউ লুকানো ও দেখানোর প্রয়োজন হয়।
এইসব আপডেট ম্যানেজ করার সাধারণ প্যাটার্ন হল, বেছে নেওয়া ট্র্যাকে কোনও পরিবর্তন হয়েছে কিনা
(EVENT_TRACKS_CHANGED) এবং প্রথম ভিডিও ফ্রেম কখন রেন্ডার করা হয়েছে
(EVENT_RENDERED_FIRST_FRAME) তা জানার জন্য Player.Listener.onEvents() শোনা,
এর পাশাপাশি নতুন ছবি কখন উপলভ্য হবে তা জানার জন্য 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. }
জাভা
@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. }