I am making a chat bot application and I show the dialogs in lazycolumn, but the page does not scroll down as the dialog progresses, which causes a bad experience for the user. I found something related to this called rememberLazyListState
and implemented it in my own code but it didn't work properly. I don't know exactly what the problem is. My codes are like this
LazyColumn
val list = remember { mutableStateListOf<Message>() }
val listState = rememberLazyListState()
LazyColumn(state = listState) {
items(list.size) { i ->
Row(
horizontalArrangement =
if (list[i].id == RECEIVE_ID)
Arrangement.Start
else
Arrangement.End
) {
if (list[i].id == RECEIVE_ID) {
Item(message = list[i], botName, botcolor, list, true)
} else {
Item(message = list[i], "user", usercolor, list, false)
}
}
}
}
Item
@Composable
fun Item(
message: Message,
person: String,
color: Color,
list: SnapshotStateList<Message>,
simpleTextFlag: Boolean
) {
Column(modifier = Modifier.fillMaxSize()) {
Card(
modifier = Modifier
.padding(10.dp),
backgroundColor = color,
elevation = 10.dp
) {
Column(
horizontalAlignment = Alignment.End,
modifier = Modifier
.padding(10.dp)
.height(IntrinsicSize.Max)
) {
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(4.dp)
) {
Text(
buildAnnotatedString {
withStyle(
style = SpanStyle(
fontWeight = FontWeight.Medium,
color = Color.Black
)
) {
append("$person: ")
}
},
modifier = Modifier
.padding(4.dp)
)
Text(
buildAnnotatedString {
withStyle(
style = SpanStyle(
fontWeight = FontWeight.W900,
color = Color.White//Color(/*0xFF4552B8*/)
)
)
{
append(message.message)
}
}
)
Spacer(modifier = Modifier.padding(3.dp))
}
}
}
if (simpleTextFlag)
simpleText(list = list)
}
}
@OptIn(ExperimentalComposeUiApi::class, ExperimentalFoundationApi::class)
@Composable
fun simpleText(list: SnapshotStateList<Message>) {
var visible by remember { mutableStateOf(true) }
val coroutineScope = rememberCoroutineScope()
val keyboardController = LocalSoftwareKeyboardController.current
val bringIntoViewRequester = remember { BringIntoViewRequester() }
var text by remember { mutableStateOf("") }
AnimatedVisibility(
visible = visible,
enter = fadeIn() + slideInHorizontally(),
exit = fadeOut() + slideOutHorizontally()
) {
Row(
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.Center,
modifier = Modifier.bringIntoViewRequester(bringIntoViewRequester)
) {
OutlinedTextField(
modifier = Modifier
.padding(8.dp)
.onFocusEvent { focusState ->
if (focusState.isFocused) {
coroutineScope.launch {
bringIntoViewRequester.bringIntoView()
}
}
},
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = { keyboardController?.hide() }),
value = text,
onValueChange = { text = it },
shape = RoundedCornerShape(12.dp),
label = { Text("send message") })
IconButton(onClick = {
if (text.isNotEmpty()) {
//Adds it to our local list
list.add(
Message(
text,
Constants.SEND_ID,
Timestamp(System.currentTimeMillis()).toString()
)
)
customBotMessage(Messages.listOfMessages[index], list)
index += 1
}
text = ""
visible = false
}) {
Icon(
modifier = Modifier.padding(8.dp),
painter = painterResource(id = R.drawable.ic_baseline_send_24),
contentDescription = "send message img"
)
}
}
}
}
private fun customBotMessage(message: String, list: SnapshotStateList<Message>) {
GlobalScope.launch {
delay(1000)
withContext(Dispatchers.Main) {
list.add(
Message(
message,
Constants.RECEIVE_ID,
Timestamp(System.currentTimeMillis()).toString()
)
)
}
}
}
I keep a list
of type MutableStateListof
This list:
val list = remember { mutableStateListOf<Message>() }.
This is the list
I use in LazyColumn
. When the bot gives a message, it is added to the list
, in the same way, when the user enters a message, it is added to the list
and LazyColumn
displays them.