Media3 একটি ডিফল্ট PlayerView প্রদান করে, যেটিতে কিছু কাস্টমাইজেশন অপশন রয়েছে।
ড্রয়েবল ওভাররাইড করুন
PlayerView প্লেব্যাক কন্ট্রোল এবং প্রোগ্রেস বার প্রদর্শন করার জন্য PlayerControlView ব্যবহার করে। PlayerControlView দ্বারা ব্যবহৃত ড্রয়েবলগুলোকে আপনার অ্যাপ্লিকেশনে সংজ্ঞায়িত একই নামের ড্রয়েবল দিয়ে ওভাররাইড করা যেতে পারে। ওভাররাইড করা যায় এমন কন্ট্রোল ড্রয়েবলগুলোর তালিকার জন্য PlayerControlView ডকুমেন্টেশন দেখুন।
আরও কোনো কাস্টমাইজেশনের জন্য, অ্যাপ ডেভেলপারদের নিজস্ব UI কম্পোনেন্ট প্রয়োগ করতে হয়। তবে, এখানে কিছু সেরা অনুশীলন দেওয়া হলো যা আপনাকে শুরু করতে সাহায্য করতে পারে।
সর্বোত্তম অনুশীলন
Media3 Player (যেমন ExoPlayer , MediaController বা নিজস্ব Player ) সাথে সংযুক্ত কোনো মিডিয়া UI তৈরি করার সময়, সেরা UI অভিজ্ঞতার জন্য অ্যাপগুলোকে এই সর্বোত্তম অনুশীলনগুলো অনুসরণ করার পরামর্শ দেওয়া হয়।
প্লে/পজ বাটন
প্লে এবং পজ বাটন সরাসরি প্লেয়ারের কোনো একটি নির্দিষ্ট অবস্থার সাথে সম্পর্কিত নয়। উদাহরণস্বরূপ, প্লেয়ার পজ করা না থাকলেও, প্লেব্যাক শেষ হয়ে গেলে বা ব্যর্থ হলে একজন ব্যবহারকারী যেন তা পুনরায় শুরু করতে পারেন।
বাস্তবায়ন সহজ করার জন্য, কোন বাটনটি দেখানো হবে তা নির্ধারণ করতে ( 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 আপডেট সম্পর্কে অবহিত হওয়ার জন্য UI কম্পোনেন্টটিতে একটি Player.Listener যোগ করতে হবে। বিস্তারিত জানতে ‘Listen to playback events’ দেখুন।
UI রিফ্রেশ করা ব্যয়বহুল হতে পারে এবং প্রায়শই একাধিক প্লেয়ার ইভেন্ট একসাথে আসে। অল্প সময়ের মধ্যে ঘন ঘন UI রিফ্রেশ করা এড়াতে, সাধারণত শুধু onEvents শোনা এবং সেখান থেকে UI আপডেট ট্রিগার করা শ্রেয়।
কোটলিন
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 ইমপ্লিমেন্টেশনের সাথে কাজ করতে পারে, তার উচিত বাটন দেখানো বা লুকানোর জন্য উপলব্ধ প্লেয়ার কমান্ডগুলো পরীক্ষা করা এবং অসমর্থিত মেথড কল করা এড়ানো।
কোটলিন
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() শোনা।
কোটলিন
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. }