יצירת דפדפן של קטלוג

אפליקציית מדיה שפועלת בטלוויזיה צריכה לאפשר למשתמשים לעיין באפשרויות התוכן שלה, לבחור אפשרות ולהתחיל להפעיל את התוכן. חוויית הגלישה בתוכן באפליקציות מהסוג הזה צריכה להיות פשוטה, אינטואיטיבית, נעימה מבחינה ויזואלית ומעניינת.

דפדפן של קטלוג מדיה בדרך כלל מורכב מכמה קטעים, וכל קטע מכיל רשימה של תוכן מדיה. דוגמאות לקטעים בקטלוג מדיה: פלייליסטים, תוכן נבחר, קטגוריות מומלצות.

איור 1. מסך קטלוג אופייני. המשתמשים יכולים לעיין בנתונים בקטלוג הסרטונים.

אפשר להשתמש בפונקציות של 'כתיבה לטלוויזיה' כדי להטמיע ממשק משתמש כדי לעיין במוזיקה או בסרטונים מקטלוג המדיה של האפליקציה.

יצירת פונקציה הניתנת להגדרה לקטלוג

כל מה שמופיע במסך מיושם כפונקציה שניתנת ליצירה ב-Compose for TV. בתור התחלה, מגדירים פונקציה קומפוזבילית לדפדפן של קטלוג המדיה:

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

CatalogBrowser היא הפונקציה הניתנת להגדרה שמטמיעה את הדפדפן של קטלוג המדיה. הפונקציה מקבלת את הארגומנטים הבאים:

  • רשימה של תוכן מוצג.
  • רשימת הקטעים.
  • אובייקט Modifier.
  • פונקציית קריאה חוזרת (callback), שמפעילה מעבר מסך.

הגדרת רכיבים בממשק המשתמש

Compose for TV מציע רשימות 'לאט', רכיב להצגת מספר גדול של פריטים (או רשימה באורך לא ידוע). כדי למקם את הקטעים אנכית, צריך להפעיל את הפונקציה LazyColumn. LazyColumn מספק בלוק LazyListScope.() -> Unit, שמציע DSL להגדרת תוכן של פריטים. בדוגמה הבאה, כל קטע ממוקם ברשימה אנכית עם רווח של 16dp בין קטעים:

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

ב-composable של Section נעשה שימוש ברכיב Text. טקסט ורכיבים אחרים שמוגדרים ב-Material Design זמינים בספרייה 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 מחייבת לציין לפחות את מספר הפריטים שיש בקרוסלה ואת הדרך שבה צריך לשרטט כל פריט. אפשר לציין את האפשרות הראשונה באמצעות itemCount. אפשר להעביר את השנייה בתור למבדה. מספר האינדקס של הפריט המוצג מוענק לפונקציית הלמהדה. אפשר לקבוע את הפריט המוצג לפי ערך האינדקס הנתון:

@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. קטע הקוד הבא מציג את ה-composable של FeaturedCarousel מעל כל ה-composables של 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)
    }
  }
}