过去几天我试图找到问题的解决方案,但
键盘与垂直滚动的文本输入字段重叠 专栏。
在尝试了很多事情之后,终于找到了一切正常的解决方案,除了我想在单击按钮时在输入字段下显示错误验证消息的情况。
在这种情况下,bringIntoViewRequester.bringIntoView() 停止工作,并且 onFocusEvent 被循环触发。
这是代码:
@Composable
fun MainScreen() {
Column(
Modifier
.fillMaxSize()
.verticalScroll(state = scrollState)
.imePadding()
.navigationBarsPadding()
) {
InputField()
InputField()
InputField()
....
}
}
@Composable
fun InputField() {
val bringIntoViewRequester = remember { BringIntoViewRequester() }
val coroutineScope = rememberCoroutineScope()
val focusLocalManager = LocalFocusManager.current
val view = LocalView.current
val context = LocalContext.current
WindowInsets.ime
LaunchedEffect(Unit) {
ViewCompat.setWindowInsetsAnimationCallback(view, null)
}
Column(
modifier = Modifier
.wrapContentHeight()
.bringIntoViewRequester(bringIntoViewRequester)
) {
BasicTextField(
modifier = Modifier
.onFocusEvent { fs ->
if (fs.isFocused) {
coroutineScope.launch {
bringIntoViewRequester.bringIntoView()
}
}
}
.....
)
if (errorMessage.isNotEmpty())
Text(
text = errorMessage,
fontSize = 16.sp,
color = MaterialTheme.colors.error
)
}
}
我还在 AndroidManifest.xml
中设置了属性android:windowSoftInputMode="adjustResize"
并在MainActivity中:
WindowCompat.setDecorFitsSystemWindows(window, false)
出于某种原因,在 BringIntoView() 之前添加一些延迟后,称它对我有用
.onFocusChanged { focusState ->
if (focusState.isFocused) {
scope.launch {
delay(420)
bringIntoViewRequester.bringIntoView()
}
}
}
有趣,但 300 毫秒对于这个 hack 来说还不够:)也许这是因为键盘动画持续时间
就我而言,您只需将滚动修饰符放在 imePadding 修饰符之后即可。我认为这是因为可用的滚动区域。
Modifier
.fillMaxSize()
.imePadding()
.verticalScroll(state = scrollState)
不小心添加了这个
implementation androidx.compose.foundation:foundation:1.4.3
在我删除此依赖项后,现在它可以工作了
尝试使用decorationBox属性
BasicTextField(
decorationBox = { innerTextField ->
//custom UI
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.CenterStart
) {
//custom UI
innerTextField()
}
//custom UI
},
)
在我的例子中(使用Scaffold),我使用了innerPadding.calculateTopPadding()、innerPadding.calculateBottomPadding()以及在verticalScroll修饰符之后。这就是我让它运作良好的方法
content = { innerPadding ->
Column(
modifier = Modifier
.padding(16.dp)
.padding(
top = innerPadding.calculateTopPadding(),
bottom = innerPadding.calculateBottomPadding()
)
.verticalScroll(rememberScrollState())
) {...
嗯,这就是您所需要的,而且效果很好:
@ExperimentalMaterial3Api
@ExperimentalFoundationApi
@Composable
fun OutlinedTextFieldValidation(
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
readOnly: Boolean = false,
textStyle: TextStyle = LocalTextStyle.current,
label: @Composable (() -> Unit)? = null,
placeholder: @Composable (() -> Unit)? = null,
leadingIcon: @Composable (() -> Unit)? = null,
error: String? = null,
isError: Boolean = error?.isNotEmpty() ?: false,
trailingIcon: @Composable (() -> Unit)? = {
if (error?.isNotEmpty() == true)
Icon(Icons.Filled.Warning, "error", tint = MaterialTheme.colorScheme.error)
},
visualTransformation: VisualTransformation = VisualTransformation.None,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions.Default,
singleLine: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = MaterialTheme.shapes.small,
colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors(
disabledTextColor = Color.Black
),
) {
Column(
modifier = modifier.imePadding(), // <-- this will save your life
) {
OutlinedTextField(
enabled = enabled,
readOnly = readOnly,
value = value,
onValueChange = onValueChange,
modifier = modifier.fillMaxWidth(),
singleLine = singleLine,
textStyle = textStyle,
label = label,
placeholder = placeholder,
leadingIcon = leadingIcon,
trailingIcon = trailingIcon,
isError = isError,
visualTransformation = visualTransformation,
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
maxLines = maxLines,
interactionSource = interactionSource,
shape = shape,
colors = colors,
)
if (error?.isNotEmpty() == true) {
Text(
text = error,
color = MaterialTheme.colorScheme.error,
style = MaterialTheme.typography.labelSmall,
modifier = Modifier.padding(start = 16.dp, top = 0.dp),
)
}
}
}
特别感谢Rafa