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

如何在Jetpack Compose中为OutlinedTextField应用onTextLayout?

解决OutlinedTextField适配键盘上方显示的问题

你之前的嵌套方式存在问题,同时渲染了两个文本输入组件会导致状态冲突,还无法正确触发视图滚动逻辑。正确的做法是基于BasicTextField构建带Outlined样式的输入框,利用官方提供的装饰组件实现Outlined视觉效果,同时保留BringIntoViewRequester的核心逻辑。

下面是修正后的代码:

@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
@Composable
fun CustomOutlinedTextField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    textStyle: TextStyle = TextStyle(),
    label: @Composable (() -> Unit)? = null,
    placeholder: @Composable (() -> Unit)? = null,
    supportingText: @Composable (() -> Unit)? = null,
    isError: Boolean = false,
    enabled: Boolean = true
) {
    val bringIntoViewRequester = remember { BringIntoViewRequester() }
    val coroutineScope = rememberCoroutineScope()

    var textFieldValue by remember { mutableStateOf(TextFieldValue(value)) }

    BasicTextField(
        value = textFieldValue,
        onValueChange = { newTextFieldValue ->
            textFieldValue = newTextFieldValue
            onValueChange(newTextFieldValue.text)
        },
        onTextLayout = { textLayoutResult ->
            val cursorRect = textLayoutResult.getCursorRect(textFieldValue.selection.start)
            coroutineScope.launch {
                bringIntoViewRequester.bringIntoView(cursorRect)
            }
        },
        textStyle = textStyle,
        enabled = enabled,
        modifier = modifier
            .bringIntoViewRequester(bringIntoViewRequester),
        decorationBox = @Composable { innerTextField ->
            TextFieldDefaults.outlinedTextFieldDecorationBox(
                value = textFieldValue.text,
                innerTextField = innerTextField,
                enabled = enabled,
                singleLine = false, // 根据需求设置是否单行
                isError = isError,
                label = label,
                placeholder = placeholder,
                supportingText = supportingText,
                interactionSource = remember { MutableInteractionSource() },
                contentPadding = TextFieldDefaults.outlinedTextFieldPadding()
            )
        }
    )
}

关键说明:

  • 直接用BasicTextField作为底层输入组件,保留onTextLayout和bringIntoViewRequester逻辑,确保光标位置变化时能触发视图滚动,让输入区域始终显示在键盘上方。
  • 通过TextFieldDefaults.outlinedTextFieldDecorationBox实现OutlinedTextField的完整样式(包括标签、占位符、错误提示等),这是官方推荐的自定义Material3文本框样式的标准方式。
  • 彻底避免嵌套OutlinedTextField,从根源上解决组件重复、状态冲突的问题。

补充提示:

  • 如果项目使用Material2,需要替换为对应版本的TextFieldDefaults.outlinedTextFieldDecorationBox,注意命名空间和参数差异。
  • 确保项目Compose版本支持用到的实验性API,可根据依赖情况调整注解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:22:19