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