পরিবহন নিয়ন্ত্রণ ব্যবহার করুন

কম্পোজ দিয়ে আরও ভালোভাবে তৈরি করুন
জেটপ্যাক কম্পোজ ব্যবহার করে অ্যান্ড্রয়েড টিভি ওএস-এর জন্য ন্যূনতম কোডে সুন্দর ইউআই তৈরি করুন।

লিনব্যাক UI টুলকিটে এমন প্লেব্যাক কন্ট্রোল রয়েছে যা ব্যবহারকারীর অভিজ্ঞতাকে আরও উন্নত করে। ভিডিও অ্যাপের জন্য, ট্রান্সপোর্ট কন্ট্রোলগুলো ফরওয়ার্ড এবং ব্যাকওয়ার্ড কন্ট্রোলের সাহায্যে ভিডিও স্ক্রাবিং সমর্থন করে। স্ক্রাবিং করার সময়, ভিডিওর মধ্যে দিয়ে নেভিগেট করতে সাহায্য করার জন্য ডিসপ্লেতে থাম্বনেইল দেখানো হয়।

এই লাইব্রেরিতে অ্যাবস্ট্রাক্ট ক্লাসের পাশাপাশি আগে থেকে তৈরি ও রেডিমেড ইমপ্লিমেন্টেশনও রয়েছে, যা ডেভেলপারদের আরও সূক্ষ্ম নিয়ন্ত্রণ প্রদান করে। আগে থেকে তৈরি ইমপ্লিমেন্টেশনগুলো ব্যবহার করে আপনি খুব বেশি কোডিং ছাড়াই দ্রুত একটি ফিচার-সমৃদ্ধ অ্যাপ তৈরি করতে পারেন। যদি আরও কাস্টমাইজেশনের প্রয়োজন হয়, তবে আপনি লাইব্রেরির যেকোনো আগে থেকে তৈরি কম্পোনেন্টকে এক্সটেন্ড করতে পারেন।

নিয়ন্ত্রণ এবং খেলোয়াড়

লিনব্যাক UI টুলকিট ট্রান্সপোর্ট কন্ট্রোল UI-কে ভিডিও প্লেব্যাককারী প্লেয়ার থেকে আলাদা করে। এটি দুটি উপাদানের মাধ্যমে সম্পন্ন করা হয়: ট্রান্সপোর্ট কন্ট্রোল (এবং ঐচ্ছিকভাবে ভিডিও) প্রদর্শনের জন্য একটি প্লেব্যাক সাপোর্ট ফ্র্যাগমেন্ট এবং একটি মিডিয়া প্লেয়ারকে এনক্যাপসুলেট করার জন্য একটি প্লেয়ার অ্যাডাপ্টার

প্লেব্যাক খণ্ড

আপনার অ্যাপের UI Activity-তে একটি PlaybackSupportFragment অথবা একটি VideoSupportFragment ব্যবহার করা উচিত। উভয়ের মধ্যেই লিনব্যাক ট্রান্সপোর্ট কন্ট্রোলগুলো থাকে:

  • একটি PlaybackSupportFragment তার ট্রান্সপোর্ট কন্ট্রোলগুলোকে প্রয়োজন অনুযায়ী লুকানো বা দেখানোর জন্য অ্যানিমেট করে।
  • একটি VideoSupportFragment PlaybackSupportFragment এক্সটেন্ড করে এবং ভিডিও রেন্ডার করার জন্য এতে একটি SurfaceView থাকে।

UI উন্নত করার জন্য আপনি একটি ফ্র্যাগমেন্টের ObjectAdapter কাস্টমাইজ করতে পারেন। উদাহরণস্বরূপ, 'সম্পর্কিত ভিডিও' সারি যোগ করতে setAdapter() ব্যবহার করুন।

প্লেয়ার অ্যাডাপ্টার

PlayerAdapter হলো একটি অ্যাবস্ট্রাক্ট ক্লাস যা অন্তর্নিহিত মিডিয়া প্লেয়ারকে নিয়ন্ত্রণ করে। ডেভেলপাররা আগে থেকে তৈরি MediaPlayerAdapter ইমপ্লিমেন্টেশনটি বেছে নিতে পারেন, অথবা এই ক্লাসের নিজস্ব ইমপ্লিমেন্টেশন লিখতে পারেন।

টুকরোগুলো একসাথে আঠা দিয়ে লাগানো

প্লেব্যাক ফ্র্যাগমেন্টকে প্লেয়ারের সাথে সংযুক্ত করতে আপনাকে অবশ্যই কোনো "কন্ট্রোল গ্লু" ব্যবহার করতে হবে। লিনব্যাক লাইব্রেরি দুই ধরনের গ্লু প্রদান করে:

  • PlaybackBannerControlGlue প্লেব্যাক ফ্র্যাগমেন্টের ট্রান্সপোর্ট কন্ট্রোলগুলোকে "পুরানো শৈলীতে" একটি অস্বচ্ছ পটভূমির ভিতরে অঙ্কন করে। ( PlaybackBannerControlGlue , PlaybackControlGlue প্রতিস্থাপন করে, যা এখন অপ্রচলিত।)
  • PlaybackTransportControlGlue স্বচ্ছ ব্যাকগ্রাউন্ডসহ "নতুন শৈলীর" কন্ট্রোল ব্যবহার করে।

হেলান পরিবহন নিয়ন্ত্রণ আঠা

আপনার অ্যাপে ভিডিও স্ক্রাবিং সমর্থন করতে চাইলে আপনাকে অবশ্যই PlaybackTransportControlGlue ব্যবহার করতে হবে।

