You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现TvLazyRow标题与项目枢轴偏移量精准匹配?

解决TvLazyRow标题与高亮项起始对齐的问题

要实现类似PrimeVideo的标题与高亮项左对齐效果,不能依赖固定内边距(适配性差),核心思路是动态监听焦点项位置,让列表滚动时自动将高亮项左边缘与标题左边缘对齐,以下是具体实现方案:

方案1:利用TvLazyListState动态滚动对齐

通过监听焦点项的索引变化,自动滚动列表使高亮项的左边缘与列表左边界对齐,同时让标题和列表使用相同的左内边距,即可实现标题与高亮项的起始对齐:

@Composable
fun AlignedTvRow(title: String, itemList: List<YourItemType>) {
    val lazyListState = rememberTvLazyListState()
    val paddingStart = 16.dp // 标题和列表统一的左内边距

    // 焦点切换时自动滚动对齐
    LaunchedEffect(lazyListState.focusedItemIndex) {
        val targetIndex = lazyListState.focusedItemIndex
        if (targetIndex != -1) {
            // 获取当前焦点项相对于列表起始位置的偏移量
            val itemOffset = lazyListState.layoutInfo.visibleItemsInfo
                .find { it.index == targetIndex }
                ?.offset ?: 0
            
            // 滚动到目标项,抵消偏移量使其左边缘与列表左边界对齐
            lazyListState.animateScrollToItem(
                index = targetIndex,
                scrollOffset = -itemOffset
            )
        }
    }

    Column(modifier = Modifier.fillMaxWidth()) {
        // 标题使用统一的左内边距
        Text(
            text = title,
            modifier = Modifier.padding(start = paddingStart, bottom = 8.dp),
            style = MaterialTheme.typography.headlineSmall
        )

        TvLazyRow(
            state = lazyListState,
            contentPadding = PaddingValues(start = paddingStart, end = paddingStart)
        ) {
            items(itemList) { item ->
                // 你的列表项布局,比如卡片
                YourItemCard(item = item)
            }
        }
    }
}

方案2:动态调整标题偏移(备选)

如果需要保持列表原有滚动逻辑,也可以通过监听焦点项的偏移量,动态调整标题的X轴偏移,使其始终与高亮项左边缘对齐:

@Composable
fun OffsetAlignedTvRow(title: String, itemList: List<YourItemType>) {
    val lazyListState = rememberTvLazyListState()
    val titleOffsetX = remember { mutableStateOf(0.dp) }
    val listPaddingStart = 16.dp

    LaunchedEffect(lazyListState.focusedItemIndex) {
        lazyListState.layoutInfo.visibleItemsInfo
            .find { it.index == lazyListState.focusedItemIndex }
            ?.let { itemInfo ->
                // 计算标题需要偏移的距离,抵消焦点项的滚动偏移
                titleOffsetX.value = (-itemInfo.offset).dp
            }
    }

    Column(modifier = Modifier.fillMaxWidth()) {
        Text(
            text = title,
            modifier = Modifier
                .padding(start = listPaddingStart, bottom = 8.dp)
                .offset(x = titleOffsetX.value),
            style = MaterialTheme.typography.headlineSmall
        )

        TvLazyRow(
            state = lazyListState,
            contentPadding = PaddingValues(start = listPaddingStart, end = listPaddingStart)
        ) {
            items(itemList) { item ->
                YourItemCard(item = item)
            }
        }
    }
}

关键说明

  • 两种方案均基于TvLazyListState的焦点状态动态计算,完全适配不同屏幕尺寸、不同item宽度的场景,避免了固定内边距的适配问题。
  • 方案1是更贴近PrimeVideo的实现逻辑,通过列表滚动让高亮项对齐标题;方案2适合需要保留列表自由滚动的场景,通过标题偏移实现对齐。

内容的提问来源于stack exchange,提问作者Bharat Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 02:59:57