جعبه ابزار رابط کاربری Leanback دارای کنترلهای پخش است که تجربه کاربری بهبود یافتهای را ارائه میدهد. برای برنامههای ویدیویی، کنترلهای انتقال از جابجایی ویدیو با کنترلهای جلو و عقب پشتیبانی میکنند. هنگام جابجایی، صفحه نمایش تصاویر کوچکی را نشان میدهد تا به پیمایش در ویدیو کمک کند.
این کتابخانه شامل کلاسهای انتزاعی و همچنین پیادهسازیهای از پیش ساخته شده و آماده است که کنترل دقیقتری را برای توسعهدهندگان فراهم میکند. با استفاده از پیادهسازیهای از پیش ساخته شده، میتوانید به سرعت و بدون کدنویسی زیاد، یک برنامه غنی از ویژگیها بسازید. اگر به سفارشیسازی بیشتری نیاز دارید، میتوانید هر یک از اجزای از پیش ساخته شده کتابخانه را گسترش دهید.
کنترل و پخش کننده
جعبه ابزار رابط کاربری Leanback، رابط کاربری کنترلهای انتقال را از پخشکنندهای که ویدیو را پخش میکند، جدا میکند. این کار با دو جزء انجام میشود: یک قطعه پشتیبانی پخش برای نمایش کنترلهای انتقال (و به صورت اختیاری ویدیو) و یک آداپتور پخشکننده برای محصور کردن یک پخشکننده رسانه.
قطعه پخش
اکتیویتی رابط کاربری برنامه شما باید از یک PlaybackSupportFragment یا یک VideoSupportFragment استفاده کند. هر دو شامل کنترلهای انتقال leanback هستند:
- یک
PlaybackSupportFragmentکنترلهای انتقال خود را متحرک میکند تا در صورت نیاز آنها را پنهان/نمایش دهد. - یک
VideoSupportFragmentازPlaybackSupportFragmentارثبری میکند و یکSurfaceViewبرای رندر کردن ویدیو دارد.
شما میتوانید ObjectAdapter یک فرگمنت را برای بهبود رابط کاربری سفارشی کنید. برای مثال، setAdapter() برای اضافه کردن ردیف "ویدیوهای مرتبط" استفاده کنید.
آداپتور پخشکننده
PlayerAdapter یک کلاس انتزاعی است که پخشکنندهی رسانهی اصلی را کنترل میکند. توسعهدهندگان میتوانند پیادهسازی از پیش ساخته شدهی MediaPlayerAdapter را انتخاب کنند یا پیادهسازی خودشان را از این کلاس بنویسند.
چسباندن قطعات به یکدیگر
برای اتصال قطعه پخش به پخشکننده باید از نوعی «چسب کنترل» استفاده کنید. کتابخانه leanback دو نوع چسب ارائه میدهد:
-
PlaybackBannerControlGlueکنترلهای انتقال را در قطعه پخش به «سبک قدیمی» ترسیم میکند و آنها را درون یک پسزمینه مات قرار میدهد. (PlaybackBannerControlGlueجایگزینPlaybackControlGlueشده است که منسوخ شده است.) -
PlaybackTransportControlGlueاز کنترلهای «سبک جدید» با پسزمینه شفاف استفاده میکند.

اگر میخواهید برنامه شما از قابلیت برش ویدیو پشتیبانی کند، باید PlaybackTransportControlGlue استفاده کنید.
همچنین باید یک "میزبان چسب" مشخص کنید که چسب را به قطعه پخش متصل کند، کنترلهای انتقال را در رابط کاربری ترسیم کند و وضعیت آنها را حفظ کند و رویدادهای کنترل انتقال را به چسب برگرداند. میزبان باید با نوع قطعه پخش مطابقت داشته باشد. PlaybackSupportFragmentGlueHost با PlaybackFragment و از VideoSupportFragmentGlueHost با VideoFragment استفاده کنید.
در اینجا تصویری نشان داده شده است که چگونه قطعات یک کنترل حمل و نقل تکیه گاه به هم متصل می شوند:

کدی که برنامه شما را به هم متصل میکند باید درون PlaybackSupportFragment یا VideoSupportFragment باشد که رابط کاربری را تعریف میکند.
در مثال زیر، برنامه یک نمونه از PlaybackTransportControlGlue میسازد و آن را playerGlue نامگذاری میکند و VideoSupportFragment آن را به یک MediaPlayerAdapter تازه ایجاد شده متصل میکند. از آنجایی که این یک VideoSupportFragment است، کد راهاندازی، setHost() را برای اتصال یک VideoSupportFragmentGlueHost به playerGlue فراخوانی میکند. این کد درون کلاسی قرار دارد که VideoSupportFragment را ارثبری میکند.
کاتلین
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)) } }
جاوا
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 را برای مدیریت رویدادهای پخشکننده رسانه تعریف میکند.
سفارشیسازی رابط کاربری (UI)
شما میتوانید PlaybackBannerControlGlue و PlaybackTransportControlGlue را برای تغییر PlaybackControlsRow سفارشی کنید.
سفارشیسازی عنوان و توضیحات
برای سفارشیسازی عنوان و توضیحات در بالای کنترلهای پخش، تابع onCreateRowPresenter() را بازنویسی کنید:
کاتلین
override fun onCreateRowPresenter(): PlaybackRowPresenter { return super.onCreateRowPresenter().apply { (this as? PlaybackTransportRowPresenter) ?.setDescriptionPresenter(MyCustomDescriptionPresenter()) } }
جاوا
@Override protected PlaybackRowPresenter onCreateRowPresenter() { PlaybackTransportRowPresenter presenter = (PlaybackTransportRowPresenter) super.onCreateRowPresenter(); presenter.setDescriptionPresenter(new MyCustomDescriptionPresenter()); return presenter; }
افزودن کنترلها
چسب کنترل، کنترلهایی را برای اقدامات در یک PlaybackControlsRow نمایش میدهد.
اقدامات موجود در ردیف PlaybackControlsRow به دو گروه اختصاص داده شدهاند: اقدامات اولیه و اقدامات ثانویه . کنترلهای گروه اولیه در بالای نوار جستجو و کنترلهای گروه ثانویه در زیر نوار جستجو ظاهر میشوند. در ابتدا، فقط یک اقدام اولیه برای دکمه پخش/مکث وجود دارد و هیچ اقدام ثانویهای وجود ندارد.
شما میتوانید با بازنویسی (override) onCreatePrimaryActions() و onCreateSecondaryActions() به گروههای اصلی و فرعی، اکشن اضافه کنید.
کاتلین
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) } }
جاوا
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() را بازنویسی کنید.
کاتلین
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. }
جاوا
@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 استفاده میکند و میخواهید از قابلیت video scrubbing پشتیبانی کنید.

شما باید یک پیادهسازی از PlaybackSeekDataProvider ارائه دهید. این کامپوننت، تصاویر کوچک ویدیویی مورد استفاده هنگام پیمایش را فراهم میکند. شما باید با بسط دادن PlaybackSeekDataProvider ارائهدهنده خودتان را پیادهسازی کنید. به مثال موجود در برنامه Leanback Showcase مراجعه کنید.