আপনাকে একটি "গ্লু হোস্ট"ও নির্দিষ্ট করতে হবে, যা গ্লু-কে প্লেব্যাক ফ্র্যাগমেন্টের সাথে যুক্ত করে, UI-তে ট্রান্সপোর্ট কন্ট্রোলগুলো প্রদর্শন করে ও সেগুলোর অবস্থা বজায় রাখে এবং ট্রান্সপোর্ট কন্ট্রোল ইভেন্টগুলো গ্লু-তে ফেরত পাঠায়। হোস্টটিকে অবশ্যই প্লেব্যাক ফ্র্যাগমেন্টের ধরনের সাথে মিলতে হবে। PlaybackFragment এর সাথে PlaybackSupportFragmentGlueHost এবং VideoFragment এর সাথে VideoSupportFragmentGlueHost ব্যবহার করুন।

এখানে একটি চিত্রের মাধ্যমে দেখানো হয়েছে যে একটি লিনব্যাক ট্রান্সপোর্ট কন্ট্রোলের অংশগুলো কীভাবে একসাথে যুক্ত হয়:

হেলান পরিবহন নিয়ন্ত্রণ আঠা

আপনার অ্যাপটিকে একত্রিত করে রাখা কোডটি UI নির্ধারণকারী PlaybackSupportFragment বা VideoSupportFragment ভিতরে থাকা উচিত।

নিম্নলিখিত উদাহরণে, অ্যাপটি PlaybackTransportControlGlue এর একটি ইনস্ট্যান্স তৈরি করে, যার নাম দেয় playerGlue , এবং এর VideoSupportFragment একটি নতুন তৈরি করা MediaPlayerAdapter সাথে সংযুক্ত করে। যেহেতু এটি একটি VideoSupportFragment , তাই সেটআপ কোডটি playerGlue এর সাথে একটি VideoSupportFragmentGlueHost সংযুক্ত করার জন্য setHost() কল করে। এই কোডটি সেই ক্লাসের ভিতরে অন্তর্ভুক্ত করা হয়েছে যা VideoSupportFragment কে এক্সটেন্ড করে।

কোটলিন

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

জাভা

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 গ্লু কাস্টমাইজ করা

আপনি PlaybackControlsRow পরিবর্তন করতে PlaybackBannerControlGlue এবং PlaybackTransportControlGlue কাস্টমাইজ করতে পারেন।

শিরোনাম এবং বিবরণ কাস্টমাইজ করা

প্লেব্যাক কন্ট্রোলের শীর্ষে থাকা শিরোনাম এবং বিবরণ কাস্টমাইজ করতে, onCreateRowPresenter() ওভাররাইড করুন:

কোটলিন

override fun onCreateRowPresenter(): PlaybackRowPresenter {
    return super.onCreateRowPresenter().apply {
        (this as? PlaybackTransportRowPresenter)
                ?.setDescriptionPresenter(MyCustomDescriptionPresenter())
    }
}

জাভা

@Override
protected PlaybackRowPresenter onCreateRowPresenter() {
  PlaybackTransportRowPresenter presenter = (PlaybackTransportRowPresenter) super.onCreateRowPresenter();
  presenter.setDescriptionPresenter(new MyCustomDescriptionPresenter());
  return presenter;
}

নিয়ন্ত্রণ যোগ করা

কন্ট্রোল গ্লু একটি PlaybackControlsRow এর অ্যাকশনগুলোর জন্য কন্ট্রোল প্রদর্শন করে।

PlaybackControlsRow এর অ্যাকশনগুলোকে দুটি গ্রুপে ভাগ করা হয়েছে: প্রাইমারি অ্যাকশন এবং সেকেন্ডারি অ্যাকশন । প্রাইমারি গ্রুপের কন্ট্রোলগুলো সিক বারের উপরে এবং সেকেন্ডারি গ্রুপের কন্ট্রোলগুলো সিক বারের নিচে দেখা যায়। প্রাথমিকভাবে, প্লে/পজ বাটনের জন্য শুধুমাত্র একটি প্রাইমারি অ্যাকশন থাকে এবং কোনো সেকেন্ডারি অ্যাকশন থাকে না।

আপনি onCreatePrimaryActions() এবং onCreateSecondaryActions() ওভাররাইড করে প্রাইমারি ও সেকেন্ডারি গ্রুপে অ্যাকশন যোগ করতে পারেন।

কোটলিন

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

জাভা

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() ওভাররাইড করতে হবে।

কোটলিন

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

জাভা

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

বিশেষ ক্ষেত্রে, কাস্টম কন্ট্রোল রেন্ডার করতে এবং PlaybackSeekUi ব্যবহার করে সিক অ্যাকশনে সাড়া দিতে আপনি আপনার নিজস্ব PlaybackTransportRowPresenter প্রয়োগ করতে চাইতে পারেন।

ভিডিও স্ক্রাবিং

যদি আপনার অ্যাপ VideoSupportFragment ব্যবহার করে এবং আপনি ভিডিও স্ক্রাবিং সমর্থন করতে চান।

ঘষাঘষি

আপনাকে PlaybackSeekDataProvider এর একটি ইমপ্লিমেন্টেশন প্রদান করতে হবে। এই কম্পোনেন্টটি স্ক্রোল করার সময় ব্যবহৃত ভিডিও থাম্বনেইলগুলো সরবরাহ করে। আপনাকে অবশ্যই PlaybackSeekDataProvider এক্সটেন্ড করে আপনার নিজস্ব প্রোভাইডার ইমপ্লিমেন্ট করতে হবে। Leanback Showcase অ্যাপে উদাহরণটি দেখুন।