نمای جزئیات بسازید

با Compose بهتر بسازید
با استفاده از Jetpack Compose برای سیستم عامل Android TV، رابط‌های کاربری زیبایی با حداقل کد ایجاد کنید.

کلاس‌های رابط مرور رسانه که توسط کتابخانه منسوخ‌شده androidx.leanback ارائه می‌شوند، شامل کلاس‌هایی برای نمایش اطلاعات اضافی در مورد یک آیتم رسانه‌ای، مانند توضیحات یا نظرات، هستند. آن‌ها همچنین شامل کلاس‌هایی برای انجام اقدامی روی آن آیتم، مانند خرید آن یا پخش محتوای آن، می‌باشند.

این راهنما نحوه ایجاد یک کلاس ارائه‌دهنده برای جزئیات آیتم رسانه‌ای و نحوه گسترش کلاس DetailsSupportFragment را برای پیاده‌سازی نمای جزئیات برای یک آیتم رسانه‌ای هنگام انتخاب آن توسط کاربر، مورد بحث قرار می‌دهد.

نکته: مثال پیاده‌سازی نشان داده شده در اینجا از یک activity اضافی برای شامل کردن DetailsSupportFragment استفاده می‌کند. با این حال، می‌توان با جایگزینی BrowseSupportFragment با DetailsSupportFragment در همان activity با استفاده از fragment transactionها، از ایجاد activity دوم جلوگیری کرد. برای اطلاعات بیشتر در مورد استفاده از fragment transactionها، به Create a fragment مراجعه کنید.

یک ارائه‌دهنده جزئیات بسازید

در چارچوب مرور رسانه که توسط جعبه ابزار Leanback UI ارائه شده است، شما از اشیاء ارائه دهنده برای کنترل نمایش داده‌ها روی صفحه، از جمله جزئیات آیتم رسانه، استفاده می‌کنید. برای این منظور، این چارچوب کلاس AbstractDetailsDescriptionPresenter را ارائه می‌دهد که تقریباً پیاده‌سازی کاملی از ارائه دهنده برای جزئیات آیتم رسانه است. تنها کاری که باید انجام دهید پیاده‌سازی متد onBindDescription() برای اتصال فیلدهای نما به اشیاء داده شماست، همانطور که در نمونه کد زیر نشان داده شده است:

کاتلین

class DetailsDescriptionPresenter : AbstractDetailsDescriptionPresenter() {

    override fun onBindDescription(viewHolder: AbstractDetailsDescriptionPresenter.ViewHolder, itemData: Any) {
        val details = itemData as MyMediaItemDetails
        // In a production app, the itemData object contains the information
        // needed to display details for the media item:
        // viewHolder.title.text = details.shortTitle

        // Here we provide static data for testing purposes:
        viewHolder.apply {
            title.text = itemData.toString()
            subtitle.text = "2014   Drama   TV-14"
            body.text = ("Lorem ipsum dolor sit amet, consectetur "
                    + "adipisicing elit, sed do eiusmod tempor incididunt ut labore "
                    + " et dolore magna aliqua. Ut enim ad minim veniam, quis "
                    + "nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
                    + "commodo consequat.")
        }
    }
}

جاوا

public class DetailsDescriptionPresenter
        extends AbstractDetailsDescriptionPresenter {

    @Override
    protected void onBindDescription(ViewHolder viewHolder, Object itemData) {
        MyMediaItemDetails details = (MyMediaItemDetails) itemData;
        // In a production app, the itemData object contains the information
        // needed to display details for the media item:
        // viewHolder.getTitle().setText(details.getShortTitle());

        // Here we provide static data for testing purposes:
        viewHolder.getTitle().setText(itemData.toString());
        viewHolder.getSubtitle().setText("2014   Drama   TV-14");
        viewHolder.getBody().setText("Lorem ipsum dolor sit amet, consectetur "
                + "adipisicing elit, sed do eiusmod tempor incididunt ut labore "
                + " et dolore magna aliqua. Ut enim ad minim veniam, quis "
                + "nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
                + "commodo consequat.");
    }
}

