استخدام عناصر التحكّم في النقل

الإنشاء بشكل أفضل باستخدام Compose
يمكنك إنشاء واجهات مستخدم رائعة باستخدام أقل عدد ممكن من الرموز باستخدام Jetpack Compose لنظام التشغيل Android TV.

تحتوي مجموعة أدوات واجهة مستخدم Leanback على عناصر تحكم في التشغيل توفر تجربة المستخدم. بالنسبة إلى تطبيقات الفيديو، توفِّر عناصر التحكّم في النقل ميزة التقديم والترجيع في الفيديو. مع عناصر التحكم للأمام والخلف. تظهر عند مسح الشاشة والصور المصغّرة للمساعدة في التنقل بين أقسام الفيديو.

تتضمّن المكتبة دروسًا تجريدية، بالإضافة إلى تطبيقات جاهزة وجاهزة مسبقًا. التي توفر تحكمًا أكثر دقة للمطوّرين. استخدام واجهة برمجة تطبيقات معدة مسبقًا عمليات التنفيذ، يمكنك إنشاء تطبيق غني بالميزات بسرعة وبدون الحاجة إلى ترميز كثيرًا. إذا كنت بحاجة إلى مزيد من التخصيص، فيمكنك توسيع أي من واجهات برمجة التطبيقات والمكونات.

عناصر التحكّم والمشغّل

تفصل مجموعة أدوات واجهة مستخدم Leanback واجهة المستخدم لعناصر التحكم في النقل المشغّل الذي يشغّل الفيديو. ويتم تحقيق ذلك من خلال عنصرين: جزء دعم التشغيل لعرض عناصر التحكم في النقل (و فيديو اختياريًا) ومحوّل مشغّل لتغليف مشغّل وسائط.

جزء التشغيل

يجب أن يستخدم نشاط واجهة المستخدم في تطبيقك PlaybackSupportFragment أو VideoSupportFragment يحتوي كلاهما على عناصر التحكم في النقل leanback:

يمكنك تخصيص طريقة ObjectAdapter لتحسين واجهة المستخدم. على سبيل المثال، استخدم setAdapter() لإضافة "فيديوهات ذات صلة" الصف.

مهايئ المشغّل

PlayerAdapter هي فئة مجردة للتحكم في مشغّل الوسائط الأساسي. يمكن للمطوّرين الاختيار تنفيذ MediaPlayerAdapter المنشأة مسبقًا أو كتابة كيفية تنفيذها لهذه الفئة.

لصق القطع معًا

يجب استخدام بعض "الغراء" لربط الجزء المخصص للتشغيل للّاعب. The leanback المكتبة نوعين من الغراء هما:

  • تعادَل PlaybackBannerControlGlue نقل عناصر التحكم في جزء التشغيل بـ "النمط القديم"، مما يجعلها داخل خلفية مبهمة. (PlaybackBannerControlGlue) يحل محل PlaybackControlGlue، الذي تم إيقافه).
  • PlaybackTransportControlGlue يستخدم "النمط الجديد" وعناصر التحكم ذات الخلفية الشفافة.

غراء التحكّم في نقل البيانات من leanback

إذا كنت تريد أن يتيح تطبيقك تنظيف الفيديوهات، يجب استخدام PlaybackTransportControlGlue

يجب أيضًا تحديد "مضيف ملتصق". الذي/التي يربط الغراء بالتشغيل ويرسم عناصر التحكم في النقل في واجهة المستخدم ويحافظ على حالته ويمرر أحداث التحكم في النقل مرة أخرى إلى الغراء. يجب أن يطابق المضيف نوع جزء التشغيل. استخدام PlaybackSupportFragmentGlueHost باستخدام PlaybackFragment و VideoSupportFragmentGlueHost مع VideoFragment

في ما يلي صورة توضيحية تعرض كيفية عمل عناصر التحكم في النقل على leanback. التوافق معًا:

غراء التحكّم في نقل البيانات من leanback

يجب أن يكون الرمز الذي يلتصق بتطبيقك معًا داخل 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 .