在電視應用程式中,瀏覽體驗仰賴有效率的焦點導覽。使用標準 Compose Foundation 延遲版面配置,您可以建立高效能的垂直和水平清單,自動處理焦點驅動捲動,讓有效項目保持在檢視畫面中。
針對電視最佳化的預設捲動行為
從 Compose Foundation 1.7.0 開始,標準 Lazy 版面配置 (例如 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 中電視專用的 Lazy 版面配置已淘汰,改用標準 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) |