電視應用程式的瀏覽體驗取決於以焦點為基礎的有效導覽。 使用標準 Compose Foundation 延遲版面配置,即可建立高效能的直向和橫向清單,自動處理焦點驅動的捲動,讓有效項目保持在檢視畫面中。
針對電視最佳化的預設捲動行為
從 Compose Foundation 1.7.0 開始,標準延遲版面配置 (例如 LazyRow 和 LazyColumn) 內建支援焦點定位功能。建議您使用這種方式為電視應用程式建立目錄,因為這樣可確保焦點項目保持可見,並以直覺式方式呈現給使用者。
如要導入基本可捲動清單,請使用標準延遲元件。這些元件會自動處理 D-pad 導覽,並將焦點項目帶入檢視畫面。
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
@Composable
fun MovieCatalog(movies: List<Movie>) {
LazyRow {
items(movies) { movie ->
MovieCard(
movie = movie,
onClick = { /* Handle click */ }
)
}
}
}
使用 BringIntoViewSpec 自訂捲動行為
如果設計需要特定「軸心」點 (例如,將焦點項目與左側邊緣的距離維持在 30%),您可以使用 BringIntoViewSpec 自訂捲動行為。這項功能取代了舊版 pivotOffsets 功能,可讓您準確定義可視區域應如何捲動,以容納焦點項目。
1. 定義自訂 BringIntoViewSpec
您可以使用下列輔助組合函式,根據父項和子項的分數定義「樞紐」。parentFraction 會決定項目在容器中的放置位置,childFraction 則會決定項目的哪個部分要與該點對齊。
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun PositionFocusedItemInLazyLayout(
parentFraction: Float = 0.3f,
childFraction: Float = 0f,
content: @Composable () -> Unit,
) {
val bringIntoViewSpec = remember(parentFraction, childFraction) {
object : BringIntoViewSpec {
override fun calculateScrollDistance(
offset: Float, // Item's initial position
size: Float, // Item's size
containerSize: Float // Container's size
): Float {
// Calculate the offset position of the item's leading edge.
val initialTargetForLeadingEdge =
parentFraction * containerSize - (childFraction * size)
// If the item fits in the container, and scrolling would cause
// its trailing edge to be clipped, adjust targetForLeadingEdge
// to prevent over-scrolling near the end of list.
val targetForLeadingEdge = if (size <= containerSize &&
(containerSize - initialTargetForLeadingEdge) < size) {
// If clipped, align the item's trailing edge with the
// container's trailing edge.
containerSize - size
} else {
initialTargetForLeadingEdge
}
// Return scroll distance relative to initial item position.
return offset - targetForLeadingEdge
}
}
}
// Apply the spec to all scrollables in the hierarchy
CompositionLocalProvider(
LocalBringIntoViewSpec provides bringIntoViewSpec,
content = content,
)
}
2. 套用自訂規格
使用輔助程式包裝版面配置,套用定位。這項功能有助於在目錄的不同列中建立「一致的焦點線」。
PositionFocusedItemInLazyLayout(
parentFraction = 0.3f, // Pivot 30% from the edge
childFraction = 0.5f // Center of the item aligns with the pivot
) {
LazyColumn {
items(sectionList) { section ->
// This row and its items will respect the 30% pivot
LazyRow { ... }
}
}
}
3. 選擇不使用特定巢狀版面配置
如果您有應使用標準捲動行為而非自訂樞紐的特定巢狀配置,請提供 DefaultBringIntoViewSpec:
private val DefaultBringIntoViewSpec = object : BringIntoViewSpec {}
PositionFocusedItemInLazyLayout {
LazyColumn {
item {
// This row will ignore the custom pivot and use default behavior
CompositionLocalProvider(LocalBringIntoViewSpec provides DefaultBringIntoViewSpec) {
LazyRow { ... }
}
}
}
}
實際上,傳遞空白 BringIntoViewSpec 會啟用架構的預設行為。
從 TV Foundation 遷移至 Compose Foundation
androidx.tv.foundation 中的電視專用延遲版面配置已淘汰,建議改用標準的 Compose Foundation 版面配置。
依附元件更新
確認 build.gradle 使用 1.7.0 以上版本:
androidx.compose.foundationandroidx.compose.runtime
元件對應
如要遷移,請更新匯入內容,並從元件中移除 Tv 前置字元:
| 已淘汰的電視元件 | Compose Foundation 替代項目 |
|---|---|
| TvLazyRow | LazyRow |
| TvLazyColumn | LazyColumn |
| TvLazyHorizontalGrid | LazyHorizontalGrid |
| TvLazyVerticalGrid | LazyVerticalGrid |
| pivotOffsets | BringIntoViewSpec (透過 LocalBringIntoViewSpec) |