تحتوي مجموعة أدوات واجهة مستخدم Leanback على عناصر تحكّم في التشغيل توفّر تجربة مستخدم محسّنة. بالنسبة إلى تطبيقات الفيديو، تتيح عناصر التحكّم في النقل إمكانية البحث السريع في الفيديو باستخدام عناصر التحكّم في التقديم والترجيع. أثناء سحب نقطة التقديم والترجيع، تعرض الشاشة صورًا مصغّرة للمساعدة في التنقّل خلال الفيديو.
تتضمّن المكتبة فئات مجرّدة بالإضافة إلى عمليات تنفيذ جاهزة ومتاحة للاستخدام مباشرةً، ما يوفّر للمطوّرين إمكانية تحكّم أكثر دقة. باستخدام عمليات التنفيذ المسبقة الإنشاء، يمكنك إنشاء تطبيق غني بالميزات بسرعة بدون الحاجة إلى الكثير من الترميز. إذا كنت بحاجة إلى المزيد من التخصيص، يمكنك توسيع أي من المكوّنات المسبقة الإنشاء في المكتبة.
عناصر التحكّم والمشغّل
تفصل مجموعة أدوات واجهة مستخدم Leanback واجهة مستخدم عناصر التحكّم في النقل عن المشغّل الذي يشغّل الفيديو. يتم ذلك باستخدام مكوّنَين: جزء دعم التشغيل لعرض عناصر التحكّم في النقل (والفيديو اختياريًا) ومحوّل المشغّل لتضمين مشغّل وسائط.
جزء التشغيل
يجب أن يستخدم نشاط واجهة المستخدم في تطبيقك
PlaybackSupportFragment
أو
VideoSupportFragment
.
يتضمّن كلا الخيارين عناصر التحكّم في النقل في وضع ملء الشاشة:
- تعمل الأداة
PlaybackSupportFragment
على تحريك عناصر التحكّم في النقل لإخفائها أو إظهارها حسب الحاجة. - يمتدّ
VideoSupportFragment
إلىPlaybackSupportFragment
ويتضمّنSurfaceView
لعرض الفيديو.
يمكنك تخصيص ObjectAdapter
لأحد الأجزاء
لتحسين واجهة المستخدم. على سبيل المثال، استخدِم
setAdapter()
لإضافة صف "الفيديوهات ذات الصلة".
PlayerAdapter
PlayerAdapter
هي فئة مجرّدة تتحكّم في مشغّل الوسائط الأساسي. يمكن للمطوّرين اختيار تنفيذ MediaPlayerAdapter
المُعدّ مسبقًا أو كتابة تنفيذهم الخاص لهذه الفئة.
تجميع الأجزاء
يجب استخدام بعض "الروابط" لربط جزء التشغيل بالمشغّل. توفّر مكتبة leanback نوعَين من الروابط:
- تعرض السمة
PlaybackBannerControlGlue
عناصر التحكّم في النقل في جزء التشغيل "بالأسلوب القديم"، أي يتم وضعها داخل خلفية غير شفافة. (يحلّPlaybackBannerControlGlue
محلّPlaybackControlGlue
، الذي تم إيقافه نهائيًا). - تستخدم
PlaybackTransportControlGlue
عناصر تحكّم "بالأسلوب الجديد" مع خلفية شفافة.
إذا كنت تريد أن يتيح تطبيقك إمكانية تقديم الفيديو أو ترجيعه بسرعة، عليك استخدام
PlaybackTransportControlGlue
.
عليك أيضًا تحديد "مضيف ربط" يربط الرمز البرمجي للواجهة بالرمز البرمجي الخاص بمقطع التشغيل، ويرسم عناصر التحكّم في النقل في واجهة المستخدم ويحافظ على حالتها، وينقل أحداث عناصر التحكّم في النقل إلى الرمز البرمجي للواجهة. يجب أن يتطابق المضيف مع نوع جزء التشغيل. استخدِم PlaybackSupportFragmentGlueHost
مع PlaybackFragment
، وVideoSupportFragmentGlueHost
مع VideoFragment
.
في ما يلي رسم توضيحي يوضّح كيفية عمل عناصر التحكّم في النقل في وضع الاسترخاء:
يجب أن يكون الرمز البرمجي الذي يربط أجزاء تطبيقك معًا داخل PlaybackSupportFragment
أو VideoSupportFragment
الذي يحدّد واجهة المستخدم.
في المثال التالي، ينشئ التطبيق مثيلاً من PlaybackTransportControlGlue
، ويسمّيه playerGlue
، ويربط VideoSupportFragment
بـ MediaPlayerAdapter
تم إنشاؤه حديثًا. بما أنّ هذا VideoSupportFragment
، يستدعي رمز الإعداد setHost()
لربط VideoSupportFragmentGlueHost
بـ playerGlue
. يتم تضمين الرمز داخل الفئة التي توسّع VideoSupportFragment
.
Kotlin
class MyVideoFragment : VideoSupportFragment() { fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) val playerGlue = PlaybackTransportControlGlue(getActivity(), MediaPlayerAdapter(getActivity())) playerGlue.setHost(VideoSupportFragmentGlueHost(this)) playerGlue.addPlayerCallback(object : PlaybackGlue.PlayerCallback() { override fun onPreparedStateChanged(glue: PlaybackGlue) { if (glue.isPrepared()) { playerGlue.seekProvider = MySeekProvider() playerGlue.play() } } }) playerGlue.setSubtitle("Leanback artist") playerGlue.setTitle("Leanback team at work") val uriPath = "android.resource://com.example.android.leanback/raw/video" playerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath)) } }
Java
public class MyVideoFragment extends VideoSupportFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final PlaybackTransportControlGlue<MediaPlayerAdapter> playerGlue = new PlaybackTransportControlGlue(getActivity(), new MediaPlayerAdapter(getActivity())); playerGlue.setHost(new VideoSupportFragmentGlueHost(this)); playerGlue.addPlayerCallback(new PlaybackGlue.PlayerCallback() { @Override public void onPreparedStateChanged(PlaybackGlue glue) { if (glue.isPrepared()) { playerGlue.setSeekProvider(new MySeekProvider()); playerGlue.play(); } } }); playerGlue.setSubtitle("Leanback artist"); playerGlue.setTitle("Leanback team at work"); String uriPath = "android.resource://com.example.android.leanback/raw/video"; playerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath)); } }
يُرجى العِلم أنّ رمز الإعداد يحدّد أيضًا PlayerAdapter.Callback
للتعامل مع الأحداث من مشغّل الوسائط.
تخصيص رمز الربط بين واجهة المستخدم
يمكنك تخصيص PlaybackBannerControlGlue
وPlaybackTransportControlGlue
لتغيير PlaybackControlsRow
.
تخصيص العنوان والوصف
لتخصيص العنوان والوصف في أعلى عناصر التحكّم في التشغيل، عليك إلغاء onCreateRowPresenter()
:
Kotlin
override fun onCreateRowPresenter(): PlaybackRowPresenter { return super.onCreateRowPresenter().apply { (this as? PlaybackTransportRowPresenter) ?.setDescriptionPresenter(MyCustomDescriptionPresenter()) } }
Java
@Override protected PlaybackRowPresenter onCreateRowPresenter() { PlaybackTransportRowPresenter presenter = (PlaybackTransportRowPresenter) super.onCreateRowPresenter(); presenter.setDescriptionPresenter(new MyCustomDescriptionPresenter()); return presenter; }
إضافة عناصر تحكّم
تعرض أداة الربط بين عناصر التحكّم عناصر التحكّم في الإجراءات في PlaybackControlsRow
.
يتم تقسيم الإجراءات في PlaybackControlsRow
إلى مجموعتين: الإجراءات الأساسية والإجراءات الثانوية. تظهر عناصر التحكّم في المجموعة الأساسية فوق شريط التقدّم، بينما تظهر عناصر التحكّم في المجموعة الثانوية أسفل شريط التقدّم. في البداية، يتوفّر إجراء أساسي واحد فقط لزر التشغيل/الإيقاف المؤقت، ولا تتوفّر أي إجراءات ثانوية.
يمكنك إضافة إجراءات إلى المجموعتين الأساسية والثانوية من خلال إلغاء onCreatePrimaryActions()
وonCreateSecondaryActions()
.
Kotlin
private lateinit var repeatAction: PlaybackControlsRow.RepeatAction private lateinit var pipAction: PlaybackControlsRow.PictureInPictureAction private lateinit var thumbsUpAction: PlaybackControlsRow.ThumbsUpAction private lateinit var thumbsDownAction: PlaybackControlsRow.ThumbsDownAction private lateinit var skipPreviousAction: PlaybackControlsRow.SkipPreviousAction private lateinit var skipNextAction: PlaybackControlsRow.SkipNextAction private lateinit var fastForwardAction: PlaybackControlsRow.FastForwardAction private lateinit var rewindAction: PlaybackControlsRow.RewindAction override fun onCreatePrimaryActions(primaryActionsAdapter: ArrayObjectAdapter) { // Order matters, super.onCreatePrimaryActions() will create the play / pause action. // Will display as follows: // play/pause, previous, rewind, fast forward, next // > /|| |< << >> >| super.onCreatePrimaryActions(primaryActionsAdapter) primaryActionsAdapter.apply { add(skipPreviousAction) add(rewindAction) add(fastForwardAction) add(skipNextAction) } } override fun onCreateSecondaryActions(adapter: ArrayObjectAdapter?) { super.onCreateSecondaryActions(adapter) adapter?.apply { add(thumbsDownAction) add(thumbsUpAction) } }
Java
private PlaybackControlsRow.RepeatAction repeatAction; private PlaybackControlsRow.PictureInPictureAction pipAction; private PlaybackControlsRow.ThumbsUpAction thumbsUpAction; private PlaybackControlsRow.ThumbsDownAction thumbsDownAction; private PlaybackControlsRow.SkipPreviousAction skipPreviousAction; private PlaybackControlsRow.SkipNextAction skipNextAction; private PlaybackControlsRow.FastForwardAction fastForwardAction; private PlaybackControlsRow.RewindAction rewindAction; @Override protected void onCreatePrimaryActions(ArrayObjectAdapter primaryActionsAdapter) { // Order matters, super.onCreatePrimaryActions() will create the play / pause action. // Will display as follows: // play/pause, previous, rewind, fast forward, next // > /|| |< << >> >| super.onCreatePrimaryActions(primaryActionsAdapter); primaryActionsAdapter.add(skipPreviousAction); primaryActionsAdapter.add(rewindAction); primaryActionsAdapter.add(fastForwardAction); primaryActionsAdapter.add(skipNextAction); } @Override protected void onCreateSecondaryActions(ArrayObjectAdapter adapter) { super.onCreateSecondaryActions(adapter); adapter.add(thumbsDownAction); adapter.add(thumbsUpAction); }
يجب إلغاء onActionClicked()
للتعامل مع الإجراءات الجديدة.
Kotlin
override fun onActionClicked(action: Action) { when(action) { rewindAction -> { // Handle Rewind } fastForwardAction -> { // Handle FastForward } thumbsDownAction -> { // Handle ThumbsDown } thumbsUpAction -> { // Handle ThumbsUp } else -> // The superclass handles play/pause and delegates next/previous actions to abstract methods, // so those two methods should be overridden rather than handling the actions here. super.onActionClicked(action) } } override fun next() { // Skip to next item in playlist. } override fun previous() { // Skip to previous item in playlist. }
Java
@Override public void onActionClicked(Action action) { if (action == rewindAction) { // Handle Rewind } else if (action == fastForwardAction ) { // Handle FastForward } else if (action == thumbsDownAction) { // Handle ThumbsDown } else if (action == thumbsUpAction) { // Handle ThumbsUp } else { // The superclass handles play/pause and delegates next/previous actions to abstract methods, // so those two methods should be overridden rather than handling the actions here. super.onActionClicked(action); } } @Override public void next() { // Skip to next item in playlist. } @Override public void previous() { // Skip to previous item in playlist. }
في حالات خاصة، قد تحتاج إلى تنفيذ
PlaybackTransportRowPresenter
خاص بك لعرض عناصر تحكّم مخصّصة والاستجابة لإجراءات البحث باستخدام
PlaybackSeekUi
.
تنقيح الفيديو
إذا كان تطبيقك يستخدم VideoSupportFragment
وأردت إتاحة ميزة "التقديم السريع للفيديو"
عليك تقديم تنفيذ PlaybackSeekDataProvider
.
يوفّر هذا المكوّن الصور المصغّرة للفيديوهات المستخدَمة عند التمرير.
يجب تنفيذ موفِّرك الخاص من خلال توسيع PlaybackSeekDataProvider
.
يمكنك الاطّلاع على المثال في
تطبيق Leanback Showcase.
.