如何使用方向键更快地滚动 LazyRow?

问题描述 投票:0回答:1

我正在尝试使用 Compose 在 Android TV 上实现轮播组件,但我在使用方向键快速滚动时遇到了问题。注意:我想将焦点项目保留为屏幕上第一个显示的项目。

这里是屏幕截图:

通过在每个项目之后按下并释放右键来滚动前 5 个项目。接下来的 15 个项目通过按住右键滚动到列表的末尾。

滚动和焦点管理效果很好,但我想让它更快。在屏幕截图上,您会看到当按下右键时,列表会滚动 然后 下一个项目获得焦点。真的很慢

这是可组合函数:

@Composable
private fun CustomLazyRow() {
    val scrollState = rememberLazyListState()

    LazyRow(
        state = scrollState,
        horizontalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        itemsIndexed(
            items = (1..20).toList()
        ) { index, item ->
            var isFocused by remember { mutableStateOf(false) }
            Text(
                text = "Item $item",
                modifier = Modifier
                    .dpadNavigation(scrollState, index)
                    .width(156.dp)
                    .aspectRatio(4 / 3F)
                    .onFocusChanged { isFocused = it.isFocused }
                    .focusable()
                    .border(if (isFocused) 4.dp else Dp.Hairline, Color.Black)
            )
        }
    }
}

dpadNavigation
修饰符函数:

fun Modifier.dpadNavigation(
    scrollState: LazyListState,
    index: Int
) = composed {
    val focusManager = LocalFocusManager.current
    var focusDirectionToMove by remember { mutableStateOf<FocusDirection?>(null) }
    val scope = rememberCoroutineScope()

    onKeyEvent {
        if (it.type == KeyEventType.KeyDown) {
            when (it.nativeKeyEvent.keyCode) {
                KeyEvent.KEYCODE_DPAD_LEFT -> focusDirectionToMove = FocusDirection.Left
                KeyEvent.KEYCODE_DPAD_RIGHT -> focusDirectionToMove = FocusDirection.Right
            }
            if (focusDirectionToMove != null) {
                scope.launch {
                    if (focusDirectionToMove == FocusDirection.Left && index > 0) {
                        // This does not work:
                        // scope.launch { scrollState.animateScrollToItem(index - 1) }
                        scrollState.animateScrollToItem(index - 1)
                        focusManager.moveFocus(FocusDirection.Left)
                    }
                    if (focusDirectionToMove == FocusDirection.Right) {
                        // scope.launch { scrollState.animateScrollToItem(index + 1) }
                        scrollState.animateScrollToItem(index + 1)
                        focusManager.moveFocus(FocusDirection.Right)
                    }
                }
            }
        }
        true
    }
}

我以为是

animateScrollToItem
函数在执行
moveFocus
之前必须完成。

所以我尝试在它自己的

animateScrollToItem
块中执行
launch
但是它没有用;在这种情况下根本没有滚动。

您可以在 https://github.com/geekarist/perf-carousel 的 repo 中查看完整的源代码

android android-jetpack-compose android-tv android-jetpack-compose-tv
1个回答
0
投票

Google 正在努力使 Jetpack compose 与电视兼容。结帐Android TV Compose 发布.

要回答您的问题,您可以使用 TvLazyRow 可组合项来构建与电视兼容的惰性行。为了保持焦点在同一位置,您可以使用

pivotOffset
(PivotOffset) param TvLazyRow 将行内的项目定位在固定位置。

© www.soinside.com 2019 - 2024. All rights reserved.