调整需要进入视图的可组合项的大小时,BringIntoViewRequester 不起作用

问题描述 投票:0回答:6

过去几天我试图找到问题的解决方案,但

键盘与垂直滚动的文本输入字段重叠 专栏。

在尝试了很多事情之后,终于找到了一切正常的解决方案,除了我想在单击按钮时在输入字段下显示错误验证消息的情况。

在这种情况下,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)
android-jetpack-compose android-softkeyboard input-field
6个回答
2
投票

出于某种原因,在 BringIntoView() 之前添加一些延迟后,称它对我有用

.onFocusChanged { focusState ->
                if (focusState.isFocused) {
                    scope.launch {
                        delay(420)
                        bringIntoViewRequester.bringIntoView()
                    }
                }
            }

有趣,但 300 毫秒对于这个 hack 来说还不够:)也许这是因为键盘动画持续时间


1
投票

就我而言,您只需将滚动修饰符放在 imePadding 修饰符之后即可。我认为这是因为可用的滚动区域。

Modifier
        .fillMaxSize()
        .imePadding()
        .verticalScroll(state = scrollState)

0
投票

不小心添加了这个

implementation androidx.compose.foundation:foundation:1.4.3
在我删除此依赖项后,现在它可以工作了


0
投票

尝试使用decorationBox属性

BasicTextField(
    decorationBox = { innerTextField ->
                            //custom UI
                        Box(
                            modifier = Modifier
                                .fillMaxSize(),
                            contentAlignment = Alignment.CenterStart
                        ) {
                            //custom UI
                            innerTextField()
                        }
                            //custom UI
                    },
)

0
投票

在我的例子中(使用Scaffold),我使用了innerPadding.calculateTopPadding()、innerPadding.calculateBottomPadding()以及在verticalScroll修饰符之后。这就是我让它运作良好的方法

    content = { innerPadding ->
        Column(
            modifier = Modifier
                .padding(16.dp)
                .padding(
                     top = innerPadding.calculateTopPadding(), 
                     bottom = innerPadding.calculateBottomPadding()
                )
                .verticalScroll(rememberScrollState())
        ) {...

-2
投票

嗯,这就是您所需要的,而且效果很好:

@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

© www.soinside.com 2019 - 2024. All rights reserved.