Jetpack Compose中BasicTextField粘贴框位置异常修复求助
问题:Jetpack Compose 1.4.2中BasicTextField粘贴框位置异常修复
我在Jetpack Compose 1.4.2中实现了一个自定义BasicTextField,粘贴复制的文本时,粘贴框出现在左上角异常位置,求修复方法。
更新:附上CustomTextField实现代码:
@Composable fun CustomTextField( value: String, placeholder: String, enabled: Boolean = true, loading: Boolean = false, keyboardType: KeyboardType, update: ((String) -> Unit)? = null ) { var focus by remember { mutableStateOf(false) } BasicTextField( value = value, onValueChange = { new -> update?.let { it(new) } }, cursorBrush = SolidColor(Blue), textStyle = MaterialTheme.typography.bodyMedium, decorationBox = { inner -> Box( modifier = Modifier .fillMaxWidth() .padding( start = 16.dp, end = 16.dp ), contentAlignment = Alignment.CenterStart ) { if (value.isEmpty()) { Text( text = placeholder, style = MaterialTheme.typography.bodyMedium, color = Blue_2 ) } else { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier .fillMaxWidth() ) { inner() if (loading) { Box( modifier = Modifier .padding(vertical = 24.dp, horizontal = 16.dp) .size(16.dp) ) { CircularProgressIndicator( color = Blue_6 ) } } } } } }, visualTransformation = if (keyboardType == KeyboardType.Password) PasswordVisualTransformation() else VisualTransformation.None, keyboardOptions = KeyboardOptions( keyboardType = keyboardType ), enabled = enabled, modifier = Modifier .fillMaxWidth() .shadow( elevation = if (focus) 15.dp else 7.5.dp, shape = RoundedCornerShape(16.dp), clip = false, ambientColor = Blue_6, spotColor = Blue_6 ) .background( if (focus) Focused else Not_Focused, RoundedCornerShape(16.dp) ) .height(60.dp) .onFocusChanged { focus = it.hasFocus }, singleLine = true ) }
问题截图:
解决方案
粘贴框位置异常的核心原因是自定义decorationBox时,没有保持输入区域(inner())布局的稳定性,导致系统无法正确计算粘贴菜单的定位基准。修复步骤如下:
- 不要根据
value是否为空切换输入区域的容器结构,让inner()始终作为输入载体存在,placeholder和加载指示器直接叠加在其上方。 - 确保布局约束(如padding、高度)直接传递给
inner()所在的容器,维持输入区域的布局树稳定。
修改后的decorationBox代码示例:
decorationBox = { inner -> Box( modifier = Modifier .fillMaxWidth() .padding(start = 16.dp, end = 16.dp) .height(60.dp), contentAlignment = Alignment.CenterStart ) { // 始终渲染inner,保证输入区域布局稳定 inner() // placeholder叠加在输入区域上方,仅value为空时显示 if (value.isEmpty()) { Text( text = placeholder, style = MaterialTheme.typography.bodyMedium, color = Blue_2 ) } // 加载指示器通过align定位到右侧 if (loading) { Box( modifier = Modifier .align(Alignment.CenterEnd) .padding(horizontal = 16.dp) .size(16.dp) ) { CircularProgressIndicator(color = Blue_6) } } } }
额外说明:
- 原代码中切换容器的逻辑会导致输入区域的布局频繁重组,不仅引发粘贴菜单位置异常,还会增加不必要的性能开销。
- 保持
inner()的布局稳定性后,系统能基于输入区域的正确约束计算光标和粘贴菜单的位置,解决异常问题。
内容的提问来源于stack exchange,提问作者Lukas
相关产品推荐
相关产品推荐

