電視應用程式的瀏覽體驗取決於以焦點為基礎的有效導覽。 您可以使用標準 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) |