Taşıma kontrollerini kullan

Compose ile daha iyi uygulamalar geliştirin
Android TV OS için Jetpack Compose'u kullanarak minimum kodla güzel kullanıcı arayüzleri oluşturun.

Leanback kullanıcı arayüzü araç setinde, daha iyi bir kullanıcı deneyimi sağlayan oynatma kontrolleri bulunur. Video uygulamalarında, ileri ve geri kontrolleriyle video sarma işlemi desteklenir. İlerleme noktasını sürüklerken videoda gezinmeye yardımcı olmak için küçük resimler gösterilir.

Kitaplıkta, geliştiricilere daha ayrıntılı kontrol olanağı sağlayan hazır, kullanıma hazır uygulamaların yanı sıra soyut sınıflar da bulunur. Önceden oluşturulmuş uygulamaları kullanarak çok fazla kod yazmadan zengin özelliklere sahip bir uygulamayı hızlıca oluşturabilirsiniz. Daha fazla özelleştirmeye ihtiyacınız varsa kitaplığın önceden oluşturulmuş bileşenlerinden herhangi birini genişletebilirsiniz.

Kontroller ve oynatıcı

Leanback kullanıcı arayüzü araç seti, aktarım kontrolleri kullanıcı arayüzünü videoyu oynatan oynatıcıdan ayırır. Bu işlem iki bileşenle gerçekleştirilir: taşıma kontrollerini (ve isteğe bağlı olarak videoyu) görüntülemek için oynatma desteği parçası ve bir medya oynatıcıyı kapsüllemek için oynatıcı bağdaştırıcısı.

Oynatma parçası

Uygulamanızın kullanıcı arayüzü etkinliği, PlaybackSupportFragment veya VideoSupportFragment kullanmalıdır. Her ikisinde de Leanback aktarma kontrolleri bulunur:

Kullanıcı arayüzünü iyileştirmek için bir parçanın ObjectAdapter bölümünü özelleştirebilirsiniz. Örneğin, "ilgili videolar" satırı eklemek için setAdapter() kullanın.

PlayerAdapter

PlayerAdapter, temel medya oynatıcıyı kontrol eden soyut bir sınıftır. Geliştiriciler, önceden oluşturulmuş MediaPlayerAdapter uygulamayı seçebilir veya bu sınıfın kendi uygulamalarını yazabilir.

Parçaları birbirine yapıştırma

Oynatma parçasını oynatıcıya bağlamak için bir "kontrol yapıştırıcısı" kullanmanız gerekir. Leanback kitaplığı iki tür yapıştırıcı sağlar:

leanback transport control glue

Uygulamanızın video sarma özelliğini desteklemesini istiyorsanız PlaybackTransportControlGlue kullanmanız gerekir.

Ayrıca, yapıştırıcıyı oynatma parçasına bağlayan, kullanıcı arayüzünde aktarım kontrollerini çizen ve durumlarını koruyan, aktarım kontrolü etkinliklerini yapıştırıcıya geri ileten bir "yapıştırıcı ana makinesi" de belirtmeniz gerekir. Ana makine, oynatma parçası türüyle eşleşmelidir. PlaybackSupportFragmentGlueHost özelliğini PlaybackFragment ile, VideoSupportFragmentGlueHost özelliğini ise VideoFragment ile kullanın.

Aşağıda, rahat izleme için oynatma kontrolünün parçalarının nasıl bir araya geldiğini gösteren bir resim yer almaktadır:

leanback transport control glue

Uygulamanızı bir araya getiren kod, kullanıcı arayüzünü tanımlayan PlaybackSupportFragment veya VideoSupportFragment içinde olmalıdır.

Aşağıdaki örnekte, uygulama PlaybackTransportControlGlue öğesinin bir örneğini oluşturur, bu örneğe playerGlue adını verir ve VideoSupportFragment öğesini yeni oluşturulan bir MediaPlayerAdapter öğesine bağlar. Bu bir VideoSupportFragment olduğundan kurulum kodu, VideoSupportFragmentGlueHost öğesini playerGlue öğesine eklemek için setHost() işlevini çağırır. Kod, VideoSupportFragment öğesini genişleten sınıfın içine eklenir.

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));
  }
}

Kurulum kodunun, medya oynatıcıdaki etkinlikleri işlemek için bir PlayerAdapter.Callback da tanımladığını unutmayın.

Kullanıcı arayüzü yapıştırıcısını özelleştirme

PlaybackControlsRow değerini değiştirmek için PlaybackBannerControlGlue ve PlaybackTransportControlGlue değerlerini özelleştirebilirsiniz.

Başlığı ve açıklamayı özelleştirme

Oynatma kontrollerinin üst kısmındaki başlığı ve açıklamayı özelleştirmek için onCreateRowPresenter() öğesini geçersiz kılın:

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

Kontrol ekleme

Kontrol yapıştırıcısı, PlaybackControlsRow içindeki işlemler için kontrolleri gösterir.

PlaybackControlsRow içindeki işlemler iki gruba atanır: birincil işlemler ve ikincil işlemler. Birincil grubun kontrolleri arama çubuğunun üzerinde, ikincil grubun kontrolleri ise arama çubuğunun altında görünür. Başlangıçta, oynatma/duraklatma düğmesi için yalnızca tek bir birincil işlem vardır ve ikincil işlem yoktur.

onCreatePrimaryActions() ve onCreateSecondaryActions() değerlerini geçersiz kılarak birincil ve ikincil gruplara işlemler ekleyebilirsiniz.

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);
}

Yeni işlemleri işlemek için onActionClicked() geçersiz kılmanız gerekir.

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

Özel durumlarda, özel kontroller oluşturmak ve PlaybackTransportRowPresenter kullanarak arama işlemlerine yanıt vermek için kendi PlaybackSeekUi öğenizi uygulamak isteyebilirsiniz.

Video yükleme göstergesi

Uygulamanızda VideoSupportFragment kullanılıyorsa ve video sarma özelliğini desteklemek istiyorsanız.

ovma

PlaybackSeekDataProvider uygulaması sağlamanız gerekir. Bu bileşen, kaydırma sırasında kullanılan video küçük resimlerini sağlar. PlaybackSeekDataProvider öğesini genişleterek kendi sağlayıcınızı uygulamanız gerekir. Leanback Showcase uygulamasındaki örneğe bakın. .