Anonymous
Android Compose ScrollView не прокручивается вниз при появлении клавиатуры?
Сообщение
Anonymous » 04 дек 2025, 08:47
Я работаю над экраном входа в систему с помощью Jetpack Compose и пытаюсь реализовать автоматическую прокрутку, чтобы последняя кнопка («Войти без пароля») была видна при появлении клавиатуры.
Я использую Scaffold со столбцом, содержащим мои поля ввода и кнопки, заключенные в Modifier.verticalScroll(scrollState). Я использую собственный метод RememberImeState() для определения активности клавиатуры, а затем вызываю метод ScrollState.animateScrollTo(scrollState.maxValue) в LaunchedEffect.
Код ImeState:
Код: Выделить всё
@Composable
fun rememberImeState(): State {
val imeState = remember {
mutableStateOf(false)
}
val view = LocalView.current
DisposableEffect(view) {
val listener = ViewTreeObserver.OnGlobalLayoutListener {
val isKeyboardOpen = ViewCompat.getRootWindowInsets(view)
?.isVisible(WindowInsetsCompat.Type.ime()) ?: true
imeState.value = isKeyboardOpen
}
view.viewTreeObserver.addOnGlobalLayoutListener(listener)
onDispose {
view.viewTreeObserver.removeOnGlobalLayoutListener(listener)
}
}
return imeState
}
Страница входа
Код: Выделить всё
@Composable
fun Login() {
val imeState = rememberImeState()
val scrollState = rememberScrollState()
LaunchedEffect(key1 = imeState.value) {
if (imeState.value) {
scrollState.animateScrollTo(scrollState.maxValue, tween(300))
}
}
var email by remember {
mutableStateOf("")
}
var password by remember {
mutableStateOf("")
}
Scaffold(
topBar = {
// Top app bar with a back button and header text
TopAppBar(
title = {Text("Login")},
navigationIcon = {
IconButton(
onClick = {},
content = {
Icon(imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = null)
}
)
}
)
},
) { innerPadding ->
Column(
modifier = Modifier
.verticalScroll(scrollState)
.fillMaxSize()
.padding(innerPadding)
.padding(16.dp)
.focusable(),
verticalArrangement = Arrangement.Top,
horizontalAlignment = CenterHorizontally
) {
Text(
modifier = Modifier.fillMaxWidth(),
text = "Email or Username",
style = MaterialTheme.typography.titleLarge,
textAlign = TextAlign.Start,
)
Spacer(modifier = Modifier.size(4.dp))
TextField(
value = email,
onValueChange = {
email = it
},
)
Spacer(modifier = Modifier.size(32.dp))
Text(
modifier = Modifier.fillMaxWidth(),
text = "Password",
style = MaterialTheme.typography.titleLarge,
textAlign = TextAlign.Start,
)
Spacer(modifier = Modifier.size(4.dp))
TextField(
value = password,
onValueChange = {
password = it
},
)
Spacer(modifier = Modifier.size(4.dp))
Text(
text = "errorMessage",
fontSize = 12.sp
)
Spacer(modifier = Modifier.height(25.dp))
Button(
modifier = Modifier.height(43.dp),
onClick = {},
content = {
Text("Login")
}
)
Spacer(modifier = Modifier.height(2.dp))
Button(modifier = Modifier.height(43.dp),
onClick = {},
content = {
Text("Log in without password")
}
)
}
}
}
Этот текущий результат
Подробнее здесь:
https://stackoverflow.com/questions/798 ... rd-appears
1764827267
Anonymous
Я работаю над экраном входа в систему с помощью Jetpack Compose и пытаюсь реализовать автоматическую прокрутку, чтобы последняя кнопка («Войти без пароля») была видна при появлении клавиатуры. Я использую Scaffold со столбцом, содержащим мои поля ввода и кнопки, заключенные в Modifier.verticalScroll(scrollState). Я использую собственный метод RememberImeState() для определения активности клавиатуры, а затем вызываю метод ScrollState.animateScrollTo(scrollState.maxValue) в LaunchedEffect. Код ImeState: [code]@Composable fun rememberImeState(): State { val imeState = remember { mutableStateOf(false) } val view = LocalView.current DisposableEffect(view) { val listener = ViewTreeObserver.OnGlobalLayoutListener { val isKeyboardOpen = ViewCompat.getRootWindowInsets(view) ?.isVisible(WindowInsetsCompat.Type.ime()) ?: true imeState.value = isKeyboardOpen } view.viewTreeObserver.addOnGlobalLayoutListener(listener) onDispose { view.viewTreeObserver.removeOnGlobalLayoutListener(listener) } } return imeState } [/code] Страница входа [code]@Composable fun Login() { val imeState = rememberImeState() val scrollState = rememberScrollState() LaunchedEffect(key1 = imeState.value) { if (imeState.value) { scrollState.animateScrollTo(scrollState.maxValue, tween(300)) } } var email by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } Scaffold( topBar = { // Top app bar with a back button and header text TopAppBar( title = {Text("Login")}, navigationIcon = { IconButton( onClick = {}, content = { Icon(imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null) } ) } ) }, ) { innerPadding -> Column( modifier = Modifier .verticalScroll(scrollState) .fillMaxSize() .padding(innerPadding) .padding(16.dp) .focusable(), verticalArrangement = Arrangement.Top, horizontalAlignment = CenterHorizontally ) { Text( modifier = Modifier.fillMaxWidth(), text = "Email or Username", style = MaterialTheme.typography.titleLarge, textAlign = TextAlign.Start, ) Spacer(modifier = Modifier.size(4.dp)) TextField( value = email, onValueChange = { email = it }, ) Spacer(modifier = Modifier.size(32.dp)) Text( modifier = Modifier.fillMaxWidth(), text = "Password", style = MaterialTheme.typography.titleLarge, textAlign = TextAlign.Start, ) Spacer(modifier = Modifier.size(4.dp)) TextField( value = password, onValueChange = { password = it }, ) Spacer(modifier = Modifier.size(4.dp)) Text( text = "errorMessage", fontSize = 12.sp ) Spacer(modifier = Modifier.height(25.dp)) Button( modifier = Modifier.height(43.dp), onClick = {}, content = { Text("Login") } ) Spacer(modifier = Modifier.height(2.dp)) Button(modifier = Modifier.height(43.dp), onClick = {}, content = { Text("Log in without password") } ) } } } [/code] Этот текущий результат [img]https://i.sstatic.net/820EF3ET.png[/img] Подробнее здесь: [url]https://stackoverflow.com/questions/79837083/android-compose-scrollview-not-scrolling-to-bottom-when-keyboard-appears[/url]