Menggunakan kontrol transportasi

Membangun aplikasi dengan lebih baik menggunakan Compose
Membuat UI yang menarik dengan kode minimal menggunakan Jetpack Compose untuk Android TV OS.

Toolkit UI Leanback memiliki kontrol pemutaran yang memberikan {i>user experience<i}. Untuk aplikasi video, kontrol transportasi mendukung scrubbing video dengan kontrol maju dan mundur. Saat menggosok layar menunjukkan untuk membantu menavigasi video.

Library ini mencakup class abstrak serta implementasi siap pakai bawaan yang memberikan kontrol lebih terperinci bagi developer. Menggunakan Anda bisa dengan cepat membangun aplikasi yang kaya fitur tanpa banyak coding. Jika memerlukan penyesuaian lebih lanjut, Anda dapat menyediakan komponen.

Kontrol dan pemutar

Toolkit UI Leanback memisahkan UI kontrol transport dari pemutar yang memutar video. Hal ini dilakukan dengan dua komponen: fragmen dukungan pemutaran untuk menampilkan kontrol transport (dan ((opsional) video) dan adaptor pemutar untuk mengenkapsulasi pemutar media.

Playback fragment

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

Anda bisa menyesuaikan elemen ObjectAdapter untuk meningkatkan UI. Misalnya, gunakan setAdapter() untuk menambahkan "video terkait" baris.

PlayerAdapter

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

Menyatukan bagian-bagian

Anda harus menggunakan "perekat kontrol" untuk menghubungkan pemutaran fragmen kepada pemain. Garis miring {i>library<i} menyediakan dua jenis perekat:

perekat kontrol transport leanback

Jika ingin aplikasi Anda mendukung pemolesan video, Anda harus menggunakan PlaybackTransportControlGlue.

Anda juga perlu menentukan "host glue" sehingga mengikat lem ke pemutaran fragmen, menggambar kontrol transport di UI dan mempertahankan statusnya, serta melewati peristiwa kontrol transport kembali ke lem. Host harus cocok dengan jenis playback fragment. Gunakan PlaybackSupportFragmentGlueHost dengan PlaybackFragment, dan VideoSupportFragmentGlueHost dengan VideoFragment.

Berikut adalah ilustrasi yang menunjukkan bagaimana bagian kontrol transport Lean saling bekerja sama:

perekat kontrol transport leanback

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

Dalam misalnya, aplikasi membuat instance PlaybackTransportControlGlue, menamainya playerGlue, dan menghubungkan VideoSupportFragment-nya ke MediaPlayerAdapter yang baru dibuat. Sejak ini adalah VideoSupportFragment yang dipanggil kode penyiapan setHost() untuk melampirkan VideoSupportFragmentGlueHost ke playerGlue. Kode 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 pemutar media.

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, penggantian 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 di PlaybackControlsRow ditetapkan ke dua kelompok: tindakan primer dan sekunder tindakan. Kontrol untuk grup utama muncul di atas bilah pencarian dan kontrol untuk dan grup sekunder akan muncul di bawah bilah geser. Awalnya, hanya ada satu tindakan utama untuk tombol putar/jeda, dan tidak ada tindakan sekunder.

Anda dapat menambahkan tindakan ke grup utama 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 mungkin ingin menerapkan PlaybackTransportRowPresenter 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 di Aplikasi Leanback Showcase. kami.