Jetpack Compose:打开键盘时滚动到屏幕底部

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

键盘打开后,我想将布局(不是 LazyColumn)滚动到最底部。键盘打开检测工作正常:

var parentSize by remember {
    mutableStateOf(Size.Zero)
}
val scrollState = rememberScrollState()

DisposableEffect(view) {
    scope.launch {
        scrollState.animateScrollTo(parentSize.height.toInt())
    }
    val listener = ViewTreeObserver.OnGlobalLayoutListener {
        val isKeyboardOpen = ViewCompat.getRootWindowInsets(view)
            ?.isVisible(WindowInsetsCompat.Type.ime()) ?: true
        if (isKeyboardOpen) {
            scope.launch {
                scrollState.animateScrollTo(parentSize.height.toInt())
            }
        }
    }

    view.viewTreeObserver.addOnGlobalLayoutListener(listener)
    onDispose {
        view.viewTreeObserver.removeOnGlobalLayoutListener(listener)
    }
}

OutlinedTextField(
    value = uiState.emailInput,
    onValueChange = { onEmailInputChanged(it) },
    label = { Text(text = stringResource(id = C.string.email)) },
    keyboardOptions = KeyboardOptions(
        keyboardType = KeyboardType.Email,
        imeAction = ImeAction.Next
    ),
    singleLine = true,
    modifier = Modifier
        .fillMaxWidth()
        .padding(horizontal = Dimen.medium)
        .onFocusChanged {
            scope.launch {
                scrollState.animateScrollTo(parentSize.height.toInt())
            }
        }
)
// the very bottom view
Button(
                onClick = { onLoginClicked() },
                modifier = Modifier
                    .wrapContentHeight(Alignment.Bottom)
                    .defaultMinSize(minHeight = Dimen.veryLarge)
                    .fillMaxWidth()
                    .onGloballyPositioned {
                        //here u can access the parent layout coordinate size
                        parentSize = it.parentLayoutCoordinates?.parentLayoutCoordinates?.size?.toSize()?: Size.Zero
                    }
                    .padding(start = Dimen.medium, end = Dimen.medium, bottom = Dimen.medium),
                enabled = !uiState.isLoading && uiState.inputCorrect,
            )

但是,无论我做什么,自动滚动都不起作用。我做错了什么?

android scroll android-jetpack-compose
2个回答
0
投票

您可以使用

scrollState.maxValue
。另外,如果可以的话,请将
animateScrollTo
替换为
scrollTo

最后你的代码如下:

scope.launch {
    scrollState.scrollTo(scrollState.maxValue)
}

0
投票

监听键盘打开的更好方法可能是使用

WindowInsetsAnimationCompat
而不是
ViewTreeObserver.OnGlobalLayoutListener
。它甚至为我解决了一个问题,即由于动画冲突,动画滚动到视图末尾不起作用。

我将逻辑提取到可重用函数中,以便在键盘打开动画完成后执行任意逻辑。也许这也可以进一步改进您的解决方案:

@Composable
fun ExecuteOnKeyboardOpen(callback: () -> Unit) {
    val view = LocalView.current
    DisposableEffect(view) {
        ViewCompat.setWindowInsetsAnimationCallback(
            view,
            object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_CONTINUE_ON_SUBTREE) {
                override fun onProgress(
                    insets: WindowInsetsCompat,
                    runningAnimations: MutableList<WindowInsetsAnimationCompat>
                ): WindowInsetsCompat = insets // mandatory override

                override fun onEnd(animation: WindowInsetsAnimationCompat) {
                    if (animation.typeMask and WindowInsetsCompat.Type.ime()
                        == WindowInsetsCompat.Type.ime()
                    ) {
                        val isKeyboardOpen = ViewCompat.getRootWindowInsets(view)
                            ?.isVisible(WindowInsetsCompat.Type.ime()) ?: true
                        if (isKeyboardOpen) {
                            callback()
                        }
                    }
                    super.onEnd(animation)
                }
            }
        )

        onDispose {
            ViewCompat.setWindowInsetsAnimationCallback(view, null)
        }
    }
}

要滚动到页面末尾,您可以像这样使用它:

ExecuteOnKeyboardOpen {
    scope.launch {
        scrollState.animateScrollTo(scrollState.maxValue)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.