قطعه جزئیات را گسترش دهید

هنگام استفاده از کلاس DetailsSupportFragment برای نمایش جزئیات آیتم رسانه‌ای خود، آن کلاس را برای ارائه محتوای اضافی، مانند تصویر پیش‌نمایش و اقدامات برای آیتم رسانه‌ای، گسترش دهید. همچنین می‌توانید محتوای اضافی، مانند لیستی از آیتم‌های رسانه‌ای مرتبط، ارائه دهید.

کد مثال زیر نحوه استفاده از کلاس presenter که در بخش قبل نشان داده شد را برای افزودن تصویر پیش‌نمایش و اکشن‌ها برای آیتم رسانه‌ای که در حال مشاهده است، نشان می‌دهد. این مثال همچنین افزودن ردیف آیتم‌های رسانه‌ای مرتبط را نشان می‌دهد که در زیر فهرست جزئیات ظاهر می‌شود.

کاتلین

private const val TAG = "MediaItemDetailsFragment"

class MediaItemDetailsFragment : DetailsSupportFragment() {
    private lateinit var rowsAdapter: ArrayObjectAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        Log.i(TAG, "onCreate")
        super.onCreate(savedInstanceState)

        buildDetails()
    }

    private fun buildDetails() {
        val selector = ClassPresenterSelector().apply {
            // Attach your media item details presenter to the row presenter:
            FullWidthDetailsOverviewRowPresenter(DetailsDescriptionPresenter()).also {
                addClassPresenter(DetailsOverviewRow::class.java, it)
            }
            addClassPresenter(ListRow::class.java, ListRowPresenter())
        }
        rowsAdapter = ArrayObjectAdapter(selector)

        val res = activity.resources
        val detailsOverview = DetailsOverviewRow("Media Item Details").apply {

            // Add images and action buttons to the details view
            imageDrawable = res.getDrawable(R.drawable.jelly_beans)
            addAction(Action(1, "Buy $9.99"))
            addAction(Action(2, "Rent $2.99"))
        }
        rowsAdapter.add(detailsOverview)

        // Add a related items row
        val listRowAdapter = ArrayObjectAdapter(StringPresenter()).apply {
            add("Media Item 1")
            add("Media Item 2")
            add("Media Item 3")
        }
        val header = HeaderItem(0, "Related Items")
        rowsAdapter.add(ListRow(header, listRowAdapter))

        adapter = rowsAdapter
    }
}

جاوا

public class MediaItemDetailsFragment extends DetailsSupportFragment {
    private static final String TAG = "MediaItemDetailsFragment";
    private ArrayObjectAdapter rowsAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "onCreate");
        super.onCreate(savedInstanceState);

        buildDetails();
    }

    private void buildDetails() {
        ClassPresenterSelector selector = new ClassPresenterSelector();
        // Attach your media item details presenter to the row presenter:
        FullWidthDetailsOverviewRowPresenter rowPresenter =
            new FullWidthDetailsOverviewRowPresenter(
                new DetailsDescriptionPresenter());

        selector.addClassPresenter(DetailsOverviewRow.class, rowPresenter);
        selector.addClassPresenter(ListRow.class,
                new ListRowPresenter());
        rowsAdapter = new ArrayObjectAdapter(selector);

        Resources res = getActivity().getResources();
        DetailsOverviewRow detailsOverview = new DetailsOverviewRow(
                "Media Item Details");

        // Add images and action buttons to the details view
        detailsOverview.setImageDrawable(res.getDrawable(R.drawable.jelly_beans));
        detailsOverview.addAction(new Action(1, "Buy $9.99"));
        detailsOverview.addAction(new Action(2, "Rent $2.99"));
        rowsAdapter.add(detailsOverview);

        // Add a related items row
        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
                new StringPresenter());
        listRowAdapter.add("Media Item 1");
        listRowAdapter.add("Media Item 2");
        listRowAdapter.add("Media Item 3");
        HeaderItem header = new HeaderItem(0, "Related Items", null);
        rowsAdapter.add(new ListRow(header, listRowAdapter));

        setAdapter(rowsAdapter);
    }
}

