1

I am trying to implement a chat function in my app. I am dealing with the elements being pushed upwards when the keyboard is called. Right now what seems to be working the closest to what I want is setting android:windowSoftInputMode="adjustNothing", adding imePadding and windowInsets since I'm using a Scaffold. However, the padding for the chat box lazy columns move but not the contents. I tried using offset y instead but I'm not really sure how to retrieve the height of the keyboard.

Box(
    Modifier
        .padding(top = 10.dp)
        .fillMaxSize()
        .consumeWindowInsets(padding)
        .imePadding()
        .zIndex(0.5f)
) {

    var listState = rememberLazyListState()
    val coroutineScope = rememberCoroutineScope()
    var textBoxList = remember {
        mutableStateListOf(
            TextBoxData("This is the first message", "Bot"),
            TextBoxData("This is the second message", "User"),
            TextBoxData("This is the first message", "Bot"),
            TextBoxData("This is the second message", "User"),
            TextBoxData("This is the last message", "User")
        )
    }

    // LazyColumn for chat
    LazyColumn(
        Modifier
            .fillMaxSize()
            .padding(bottom = 50.dp),
        state = listState
    ) {
        //For Each, Map
        items(textBoxList) { item ->
            TextBox(item)
        }

    }

    // Bottom Input Bar
    Box(
        Modifier
            .align(Alignment.BottomCenter)
            .fillMaxWidth()
            .height(50.dp)
            .clip(RoundedCornerShape(20.dp))
            .background(Black)
            .border(2.dp, White, RoundedCornerShape(20.dp))
    ) {
        Row(
            Modifier.fillMaxSize(),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Icon(
                imageVector = FeatherIcons.Mic,
                "Microphone Icon",
                tint = White,
                modifier = Modifier
                    .fillMaxHeight()
                    .padding(start = 10.dp)
            )

            // Text Field Here
            var inputText by remember { mutableStateOf("") }
            var textFieldScrollState = rememberScrollState(10)
            var lineWidth = 255.dp
            var textWidth = measureTextWidth(
                inputText,
                TextStyle(
                    fontSize = 16.sp,
                    fontFamily = RalewayRegular
                )
             )

             // Configure the Alignment and Scroll State
             TextField(
                 value = inputText,
                 onValueChange = {
                     inputText = it
                     val currLine = (textWidth / lineWidth).toInt()
                     coroutineScope.launch {
                         textFieldScrollState.scrollTo(
                             // Dont scroll if on first line (Default is 0)
                             if (currLine == 0) 5 else textFieldScrollState.maxValue - 5)
                             Log.i("TextSize", listState.layoutInfo.viewportEndOffset.toString())
                     }
                 },
                 placeholder = {
                     Text(
                         "Type Something...",
                         color = White.copy(0.7f),
                         fontSize = 16.sp,
                         lineHeight = 16.sp,
                         fontFamily = RalewayRegular
                     )
                 },
                 textStyle = TextStyle(
                     color = White,
                     fontSize = 16.sp,
                     fontFamily = RalewayRegular,
                     textAlign = TextAlign.Start,
                 ),
                 modifier = Modifier
                     .width(290.dp)
                     .fillMaxHeight()
                     .padding(start = 10.dp)
                     .verticalScroll(textFieldScrollState),
                 colors = TextFieldDefaults.colors(
                     focusedTextColor = White,
                     unfocusedTextColor = White,
                     unfocusedContainerColor = Black,
                     focusedContainerColor = Black
                 )
             )

             val regex_space = Regex("^\\s*\$") // \\s* means unlimited number of empty (\\s)
             Icon(
                 imageVector = FeatherIcons.Send,
                 contentDescription = "Send button",
                 tint = White,
                 modifier = Modifier
                     .fillMaxHeight()
                     .padding(start = 10.dp)
                     .clickable {
                         if (!inputText.matches(regex_space)) {
                             textBoxList.add(TextBoxData(inputText, "User"))
                             inputText = ""
                             //Use Coroutine Scope to Scroll
                             //LazyColumn needs items(textBoxList) to scroll to the item index
                             coroutineScope.launch {
                                 listState.scrollToItem(textBoxList.size - 1)
                            }
                        }
                    }
                )
            }
        }
    }
}
2
  • Does this answer your question? LazyColumn not scrolling smoothly with keyboard Commented Feb 20 at 5:11
  • you can use Modifier.navigationBarsWithImePadding() to handle the insets and padding correctly. Additionally, ensure that the LazyColumn scrolls to the bottom when new messages are added. Commented Feb 20 at 6:30

1 Answer 1

0

you can consider reverseLayout = true on LazyColumn, and build your UI to reverse messages—place the input field inside the list.

Sign up to request clarification or add additional context in comments.

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.