إنشاء متصفِّح كتالوج

يجب أن يسمح تطبيق الوسائط الذي يتم تشغيله على التلفزيون للمستخدمين بتصفّح المحتوى الذي يوفّره واختيار المحتوى الذي تريد إتاحتها وبدء تشغيل المحتوى. وينبغي أن تكون تجربة تصفح المحتوى للتطبيقات من هذا النوع بسيطة وبديهية، وممتعة وجذابة بصريًا.

يوضّح هذا القسم كيفية استخدام الوظائف التي توفّرها ميزة Compose for TV في تنفيذ واجهة مستخدم لتصفّح الموسيقى أو الفيديوهات من كتالوج الوسائط الخاص بتطبيقك.

الشكل 1. شاشة كتالوج نموذجية يمكن للمستخدمين تصفُّح بيانات كتالوج الفيديو.

يميل متصفح كتالوج الوسائط إلى أن يتكون من عدة أقسام، ويحتوي كل قسم على قائمة بمحتوى الوسائط. تشمل أمثلة الأقسام في كتالوج الوسائط: قوائم التشغيل والمحتوى المميز والفئات الموصى بها

إنشاء دالة قابلة للإنشاء للكتالوج

يتم تنفيذ كل شيء يظهر على الشاشة كوظيفة قابلة للإنشاء في Compose for TV. ستبدأ بتعريف دالة قابلة للإنشاء في متصفّح كتالوج الوسائط على هيئة المقتطف التالي:

@Composable
fun CatalogBrowser(
   featuredContentList: List<Movie>,
   sectionList: List<Section>,
   modifier: Modifier = Modifier,
   onItemSelected: (Movie) -> Unit = {},
) {
// ToDo: add implementation
}

CatalogBrowser هي الوظيفة القابلة للإنشاء التي تنفّذ متصفّح كتالوج الوسائط الخاص بك. تستخدم الدالة الوسيطات التالية:

  • قائمة بالمحتوى المتميّز
  • قائمة الأقسام
  • كائن "تعديل".
  • دالة رد اتصال تؤدي إلى تشغيل انتقال الشاشة.

ضبط عناصر واجهة المستخدم

توفّر ميزة "إنشاء محتوى للتلفزيون" قوائم بطيئة، ومكوِّنًا لعرض عدد كبير من العناصر (أو قائمة بطول غير معروف). ستطلب استدعاء TvLazyColumn لوضع الأقسام عموديًا. توفّر السمة TvLazyColumn حظر TvLazyListScope.() -> Unit الذي يوفّر DSL لتحديد محتوى العنصر. في المثال التالي، يتم وضع كل قسم في قائمة رأسية مع فجوة تبلغ 16 وحدة بكسل مستقلة الكثافة بين الأقسام.

@Composable
fun CatalogBrowser(
   featuredContentList: List<Movie>,
   sectionList: List<Section>,
   modifier: Modifier = Modifier,
   onItemSelected: (Movie) -> Unit = {},
) {
  TvLazyColumn(
    modifier = modifier.fillMaxSize(),
    verticalArrangement = Arrangement.spacedBy(16.dp)
  ) {
    items(sectionList) { section ->
      Section(section, onItemSelected = onItemSelected)
    }
  }
}

في المثال، تحدِّد الدالة Section القابلة للإنشاء كيفية عرض الأقسام. في الدالة التالية، توضّح TvLazyRow كيف يتم استخدام هذا الإصدار الأفقي من TvLazyColumn على نحو مماثل لتعريف قائمة أفقية ذات كتلة TvLazyListScope.() -> Unit من خلال استدعاء DSL المقدّم.

@Composable
fun Section(
  section: Section,
  modifier: Modifier = Modifier,
  onItemSelected: (Movie) -> Unit = {},
) {
  Text(
    text = section.title,
    style = MaterialTheme.typography.headlineSmall,
  )
  TvLazyRow(
     modifier = modifier,
     horizontalArrangement = Arrangement.spacedBy(8.dp)
  ) {
    items(section.movieList){ movie ->
    MovieCard(
         movie = movie,
         onClick = { onItemSelected(movie) }
       )
    }
  }
}

في المكوِّن Section القابل للإنشاء، يتم استخدام المكوِّن Text. يتم توفير النص والمكونات الأخرى المحددة في Material Design في مكتبة tv-material . يمكنك تغيير نمط النصوص على النحو المحدّد في Material Design من خلال الإشارة إلى الكائن MaterialTheme. تتوفّر هذا العنصر أيضًا من خلال مكتبة tv-material. MovieCard يحدد طريقة عرض بيانات كل فيلم في الكتالوج بصفته المقتطف التالي. تُعدّ Card أيضًا جزءًا من مكتبة مواد التلفزيون.

@Composable
fun MovieCard(
   movie: Movie,
   modifier: Modifier = Modifier,
   onClick: () -> Unit = {}
) {
   Card(modifier = modifier, onClick = onClick){
    AsyncImage(
       model = movie.thumbnailUrl,
       contentDescription = movie.title,
     )
   }
}

في المثال الموضح سابقًا، يتم عرض جميع الأفلام بالتساوي. لديهم نفس المنطقة، ولا يوجد اختلاف مرئي بينهما. ويمكنك تمييز بعض منها باستخدام Carousel.

تعرض منصة العرض بعناصر متغيّرة المعلومات في مجموعة من العناصر التي يمكن تمريرها أو تلاشي أو تتحرك إلى العرض. يمكنك استخدام المكون لإبراز المحتوى المميز، مثل الأفلام المتاحة حديثًا أو الحلقات الجديدة من البرامج التلفزيونية.

Carousel: من المتوقع أن تحدّد على الأقل عدد العناصر التي تحتوي عليها لوحة العرض الدوّارة وكيفية رسم كل عنصر. يمكن تحديد القيمة الأولى باستخدام itemCount. ويمكن تمرير الحالة الثانية على أنها لامدا. يتم منح رقم الفهرس للعنصر المعروض إلى lambda. يمكنك تحديد العنصر المعروض بقيمة الفهرس المحددة.

@Composable
function FeaturedCarousel(
  featuredContentList: List<Movie>,
  modifier: Modifier = Modifier,
) {
  Carousel(
    itemCount = featuredContentList.size,
    modifier = modifier,
  ) { index ->
    val content = featuredContentList[index]
    Box {
      AsyncImage(
        model = content.backgroundImageUrl,
        contentDescription = content.description,
        placeholder = painterResource(
          id = R.drawable.placeholder
        ),
        contentScale = ContentScale.Crop,
        modifier = Modifier.fillMaxSize()
      )
      Text(text = content.title)
    }
  }
}

يمكن أن يكون Carousel عنصرًا في قائمة بطيئة، مثل TvLazyColumn. يعرض المقتطف التالي عنصر FeaturedCarousel قابل للإنشاء فوق كل عناصر Section القابلة للإنشاء.

@Composable
fun CatalogBrowser(
   featuredContentList: List<Movie>,
   sectionList: List<Section>,
   modifier: Modifier = Modifier,
   onItemSelected: (Movie) -> Unit = {},
) {
  TvLazyColumn(
    modifier = modifier.fillMaxSize(),
    verticalArrangement = Arrangement.spacedBy(16.dp)
  ) {

    item {
      FeaturedCarousel(featuredContentList)
    }

    items(sectionList) { section ->
      Section(section, onItemSelected = onItemSelected)
    }
  }
}