สร้างเบราว์เซอร์แคตตาล็อก

แอปสื่อที่ทำงานบนทีวีต้องอนุญาตให้ผู้ใช้เรียกดูข้อเสนอเนื้อหา เลือก และเริ่มเล่นเนื้อหา ประสบการณ์การเรียกดูเนื้อหาสำหรับแอปประเภทนี้ควรเรียบง่าย ใช้งานง่าย ดึงดูดสายตา และน่าสนใจ

เครื่องมือเลือกแคตตาล็อกสื่อมักจะประกอบด้วยหลายส่วน และแต่ละส่วนจะมีรายการเนื้อหาสื่อ ตัวอย่างส่วนต่างๆ ในแคตตาล็อกสื่อ ได้แก่ เพลย์ลิสต์ เนื้อหาแนะนำ หมวดหมู่แนะนำ

รูปที่ 1 หน้าจอแคตตาล็อกทั่วไป ผู้ใช้เรียกดูข้อมูลแคตตาล็อกวิดีโอได้

ใช้ฟังก์ชันที่ Compose for TV มีให้เพื่อติดตั้งใช้งานอินเทอร์เฟซผู้ใช้สำหรับการเรียกดูเพลงหรือวิดีโอจากแคตตาล็อกสื่อของแอป

สร้างฟังก์ชันที่ประกอบกันได้สําหรับแคตตาล็อก

ทุกอย่างที่ปรากฏบนจอแสดงผลจะใช้เป็นฟังก์ชันคอมโพสิเบิลใน Compose สำหรับทีวี เริ่มต้นด้วยการกำหนดฟังก์ชันที่คอมโพสิเบิลสําหรับเบราว์เซอร์แคตตาล็อกสื่อ

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

CatalogBrowser คือฟังก์ชันที่ประกอบกันได้ซึ่งใช้แคตตาล็อกสื่อของคุณในเบราว์เซอร์ ฟังก์ชันนี้ใช้อาร์กิวเมนต์ต่อไปนี้

  • รายการเนื้อหาเด่น
  • รายชื่อส่วน
  • ออบเจ็กต์ตัวแก้ไข
  • ฟังก์ชัน Callback ซึ่งจะทริกเกอร์การเปลี่ยนหน้าจอ

ตั้งค่าองค์ประกอบ UI

คอมโพสิชันสำหรับทีวีมีรายการแบบ Lazy ซึ่งแสดงรายการจำนวนมาก (หรือรายการที่มีความยาวที่ไม่รู้จัก) เรียกใช้ 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 ข้อความและคอมโพเนนต์อื่นๆ ที่กําหนดไว้ใน Material Design มีอยู่ในคลัง tv-material คุณสามารถเปลี่ยนสไตล์ข้อความตามที่ระบุไว้ใน Material Design ได้โดยอ้างอิงถึงออบเจ็กต์ 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,
     )
   }
}

ในตัวอย่างที่อธิบายก่อนหน้านี้ ภาพยนตร์ทั้งหมดจะแสดงเท่าๆ กัน พื้นที่ของทั้ง 2 รายการเหมือนกัน ไม่มีความแตกต่างที่มองเห็นได้ คุณสามารถไฮไลต์รายการที่ต้องการได้โดยใช้ Carousel

ภาพสไลด์จะแสดงข้อมูลในชุดรายการที่เลื่อน เลือน หรือย้ายเข้ามาในมุมมองได้ คุณใช้คอมโพเนนต์นี้เพื่อไฮไลต์เนื้อหาแนะนำ เช่น ภาพยนตร์ที่เพิ่งมีให้รับชมหรือตอนใหม่ของรายการทีวี

Carousel คาดหวังให้คุณระบุจำนวนรายการที่ภาพสไลด์มีและวิธีวาดแต่ละรายการเป็นอย่างน้อย คุณสามารถระบุรายการแรกด้วย itemCount ส่วนรายการที่ 2 จะส่งเป็น 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 อาจเป็นรายการของรายการแบบเลื่อนออก เช่น 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)
    }
  }
}