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

Jetpack Compose:LazyColumn中TextField聚焦隐藏项导致失焦问题

解决LazyColumn中TextField焦点丢失问题

问题根源:当你修改addFirstItem触发LazyColumn重组时,TextField所在的item会被重新创建——因为LazyColumn会根据内容结构的变化生成新的子组件实例,原来的TextField被销毁,自然就丢失了焦点。

下面是针对不同场景的解决方案:

方案一:给Item添加稳定Key(推荐用于大量项场景)

给每个LazyColumn的item指定唯一且稳定的key,让Compose识别到这是同一个组件,重组时复用原有实例而非重建,从而保留焦点。同时配合FocusRequester做双重保险,确保状态变化后焦点不丢失:

var addFirstItem by remember { mutableStateOf(true) }
val focusRequester = remember { FocusRequester() }

LazyColumn {
    if (addFirstItem) {
        item(key = "first-item") {
            Text(
                text = "First item",
                Modifier
                    .background(Color.Red)
                    .height(100.dp)
            )
        }
    }

    item(key = "text-field-item") {
        TextField(
            value = "Second Item",
            onValueChange = {},
            modifier = Modifier
                .background(Color.Blue)
                .height(100.dp)
                .focusRequester(focusRequester)
                .onFocusChanged { focusState ->
                    if (focusState.isFocused) {
                        addFirstItem = false
                        // 主动请求焦点,避免重组后焦点丢失
                        LaunchedEffect(Unit) {
                            focusRequester.requestFocus()
                        }
                    } else {
                        addFirstItem = true
                    }
                }
        )
    }
}

这个方案的优势在于,当addFirstItem为false时,第一个item会被完全移除,LazyColumn不会加载它,适合大量项的场景,不会造成不必要的性能消耗。

方案二:用Modifier控制Item可见性(适合需保留组件实例的场景)

如果不想完全卸载第一个item(比如恢复显示时不想重新初始化),可以通过修改height和alpha来隐藏它,组件实例会被保留,但内容不会被加载:

var addFirstItem by remember { mutableStateOf(true) }
val focusRequester = remember { FocusRequester() }

LazyColumn {
    item(key = "first-item") {
        Text(
            text = "First item",
            Modifier
                .background(Color.Red)
                .height(if (addFirstItem) 100.dp else 0.dp)
                .alpha(if (addFirstItem) 1f else 0f)
        )
    }

    item(key = "text-field-item") {
        TextField(
            value = "Second Item",
            onValueChange = {},
            modifier = Modifier
                .background(Color.Blue)
                .height(100.dp)
                .focusRequester(focusRequester)
                .onFocusChanged { focusState ->
                    if (focusState.isFocused) {
                        addFirstItem = false
                    } else {
                        addFirstItem = true
                    }
                }
        )
    }
}

不过这种方式下第一个item的组件实例仍存在,对于大量项的场景,还是推荐方案一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 14:45:08