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

Jetpack Compose中LazyColumn不可见item如何获取焦点并触发滚动?

问题解决方案

问题根因

LazyColumn 仅会加载可视区域附近的子项,子项滚出可视区域后会被回收销毁。你当前的实现逻辑是等子项获取焦点后再触发滚动,但已经被回收的子项无法接收焦点事件,onFocused 回调永远不会触发,自然无法将对应子项重新滚动到可视区域,陷入逻辑死循环。

修复方案

使用 Compose 原生提供的 bringIntoViewRequester 修饰符自动处理焦点项滚入可视区的逻辑,无需手动调用 scrollToItem,代码改动最小且兼容性更好。

修改后完整代码

import androidx.compose.foundation.relocation.BringIntoViewRequester
import androidx.compose.foundation.relocation.bringIntoViewRequester

@Composable
fun ScrollableList(modifier: Modifier = Modifier) {
    val scrollState = rememberLazyListState()
    LazyColumn(
        state = scrollState,
        modifier = Modifier.padding(5.dp),
        verticalArrangement = Arrangement.spacedBy(5.dp)
    ) {
        itemsIndexed(items = (0..10).toList()) { index, item ->
            FocusableBox(
                title = "ScrollBox-$index"
            )
        }
    }
}

@Composable
fun FocusableBox(
    title: String,
    onFocused: (Boolean) -> Unit = {},
    requester: FocusRequester = FocusRequester(),
    modifier: Modifier = Modifier
) {
    // 新增 BringIntoViewRequester
    val bringIntoViewRequester = remember { BringIntoViewRequester() }
    val scope = rememberCoroutineScope()
    var boxColor by remember { mutableStateOf(Color.White) }
    var focused by remember { mutableStateOf(false) }
    Box(
        Modifier
            .bringIntoViewRequester(bringIntoViewRequester) // 注意顺序:要放在focus相关修饰符前面
            .focusRequester(requester)
            .onFocusChanged {
                boxColor = if (it.isFocused) Color.Green else Color.Gray
                focused = it.isFocused
                onFocused(it.isFocused)
                // 拿到焦点时请求将当前项滚入可视区域
                if (it.isFocused) {
                    scope.launch {
                        bringIntoViewRequester.bringIntoView()
                    }
                }
            }
            .focusable()
            .background(boxColor)
            .zIndex(if (focused) 1f else 0f)
    ) {
        Text(
            text = title,
            modifier = Modifier.padding(30.dp),
            color = Color.White,
            style = MaterialTheme.typography.subtitle2
        )
    }
}

注意事项

  • 修饰符顺序不能调换,bringIntoViewRequester 必须放在 onFocusChanged、focusable 等焦点相关修饰符之前
  • 原生逻辑会自动适配滚动位置,避免滚动越界等异常问题,自带平滑滚动效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 06:57:03