skip to Main Content

I am making a chatting app with android compose.

Usually, when you scroll freely within the chat window and press the text input window to bring up the keyboard, the chat at the bottom of the screen naturally moves up.

I tried to implement it naturally, but it didn’t work out well.

I tried using rememberLazyListState() to input scrollOffset using listState.scrollToItem or listState.animationScrollToItem, but it feels quite unnatural.

How can we implement natural LazyColumn scrolling?

[EDIT]
I think additional explanation is needed, so I’ll attach a photo.
enter image description here
Can you see the chat slightly overlapping the input window like that before the keyboard comes up?
enter image description here

Even when the keyboard comes up, can you see that the chat is still uploaded, overlapping with the input window?

This is how I want it. I want the last chat I was viewing to scroll on the screen even if the keyboard is raised or lowered.
The photo was taken from Telegram.

2

Answers


  1. Try to add Modifier.imePadding() When the keyboard appears, it will push the content up, including your LazyColumn.

    @Composable
    fun ChatScreen() {
        val listState = rememberLazyListState()
        val messages = remember { mutableStateListOf<String>() }
        var textFieldValue by remember { mutableStateOf("") }
        val keyboardController = LocalSoftwareKeyboardController.current
    
        // Add a dummy list of messages for demonstration
        LaunchedEffect(Unit) {
            repeat(50) { index ->
                messages.add("Message $index")
            }
        }
    
        // Scroll to the bottom of the list when the keyboard appears
        LaunchedEffect(keyboardController?.isVisible) {
            if (keyboardController?.isVisible == true) {
                listState.animateScrollToItem(messages.size - 1)
            }
        }
    
        Column(
            modifier = Modifier
                .fillMaxSize()
                .imePadding() // Adjust padding based on the IME
        ) {
            LazyColumn(
                state = listState,
                modifier = Modifier.weight(1f),
                reverseLayout = true // Start from the bottom
            ) {
                items(messages) { message ->
                    Text(
                        text = message,
                        modifier = Modifier.padding(8.dp)
                    )
                }
            }
    
            BasicTextField(
                value = textFieldValue,
                onValueChange = { textFieldValue = it },
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(8.dp)
            )
        }
    }
    
    
    Login or Signup to reply.
  2. For original setting of LazyColumn, when LazyColumn’s viewport size changed, Compose will try to conserve top messages visible on view.

    For some special cases like chat app, when LazyColumn’s viewport size changed and you want to make bottom messages visible, you can use field reverseLayout

                     LazyColumn(
                        modifier = Modifier,
                        reverseLayout = true,
                        state = lazyListState
                    ) {
                        ...
                    }
    

    Of course you have to change some of logic to fit your business, but this layout is the best fit for Chat app.

    Hope you find it useful.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search