ชุดเครื่องมือ UI ของ Leanback มีตัวควบคุมการเล่นที่มอบประสบการณ์การใช้งานที่ดีขึ้น สำหรับแอปวิดีโอ ตัวควบคุมการส่งจะรองรับการสครับวิดีโอด้วยตัวควบคุมไปข้างหน้าและย้อนกลับ ขณะสครับ การแสดงผลจะแสดงภาพขนาดย่อเพื่อช่วยในการนำทางผ่านวิดีโอ
ไลบรารีมีคลาสแอบสแตรกต์ รวมถึงการใช้งานที่สร้างไว้ล่วงหน้าและพร้อมใช้งาน ซึ่งช่วยให้นักพัฒนาแอปควบคุมได้ละเอียดยิ่งขึ้น การใช้การใช้งานที่สร้างไว้ล่วงหน้าช่วยให้คุณสร้างแอปที่มีฟีเจอร์มากมายได้อย่างรวดเร็วโดยไม่ต้องเขียนโค้ดมากนัก หากต้องการปรับแต่งเพิ่มเติม คุณสามารถขยายคอมโพเนนต์ที่สร้างไว้ล่วงหน้าของไลบรารีได้
ตัวควบคุมและเพลเยอร์
ชุดเครื่องมือ UI ของ Leanback แยก UI ของตัวควบคุมการส่งออกจากเพลเยอร์ที่เล่นวิดีโอ ซึ่งทำได้ด้วยคอมโพเนนต์ 2 รายการ ได้แก่ แฟรกเมนต์การรองรับการเล่นสำหรับแสดงตัวควบคุมการส่ง (และวิดีโอหากต้องการ) และ อะแดปเตอร์เพลเยอร์สำหรับห่อหุ้มมีเดียเพลเยอร์
แฟรกเมนต์การเล่น
กิจกรรม UI ของแอปควรใช้ PlaybackSupportFragment หรือ VideoSupportFragment
ทั้ง 2 อย่างมีตัวควบคุมการส่งของ Leanback ดังนี้
PlaybackSupportFragmentจะสร้างภาพเคลื่อนไหวให้ตัวควบคุมการส่งเพื่อซ่อน/แสดงตามความจำเป็นVideoSupportFragmentขยายPlaybackSupportFragmentและมีSurfaceViewสำหรับแสดงวิดีโอ
คุณสามารถปรับแต่ง ObjectAdapter ของแฟรกเมนต์เพื่อปรับปรุง UI ได้ เช่น ใช้ setAdapter() เพื่อเพิ่มแถว "วิดีโอที่เกี่ยวข้อง"
PlayerAdapter
PlayerAdapter เป็นคลาสแอบสแตรกต์ที่ควบคุมมีเดียเพลเยอร์พื้นฐาน นักพัฒนาแอปสามารถเลือกการใช้งาน MediaPlayerAdapter ที่สร้างไว้ล่วงหน้า หรือเขียนการใช้งานคลาสนี้เองก็ได้
การเชื่อมโยงส่วนต่างๆ เข้าด้วยกัน
คุณต้องใช้ "ตัวเชื่อมการควบคุม" เพื่อเชื่อมต่อแฟรกเมนต์การเล่นกับเพลเยอร์ ไลบรารี Leanback มีตัวเชื่อม 2 ประเภท ได้แก่
PlaybackBannerControlGlueจะวาดตัวควบคุมการส่งในแฟรกเมนต์การเล่นใน "สไตล์เก่า" โดยวางไว้ภายในพื้นหลังทึบแสง (PlaybackBannerControlGlueแทนที่PlaybackControlGlueซึ่งระบบเลิกใช้งานแล้ว)PlaybackTransportControlGlueใช้ตัวควบคุม "สไตล์ใหม่" ที่มีพื้นหลังโปร่งใส

หากต้องการให้แอปรองรับการสครับวิดีโอ คุณต้องใช้ PlaybackTransportControlGlue
นอกจากนี้ คุณยังต้องระบุ "โฮสต์ตัวเชื่อม" ที่ผูกตัวเชื่อมกับแฟรกเมนต์การเล่น วาดตัวควบคุมการส่งใน UI และรักษาสถานะของตัวควบคุมการส่ง รวมถึงส่งเหตุการณ์ตัวควบคุมการส่งกลับไปยังตัวเชื่อม โฮสต์ต้องตรงกับประเภทแฟรกเมนต์การเล่น ใช้ PlaybackSupportFragmentGlueHost กับ PlaybackFragment และ VideoSupportFragmentGlueHost กับ VideoFragment
ต่อไปนี้คือภาพแสดงวิธีที่ส่วนต่างๆ ของตัวควบคุมการส่งของ Leanback ทำงานร่วมกัน

โค้ดที่เชื่อมโยงแอปเข้าด้วยกันควรอยู่ใน PlaybackSupportFragment หรือ VideoSupportFragment ที่กำหนด UI
ในตัวอย่างต่อไปนี้ แอปจะสร้างอินสแตนซ์ของ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 เพื่อจัดการเหตุการณ์จากมีเดียเพลเยอร์ด้วย
การปรับแต่งตัวเชื่อม UI
คุณสามารถปรับแต่ง 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 จะกำหนดให้กับ 2 กลุ่ม ได้แก่ การดำเนินการหลักและการดำเนินการรอง ตัวควบคุมสำหรับกลุ่มหลักจะปรากฏเหนือแถบเลื่อน และตัวควบคุมสำหรับกลุ่มรองจะปรากฏใต้แถบเลื่อน ในตอนแรกจะมีเพียงการดำเนินการหลักรายการเดียวสำหรับปุ่มเล่น/หยุดชั่วคราว และไม่มีการดำเนินการรอง
คุณสามารถเพิ่มการดำเนินการลงในกลุ่มหลักและกลุ่มรองได้โดยลบล้าง 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