Menggunakan kontrol transpor Leanback

Library leanback androidx memiliki kontrol pemutaran baru yang memberikan pengalaman pengguna yang lebih baik. Untuk aplikasi video, kontrol transport mendukung pemolesan video dengan kontrol maju/mundur. Saat memoles, layar menampilkan thumbnail untuk membantu menavigasi video.

Library ini mencakup class abstrak serta implementasi siap pakai yang memberikan kontrol yang lebih terperinci kepada developer. Dengan implementasi bawaan ini, Anda dapat membuat aplikasi yang kaya fitur dengan cepat, tanpa banyak coding. Jika memerlukan penyesuaian lebih lanjut, Anda dapat menyediakan komponen mana pun dari library bawaan tersebut.

Kontrol dan pemutar

Library leanback memisahkan UI dengan kontrol transport dari pemutar yang memutar video. Hal ini dilakukan dengan dua komponen: playback support fragment untuk menampilkan kontrol transport (dan jika ingin, video) dan player adapter untuk mengenkapsulasi media player.

Playback fragment

Aktivitas UI aplikasi Anda harus menggunakan PlaybackSupportFragment atau VideoSupportFragment. Keduanya berisi kontrol transport leanback:

Anda dapat menyesuaikan ObjectAdapter fragmen untuk menyempurnakan UI. Misalnya, gunakan setAdapter() untuk menambahkan baris "video terkait".

PlayerAdapter

PlayerAdapter adalah class abstrak yang mengontrol media player yang mendasarinya. Developer dapat memilih implementasi MediaPlayerAdapter bawaan, atau menulis implementasi class ini sendiri.

Menyatukan bagian-bagian

Anda harus menggunakan "perekat kontrol" untuk menghubungkan playback fragment dengan pemutar. Library leanback menyediakan dua jenis perekat:

perekat kontrol transport leanback

Agar aplikasi mendukung pemfilteran video, Anda harus menggunakan PlaybackTransportControlGlue.

Anda juga harus menentukan "host perekat" yang menyatukan perekat dengan playback fragment, menggambar kontrol transport di UI dan mempertahankan statusnya, serta mengembalikan peristiwa kontrol transport ke perekat. Host harus cocok dengan jenis playback fragment. Gunakan PlaybackSupportFragmentGlueHost dengan PlaybackFragment, dan VideoSupportFragmentGlueHost dengan VideoFragment.

Berikut adalah ilustrasi yang menunjukkan bagaimana bagian kontrol transport leanback bekerja bersama:

perekat kontrol transport leanback

Kode yang merekatkan aplikasi Anda harus berada di dalam PlaybackSupportFragment atau VideoSupportFragment yang menentukan UI.

Dalam contoh berikut, aplikasi membuat instance PlaybackTransportControlGlue, menamainya dengan playerGlue, dan menghubungkan VideoSupportFragment-nya ke MediaPlayerAdapter yang baru dibuat. Karena ini adalah VideoSupportFragment kode penyiapan memanggil setHost() untuk menyertakan VideoSupportFragmentGlueHost ke playerGlue. Kode tersebut disertakan di dalam class yang memperluas 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));
      }
    }
    

Perhatikan bahwa kode penyiapan juga menentukan PlayerAdapter.Callback untuk menangani peristiwa dari media player.

Menyesuaikan perekat UI

Anda dapat menyesuaikan PlaybackBannerControlGlue dan PlaybackTransportControlGlue untuk mengubah PlaybackControlsRow.

Menyesuaikan judul dan deskripsi

Untuk menyesuaikan judul dan deskripsi di bagian atas kontrol pemutaran, ganti 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;
    }
    

Menambahkan kontrol

Perekat kontrol menampilkan kontrol untuk tindakan dalam PlaybackControlsRow.

Tindakan dalam PlaybackControlsRow ditetapkan ke dua grup: tindakan primer dan tindakan sekunder. Kontrol untuk grup primer muncul di atas kolom pencarian, sedangkan kontrol untuk grup sekunder muncul di bawah kolom pencarian. Awalnya, hanya ada satu tindakan primer untuk tombol putar/jeda, dan tidak ada tindakan sekunder.

Anda dapat menambahkan tindakan ke grup primer dan sekunder dengan mengganti onCreatePrimaryActions() dan 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);
    }
    

Anda harus mengganti onActionClicked() untuk menangani tindakan baru.

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.
    }
    

Dalam kasus khusus, Anda dapat mengimplementasikan PlaybackTransportRowPresenter Anda sendiri untuk merender kontrol kustom dan merespons tindakan pencarian menggunakan PlaybackSeekUi.

Memoles video

Jika aplikasi menggunakan VideoSupportFragment dan Anda ingin mendukung pemolesan video.

pemolesan

Anda perlu menyediakan implementasi PlaybackSeekDataProvider. Komponen ini menyediakan thumbnail video yang digunakan saat melakukan scrolling. Anda harus mengimplementasikan penyedia Anda sendiri dengan memperluas PlaybackSeekDataProvider. Lihat contohnya dalam aplikasi contoh Android Leanback Showcase di repositori GitHub Android TV. .