Ayrıntılar görünümü oluşturma

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.

Kullanımdan kaldırılan androidx.leanback kitaplığı tarafından sağlanan medya tarama arayüzü sınıfları, bir medya öğesiyle ilgili ek bilgileri (ör. açıklama veya yorumlar) görüntülemeye yönelik sınıflar içerir. Ayrıca, bu öğeyle ilgili işlem yapma (ör. satın alma veya içeriğini oynatma) sınıfları da içerir.

Bu kılavuzda, medya öğesi ayrıntıları için nasıl sunucu sınıfı oluşturulacağı ve kullanıcının bir medya öğesini seçtiğinde ayrıntılar görünümünü uygulamak için DetailsSupportFragment sınıfının nasıl genişletileceği açıklanmaktadır.

Not: Burada gösterilen uygulama örneğinde, DetailsSupportFragment öğesini içerecek ek bir etkinlik kullanılmaktadır. Ancak, parça işlemleri kullanarak aynı etkinlik içinde BrowseSupportFragment yerine DetailsSupportFragment koyarak ikinci bir etkinlik oluşturmaktan kaçınmak mümkündür. Parça işlemleri kullanma hakkında daha fazla bilgi için Parça oluşturma başlıklı makaleyi inceleyin.

Ayrıntı sunucusu oluşturma

Leanback UI araç seti tarafından sağlanan medya tarama çerçevesinde, medya öğesi ayrıntıları da dahil olmak üzere ekrandaki verilerin gösterimini kontrol etmek için sunucu nesnelerini kullanırsınız. Bu amaçla, çerçeve, medya öğesi ayrıntıları için sunum yapan kişinin neredeyse eksiksiz bir uygulaması olan AbstractDetailsDescriptionPresenter sınıfını sağlar. Tek yapmanız gereken, aşağıdaki kod örneğinde gösterildiği gibi görünüm alanlarını veri nesnelerinize bağlamak için onBindDescription() yöntemini uygulamaktır:

Kotlin

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

Java

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

Ayrıntılar parçasını genişletme

Medya öğesi ayrıntılarınızı göstermek için DetailsSupportFragment sınıfını kullanırken önizleme resmi ve medya öğesiyle ilgili işlemler gibi ek içerikler sağlamak için bu sınıfı genişletin. Ayrıca, ilgili medya öğelerinin listesi gibi ek içerikler de sağlayabilirsiniz.

Aşağıdaki örnek kod, görüntülenen medya öğesi için önizleme resmi ve işlemler eklemek üzere önceki bölümde gösterilen sunucu sınıfının nasıl kullanılacağını gösterir. Bu örnekte, ayrıntılar listesinin altında görünen ilgili medya öğeleri satırının eklenmesi de gösterilmektedir.

Kotlin

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

Java

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

Ayrıntılar etkinliği oluşturma

DetailsSupportFragment gibi parçaların, görüntüleme için kullanılabilmesi amacıyla bir etkinlik içinde yer alması gerekir. Göz atma etkinliğinden ayrı olarak ayrıntılar görünümünüz için bir etkinlik oluşturduğunuzda, Intent kullanarak ayrıntılar görünümünüzü çağırabilirsiniz. Bu bölümde, medya öğelerinizin ayrıntı görünümü uygulamasını içerecek bir etkinliğin nasıl oluşturulacağı açıklanmaktadır.

DetailsSupportFragment uygulamanıza referans veren bir düzen oluşturarak ayrıntılar etkinliğini oluşturun:

<!-- 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"
/>

Ardından, önceki kod örneğinde gösterilen düzeni kullanan bir etkinlik sınıfı oluşturun:

Kotlin

class DetailsActivity : FragmentActivity() {

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

Java

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

Son olarak, bu yeni etkinliği manifeste ekleyin. Kullanıcı arayüzünün medya göz atma etkinliğiyle tutarlı olmasını sağlamak için Leanback temasını uygulamayı unutmayın.

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

</application>

Tıklanan öğeler için bir işleyici tanımlama

DetailsSupportFragment uyguladıktan sonra, kullanıcı bir medya öğesini tıkladığında ayrıntılar görünümüne geçmek için ana medya tarama görünümünüzü değiştirin. Bu davranışı etkinleştirmek için öğe ayrıntıları etkinliğini başlatma amaçlı bir intent'i tetikleyen OnItemViewClickedListener nesnesini BrowseSupportFragment öğesine ekleyin.

Aşağıdaki örnekte, kullanıcı ana medya tarama etkinliğinde bir medya öğesini tıkladığında ayrıntılar görünümünü başlatmak için bir işleyicinin nasıl uygulanacağı gösterilmektedir:

Kotlin

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

Java

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