یک مرورگر کاتالوگ ایجاد کنید

یک برنامه رسانه‌ای که روی تلویزیون اجرا می‌شود، باید به کاربران اجازه دهد تا محتوای پیشنهادی آن را مرور کنند، انتخاب کنند و شروع به پخش محتوا کنند. تجربه مرور محتوا برای برنامه‌هایی از این نوع باید ساده، شهودی و از نظر بصری دلپذیر و جذاب باشد.

یک مرورگر کاتالوگ رسانه معمولاً از چندین بخش تشکیل شده است و هر بخش لیستی از محتوای رسانه‌ای دارد. نمونه‌هایی از بخش‌های موجود در یک کاتالوگ رسانه‌ای عبارتند از: لیست‌های پخش، محتوای ویژه، دسته‌های پیشنهادی.

شکل ۱. صفحه نمایش کاتالوگ معمولی. کاربران می‌توانند داده‌های کاتالوگ ویدیویی را مرور کنند.

از توابع ارائه شده توسط Compose for TV برای پیاده‌سازی رابط کاربری جهت مرور موسیقی یا ویدیوها از کاتالوگ رسانه برنامه خود استفاده کنید.

یک تابع ترکیبی برای کاتالوگ ایجاد کنید

هر چیزی که روی صفحه نمایش ظاهر می‌شود، به عنوان یک تابع قابل ترکیب در Compose for TV پیاده‌سازی شده است. با تعریف یک تابع قابل ترکیب برای مرورگر کاتالوگ رسانه شروع کنید:

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

CatalogBrowser تابعی قابل ترکیب است که مرورگر کاتالوگ رسانه شما را پیاده‌سازی می‌کند. این تابع آرگومان‌های زیر را دریافت می‌کند:

  • فهرست محتوای ویژه.
  • فهرست بخش‌ها.
  • یک شیء اصلاح‌کننده (Modifier).
  • یک تابع فراخوانی (callback function) که باعث تغییر صفحه نمایش می‌شود.

تنظیم عناصر رابط کاربری

کامپوننت Compose for TV لیست‌های تنبل (lazy lists) را ارائه می‌دهد، کامپوننتی برای نمایش تعداد زیادی آیتم (یا لیستی با طول نامشخص). برای قرار دادن بخش‌ها به صورت عمودی، LazyColumn فراخوانی کنید. LazyColumn یک بلوک LazyListScope.() -> Unit ارائه می‌دهد که یک DSL برای تعریف محتوای آیتم ارائه می‌دهد. در مثال زیر، هر بخش در یک لیست عمودی با فاصله 16 dp بین بخش‌ها قرار می‌گیرد:

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

در مثال، تابع قابل ترکیب Section نحوه نمایش بخش‌ها را تعریف می‌کند. در تابع زیر، LazyRow نشان می‌دهد که چگونه این نسخه افقی LazyColumn به طور مشابه برای تعریف یک لیست افقی با بلوک LazyListScope.() -> Unit با فراخوانی DSL ارائه شده استفاده می‌شود:

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

در Section قابل ترکیب، از کامپوننت Text استفاده شده است. متن و سایر کامپوننت‌های تعریف شده در طراحی متریال در کتابخانه tv-material ارائه می‌شوند. می‌توانید سبک متون را مطابق تعریف شده در طراحی متریال با مراجعه به شیء MaterialTheme تغییر دهید. این شیء همچنین توسط کتابخانه tv-material ارائه می‌شود. Card بخشی از کتابخانه tv-material است. MovieCard نحوه رندر شدن هر داده فیلم را در کاتالوگی که به صورت قطعه کد زیر تعریف شده است، تعریف می‌کند:

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

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

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

Carousel از شما انتظار دارد که حداقل تعداد آیتم‌هایی که Carousel دارد و نحوه‌ی نمایش هر آیتم را مشخص کنید. مورد اول را می‌توان با itemCount مشخص کرد. مورد دوم را می‌توان به عنوان یک lambda ارسال کرد. شماره‌ی اندیس آیتم نمایش داده شده به 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 می‌تواند یک آیتم از یک لیست lazy مانند TvLazyColumn باشد. قطعه کد زیر FeaturedCarousel composable را در بالای همه Section composables نشان می‌دهد:

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