键盘打开后,我想将布局(不是 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,
)
但是,无论我做什么,自动滚动都不起作用。我做错了什么?
您可以使用
scrollState.maxValue
。另外,如果可以的话,请将 animateScrollTo
替换为 scrollTo
。
最后你的代码如下:
scope.launch {
scrollState.scrollTo(scrollState.maxValue)
}
监听键盘打开的更好方法可能是使用
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)
}
}