Jetpack Compose TV端:修改LazyRow滚动行为实现焦点固定
Jetpack Compose TV实现固定焦点位置的LazyRow滚动
要实现类似Google TV启动器的固定焦点滚动效果(焦点项固定在屏幕左侧,列表围绕其滚动),可以通过监听焦点变化并主动控制LazyRow的滚动位置来实现,具体方案如下:
核心思路
当列表项获得焦点时,触发LazyRow滚动到该item,并将其对齐到屏幕左侧,替代默认的"边缘触发滚动"行为。
实现代码
@Composable fun FixedFocusLazyRow(itemsList: List<String>) { // 控制LazyRow滚动状态 val lazyListState = rememberLazyListState() // 存储每个item的焦点请求器,用于初始焦点设置 val focusRequesters = remember { itemsList.map { FocusRequester() } } // 初始加载时让第一个item获得焦点并对齐左侧 LaunchedEffect(Unit) { focusRequesters.firstOrNull()?.requestFocus() } LazyRow( state = lazyListState, contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp) ) { itemsIndexed(itemsList) { index, item -> val isFocused = remember { mutableStateOf(false) } Box( modifier = Modifier .focusRequester(focusRequesters[index]) // 监听焦点变化,触发滚动 .onFocusChanged { isFocused.value = it.isFocused if (it.isFocused) { LaunchedEffect(lazyListState, index) { // 滚动到当前焦点项,对齐到屏幕左侧 lazyListState.animateScrollToItem( index = index, alignment = Alignment.Start ) } } } .focusable() .size(220.dp, 140.dp) .background(if (isFocused.value) Color(0xFF4285F4) else Color(0xFF333333)) .padding(16.dp) ) { Text( text = item, color = Color.White, fontSize = 18.sp, modifier = Modifier.align(Alignment.Center) ) } } } }
关键细节说明
- 准确获取索引:使用
itemsIndexed遍历列表,直接拿到item的索引,避免重复项导致的定位错误。 - 平滑滚动控制:
animateScrollToItem提供流畅的滚动过渡,若需要即时滚动可替换为scrollToItem。 - 初始焦点对齐:通过
LaunchedEffect在页面加载时主动请求第一个item的焦点,确保初始状态符合预期。 - 边距调整:
contentPadding用于控制列表左右边距,保证焦点项完全显示在屏幕左侧区域。
内容的提问来源于stack exchange,提问作者Rahul Rawat
相关产品推荐
相关产品推荐

