با مجموعهها، منظم بمانید
ذخیره و طبقهبندی محتوا براساس اولویتهای شما.
Media3 یک PlayerView پیشفرض ارائه میکند که برخی از گزینههای سفارشیسازی را ارائه میکند.
موارد قابل ترسیم را لغو کنید
PlayerView از PlayerControlView برای نمایش کنترل های پخش و نوار پیشرفت استفاده می کند. نقشههایی که توسط PlayerControlView استفاده میشوند، میتوانند توسط نقشههایی با همان نامهای تعریفشده در برنامه شما لغو شوند. برای فهرستی از نقشههای کنترلی که میتوان آنها را نادیده گرفت، به مستندات PlayerControlView مراجعه کنید.
برای هر گونه سفارشی سازی بیشتر، از توسعه دهندگان برنامه انتظار می رود اجزای رابط کاربری خود را پیاده سازی کنند. با این حال، در اینجا برخی از بهترین روش ها وجود دارد که می تواند به شما در شروع کار کمک کند.
بهترین شیوه ها
هنگام پیادهسازی یک رابط کاربری رسانهای که به Media3 Player متصل میشود (به عنوان مثال ExoPlayer ، MediaController یا پیادهسازی Player سفارشی)، به برنامهها توصیه میشود این بهترین شیوهها را برای بهترین تجربه رابط کاربری دنبال کنند.
دکمه پخش/مکث
دکمه پخش و مکث مستقیماً با یک حالت پخش کننده مطابقت ندارد. به عنوان مثال، یک کاربر باید بتواند پس از پایان یافتن یا شکست آن، حتی اگر پخش کننده متوقف نشده باشد، پخش را مجدداً راه اندازی کند.
برای سادهسازی پیادهسازی، Media3 روشهایی را برای تصمیمگیری اینکه کدام دکمه نمایش داده شود ( Util.shouldShowPlayButton ) و برای کنترل فشار دادن دکمه ( Util.handlePlayPauseButtonAction ) ارائه میکند:
مؤلفه رابط کاربری باید یک Player.Listener اضافه کند تا از تغییرات وضعیتی که نیاز به بهروزرسانی رابط کاربری مربوطه دارند مطلع شود. برای جزئیات بیشتر به گوش دادن به رویدادهای پخش مراجعه کنید.
تازه کردن رابط کاربری ممکن است پرهزینه باشد و رویدادهای چند بازیکن اغلب با هم می آیند. برای جلوگیری از بهروزرسانی بیش از حد UI در مدت زمان کوتاه، معمولاً بهتر است فقط به onEvents گوش دهید و بهروزرسانیهای UI را از آنجا فعال کنید:
یک مؤلفه رابط کاربری عمومی که ممکن است نیاز به کار با پیاده سازی های مختلف Player داشته باشد، باید دستورات پخش کننده موجود را برای نمایش یا پنهان کردن دکمه ها و جلوگیری از فراخوانی روش های پشتیبانی نشده بررسی کند:
هنگامی که یک مؤلفه رابط کاربری ویدیو یا تصاویر را نمایش می دهد، معمولاً از نمای شاتر نگهدارنده استفاده می کند تا زمانی که اولین فریم یا تصویر واقعی در دسترس باشد. علاوه بر این، پخش ترکیبی ویدیو و تصویر نیاز به پنهان کردن و نمایش تصویر در زمانهای مناسب دارد.
یک الگوی رایج برای رسیدگی به این بهروزرسانیها، گوش دادن به Player.Listener.onEvents() برای هرگونه تغییر در آهنگهای انتخابی ( EVENT_TRACKS_CHANGED ) و زمانی که اولین فریم ویدیو رندر شده است ( EVENT_RENDERED_FIRST_FRAME )، و همچنین ImageOutput.onImageAvailable() برای زمانی که یک تصویر جدید در دسترس است.
کاتلین
overridefunonEvents(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.}}overridefunonImageAvailable(presentationTimeUs:Long,bitmap:Bitmap){// Show shutter, set image and show image view.}
جاوا
@OverridepublicvoidonEvents(Playerplayer,Eventsevents){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.}}@OverridepublicvoidonImageAvailable(longpresentationTimeUs,Bitmapbitmap){// Show shutter, set image and show image view.}
محتوا و نمونه کدها در این صفحه مشمول پروانههای توصیفشده در پروانه محتوا هستند. جاوا و OpenJDK علامتهای تجاری یا علامتهای تجاری ثبتشده Oracle و/یا وابستههای آن هستند.
تاریخ آخرین بهروزرسانی 2025-08-27 بهوقت ساعت هماهنگ جهانی.
[[["درک آسان","easyToUnderstand","thumb-up"],["مشکلم را برطرف کرد","solvedMyProblem","thumb-up"],["غیره","otherUp","thumb-up"]],[["اطلاعاتی که نیاز دارم وجود ندارد","missingTheInformationINeed","thumb-down"],["بیشازحد پیچیده/ مراحل بسیار زیاد","tooComplicatedTooManySteps","thumb-down"],["قدیمی","outOfDate","thumb-down"],["مشکل ترجمه","translationIssue","thumb-down"],["مشکل کد / نمونهها","samplesCodeIssue","thumb-down"],["غیره","otherDown","thumb-down"]],["تاریخ آخرین بهروزرسانی 2025-08-27 بهوقت ساعت هماهنگ جهانی."],[],[],null,["Media3 provides a default [`PlayerView`](/guide/topics/media/ui/playerview) that provides some customization\noptions.\n\nOverride drawables **Caution:** We don't guarantee that the customizations described in the following section will continue to work in future versions of the library. The resource IDs may change name, or some may be deleted entirely. This is indicated by the [resource IDs being marked 'private'](/studio/projects/android-library#PrivateResources).\n\n`PlayerView` uses `PlayerControlView` to display the playback controls and\nprogress bar. The drawables used by `PlayerControlView` can be overridden by\ndrawables with the same names defined in your application. See the\n[`PlayerControlView`](/reference/androidx/media3/ui/PlayerControlView) documentation for a list of control drawables that can\nbe overridden.\n\nFor any further customization, app developers are expected to implement their\nown UI components. However, here are some best practices that can help you get\nstarted.\n\nBest practices\n\nWhen implementing a media UI that connects to a Media3 `Player` (for example\n`ExoPlayer`, `MediaController` or a custom `Player` implementation), apps are\nadvised to follow these best practices for the best UI experience.\n\nPlay/Pause button\n\nThe play and pause button does not directly correspond to a single player state.\nFor example, a user should be able to restart playback after it ended or failed\neven if the player isn't paused.\n\nTo simplify the implementation, Media3 provides util methods to decide which\nbutton to show (`Util.shouldShowPlayButton`) and to handle button presses\n(`Util.handlePlayPauseButtonAction`): \n\nKotlin \n\n```kotlin\nval shouldShowPlayButton: Boolean = Util.shouldShowPlayButton(player)\nplayPauseButton.setImageDrawable(if (shouldShowPlayButton) playDrawable else pauseDrawable)\nplayPauseButton.setOnClickListener { Util.handlePlayPauseButtonAction(player) }\n```\n\nJava \n\n```java\nboolean shouldShowPlayButton = Util.shouldShowPlayButton(player);\nplayPauseButton.setImageDrawable(shouldShowPlayButton ? playDrawable : pauseDrawable);\nplayPauseButton.setOnClickListener(view -\u003e Util.handlePlayPauseButtonAction(player));\n```\n\n\u003cbr /\u003e\n\nListen to state updates\n\nThe UI component needs to add a `Player.Listener` to be informed of state\nchanges that require a corresponding UI update. See [Listen to playback\nevents](/guide/topics/media/exoplayer/listening-to-player-events) for details.\n\nRefreshing the UI can be costly and multiple player events often arrive\ntogether. To avoid refreshing the UI too often in a short period of time, it's\ngenerally better to listen to just `onEvents` and trigger UI updates from there: \n\nKotlin \n\n```kotlin\nplayer.addListener(object : Player.Listener{\n override fun onEvents(player: Player, events: Player.Events){\n if (events.containsAny(\n Player.EVENT_PLAY_WHEN_READY_CHANGED,\n Player.EVENT_PLAYBACK_STATE_CHANGED,\n Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED)) {\n updatePlayPauseButton()\n }\n if (events.containsAny(Player.EVENT_REPEAT_MODE_CHANGED)) {\n updateRepeatModeButton()\n }\n }\n})\n```\n\nJava \n\n```java\nplayer.addListener(new Player.Listener() {\n @Override\n public void onEvents(Player player, Player.Events events) {\n if (events.containsAny(\n Player.EVENT_PLAY_WHEN_READY_CHANGED,\n Player.EVENT_PLAYBACK_STATE_CHANGED,\n Player.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED)) {\n updatePlayPauseButton();\n }\n if (events.containsAny(Player.EVENT_REPEAT_MODE_CHANGED)) {\n updateRepeatModeButton();\n }\n }\n});\n```\n\n\u003cbr /\u003e\n\nHandle available commands\n\nA general purpose UI component that may need to work with different `Player`\nimplementations should check the available player commands to show or hide\nbuttons and to avoid calling unsupported methods: \n\nKotlin \n\n```kotlin\nnextButton.isEnabled = player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT)\n```\n\nJava \n\n```java\nnextButton.setEnabled(player.isCommandAvailable(Player.COMMAND_SEEK_TO_NEXT));\n```\n\n\u003cbr /\u003e\n\nFirst frame shutter and image display\n\nWhen a UI component displays video or images, it typically uses a placeholder\nshutter view until the real first frame or image is available. In addition,\nmixed video and image playback requires to hide and show the image view at\nappropriate times.\n\nA common pattern to handle these updates is to listen to\n[`Player.Listener.onEvents()`](/reference/androidx/media3/exoplayer/Player.Listener#onEvents(androidx.media3.exoplayer.Player,%20androidx.media3.exoplayer.Player.Events)) for any change in selected tracks\n(`EVENT_TRACKS_CHANGED`) and for when the first video frame has been rendered\n(`EVENT_RENDERED_FIRST_FRAME`), as well as [`ImageOutput.onImageAvailable()`](/reference/androidx/media3/ui/ImageOutput#onImageAvailable(long,%20android.graphics.Bitmap))\nfor when a new image is available: \n\nKotlin \n\n```kotlin\noverride fun onEvents(player: Player, events: Player.Events) {\n if (events.contains(Player.EVENT_TRACKS_CHANGED)) {\n // If no video or image track: show shutter, hide image view.\n // Otherwise: do nothing to wait for first frame or image.\n }\n if (events.contains(Player.EVENT_RENDERED_FIRST_FRAME)) {\n // Hide shutter, hide image view.\n }\n}\n\noverride fun onImageAvailable(presentationTimeUs: Long, bitmap: Bitmap) {\n // Show shutter, set image and show image view.\n}\n```\n\nJava \n\n```java\n@Override\npublic void onEvents(Player player, Events events) {\n if (events.contains(Player.EVENT_TRACKS_CHANGED)) {\n // If no video or image track: show shutter, hide image view.\n // Otherwise: do nothing to wait for first frame or image.\n }\n if (events.contains(Player.EVENT_RENDERED_FIRST_FRAME)) {\n // Hide shutter, hide image view.\n }\n}\n\n@Override\npublic void onImageAvailable(long presentationTimeUs, Bitmap bitmap) {\n // Show shutter, set image and show image view.\n}\n```\n\n\u003cbr /\u003e"]]