ایجاد یک فعالیت جزئیات

قطعاتی مانند DetailsSupportFragment باید در یک activity قرار گیرند تا برای نمایش استفاده شوند. ایجاد یک activity برای نمای جزئیات (details view) - جدا از activity مرور (browse activity) - به شما امکان می‌دهد نمای جزئیات (details view) خود را با استفاده از یک Intent فراخوانی کنید. این بخش نحوه ساخت یک activity را توضیح می‌دهد که شامل پیاده‌سازی شما از نمای جزئیات برای آیتم‌های رسانه‌ای شما باشد.

با ساختن یک طرح‌بندی که به پیاده‌سازی DetailsSupportFragment شما ارجاع می‌دهد، فعالیت details را ایجاد کنید:

<!-- file: res/layout/details.xml -->

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.example.android.mediabrowser.MediaItemDetailsFragment"
    android:id="@+id/details_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
/>

در مرحله بعد، یک کلاس فعالیت ایجاد کنید که از طرح‌بندی نشان داده شده در مثال کد قبلی استفاده کند:

کاتلین

class DetailsActivity : FragmentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.details)
    }
}

جاوا

public class DetailsActivity extends FragmentActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.details);
    }
}

در نهایت، این اکتیویتی جدید را به مانیفست اضافه کنید. به یاد داشته باشید که تم Leanback را اعمال کنید تا مطمئن شوید که رابط کاربری با اکتیویتی مرور رسانه سازگار است.

<application>
  ...
  <activity android:name=".DetailsActivity"
    android:exported="true"
    android:theme="@style/Theme.Leanback"/>

</application>

تعریف یک شنونده برای آیتم‌های کلیک‌شده

پس از پیاده‌سازی DetailsSupportFragment ، نمای اصلی مرور رسانه خود را طوری تغییر دهید که وقتی کاربر روی یک آیتم رسانه‌ای کلیک می‌کند، به نمای جزئیات شما منتقل شود. برای فعال کردن این رفتار، یک شیء OnItemViewClickedListener به BrowseSupportFragment اضافه کنید که یک intent برای شروع فعالیت جزئیات آیتم ایجاد کند.

مثال زیر نحوه پیاده‌سازی یک شنونده (listener) را برای شروع نمایش جزئیات (details view) هنگام کلیک کاربر روی یک آیتم رسانه در فعالیت اصلی مرور رسانه نشان می‌دهد:

کاتلین

class BrowseMediaActivity : FragmentActivity() {
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Create the media item rows
        buildRowsAdapter()

        // Add a listener for selected items
        browseFragment.onItemViewClickedListener = OnItemViewClickedListener { _, item, _, _ ->
            println("Media Item clicked: ${item}")
            val intent = Intent(this@BrowseMediaActivity, DetailsActivity::class.java).apply {
                // Pass the item information
                extras.putLong("id", item.getId())
            }
            startActivity(intent)
        }
    }
}

جاوا

public class BrowseMediaActivity extends FragmentActivity {
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        // Create the media item rows
        buildRowsAdapter();

        // Add a listener for selected items
        browseFragment.OnItemViewClickedListener(
            new OnItemViewClickedListener() {
                @Override
                public void onItemClicked(Object item, Row row) {
                    System.out.println("Media Item clicked: " + item.toString());
                    Intent intent = new Intent(BrowseMediaActivity.this,
                            DetailsActivity.class);
                    // Pass the item information
                    intent.getExtras().putLong("id", item.getId());
                    startActivity(intent);
                }
            });
    }
}