I am trying to scroll my LazyColumn
to the last item automatically when the keyboard appears. However, the code below that is suggested in the other StackOverflow discussions works inconsistently as shown in the attached image, and rarely brings the last item into view.
@OptIn(ExperimentalLayoutApi::class)
@Preview(showBackground = true)
@Composable
fun ChatScreen() {
val viewModel: ChatScreenViewModel = viewModel()
val textFieldContent = viewModel.textFieldState
val messages = viewModel.messageListState
val listState = viewModel.messageListScrollState
val keyboardVisibility = WindowInsets.isImeVisible
LaunchedEffect(key1 = keyboardVisibility) {
listState.animateScrollToItem(listState.layoutInfo.totalItemsCount)
}
ChatbotAppTheme {
Column(
modifier = Modifier
.fillMaxSize()
.systemBarsPadding()
.imePadding()
) {
// LazyColumn to hold messages
LazyColumn(
modifier = Modifier
.weight(1f),
state = listState
) {
items(messages) {
MessageBubble(
text = it.body,
role = it.role
)
}
}
Row(
modifier = Modifier
.fillMaxWidth()
.background(Color.Transparent),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround
) {
CustomTextField(
modifier = Modifier.weight(1f),
text = textFieldContent.value,
onValueChangeFunc = {viewModel.onTextFieldContentChanged(it)},
trailingIconFunc = {viewModel.clearTextField()},
)
CustomButton (enabled = textFieldContent.value.isNotEmpty()) {
viewModel.onSendButtonPressed()
}
}
}
}
}
I have set the required android:windowSoftInputMode="adjustResize"
in the manifest and set enableEdgeToEdge()
in the MainActivity
to ensure that isImeVisible
is working correctly. However, I am unable to get the expected result. I would really appreciate any help or insight.
I managed to fix the problem by adding a fairly long delay before executing the scroll. Note that a short delay (e.g., 50ms) does not fix the issue.
@Composable
fun ChatScreen() {
//...
val keyboardVisibility = WindowInsets.isImeVisible
LaunchedEffect(key1 = keyboardVisibility) {
if (keyboardVisibility == true){
delay(300)
viewModel.scrollToLastItem()
}
}
//...
}
class ChatScreenViewModel(): ViewModel() {
//...
val messageListScrollState = LazyListState()
fun scrollToLastItem(){
viewModelScope.launch {
messageListScrollState.scrollToItem(index = messageListScrollState.layoutInfo.totalItemsCount)
}
}
//...
}