почему я не могу использовать scrollToEnd или подобные функции в моем проекте Jetpack Compose?

Я пытаюсь перейти к последнему элементу ленивого столбца, потому что у меня есть ленивый столбец и пустой список. Приложение, которое я сделал, является приложением чат-бота, есть сообщения бота и сообщения пользователя. Когда бот дает сообщение, оно добавляется в , в то же время, когда пользователь вводит ответ, оно добавляется в , и по мере добавления в этот пустой список начинает заполняться, а также отображается ленивый столбец , но это отдельная вещь, которая должна быть в заочном приложении. По мере добавления сообщений, то есть при достижении конца экрана, экран должен скользить вниз. Я использовал или что-то подобное, чтобы сделать это, но мой проект не видитscrollToEndи выдает следующую ошибкуUnresolved reference: scrollToEndили напримерisScrolledToEnd()Когда я использую это, мне интересно, есть ли отдельный элемент, который я должен добавить. Есть ли зависимость или они устарели? вы можете помочь мне решить эту проблему


      var index = 1

@SuppressLint("CoroutineCreationDuringComposition")
@Composable
fun FirstScreen() {

    val list = remember { mutableStateListOf<Message>() }
    val UserList = remember { mutableStateListOf<Message>() }
    val botList = listOf("Peter", "Francesca", "Luigi", "Igor")
    val random = (0..3).random()
    val botName: String = botList[random]
    val hashMap: HashMap<String, String> = HashMap<String, String>()
    val coroutineScope = rememberCoroutineScope()

    customBotMessage(message = Message1, list)

    Column(modifier = Modifier.fillMaxHeight(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Top) {

        Image(
            painter = painterResource(id = R.drawable.diyetkolik_logo),
            contentDescription = "logo",
            modifier = Modifier.padding(10.dp)
        )

        Divider()
        val listState = rememberLazyListState()

        LazyColumn(modifier = Modifier.fillMaxSize(),
            state = listState) {
            println("size:"+list.size)
            items(list.size) { i ->

                Row(
                    modifier = Modifier.fillMaxWidth(),
                    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,
                            simpleTextFlag = true,
                            hashMap,
                            modifier = Modifier
                                .padding(
                                    start = 32.dp,
                                    end = 4.dp,
                                    top = 4.dp
                                ),
                        )
                    } else {
                        Item(
                            message = list[i],
                            "user",
                            usercolor,
                            UserList,
                            simpleTextFlag = false,
                            hashMap,
                            Modifier.padding(
                                start = 4.dp,
                                end = 32.dp,
                                top = 4.dp
                            )
                        )
                    }
                }
            }
        }
        val endOfListReached = remember {
            derivedStateOf {
                listState.isAtBottom() // error occurs @Composable invocations can only happen from the context of a @Composable function
            }
        }

        // act when end of list reached
        LaunchedEffect(endOfListReached) {
            // do your stuff
        }
    }
}

private fun customBotMessage(message: String, list: SnapshotStateList<Message>) {

    GlobalScope.launch {
        delay(1000)
        withContext(Dispatchers.Main) {
            list.add(
                Message(
                    message,
                    RECEIVE_ID,
                    Timestamp(System.currentTimeMillis()).toString()
                )
            )

        }
    }
}

      @Composable
fun Item(
    message: Message,
    person: String,
    color: Color,
    list: SnapshotStateList<Message>,
    simpleTextFlag: Boolean,
    hashMap: HashMap<String, String>,
    modifier: Modifier
) {

    Column(verticalArrangement = Arrangement.Top) {
        Card(
            modifier = Modifier
                .padding(10.dp),
            backgroundColor = color,
            elevation = 10.dp
        ) {
            Row(
                verticalAlignment = Alignment.Top,
                modifier = Modifier.padding(3.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)
                        }
                    }
                )
            }
        }
        if (simpleTextFlag)
            SimpleText(list = list, hashMap)
    }
}

@OptIn(ExperimentalComposeUiApi::class, ExperimentalFoundationApi::class)
@Composable
fun SimpleText(list: SnapshotStateList<Message>, hashMap: HashMap<String, String>) {

    val coroutineScope = rememberCoroutineScope()
    val keyboardController = LocalSoftwareKeyboardController.current
    val bringIntoViewRequester = remember { BringIntoViewRequester() }
    var visible by remember { mutableStateOf(true) }

    var text by remember { mutableStateOf("") }

    AnimatedVisibility(
        visible = visible,
        enter = fadeIn() + slideInHorizontally(),
        exit = fadeOut() + slideOutHorizontally()
    ) {
        Row(
            verticalAlignment = Alignment.Bottom,
            horizontalArrangement = Arrangement.End,
            modifier = Modifier.bringIntoViewRequester(bringIntoViewRequester)
        ) {
            OutlinedTextField(
                modifier = Modifier
                    .padding(2.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()
                        )
                    )
                    hashMap.put(Messages.listOfMessageKeys[index - 1], text)
                    customBotMessage(listOfMessages[index], list)
                    index += 1
                    visible = false
                }
                text = ""


            }) {
                Icon(
                    modifier = Modifier.padding(2.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()
                )
            )
        }
    }
}

Я знаю, что это плохо написанный код, и у вас могут возникнуть проблемы с его пониманием, поэтому я объясню, как этот код работает для вас. Вкратце, первый экран, который открывается, это FirstScreen, и есть пустой список, который я определил здесь, и под пустым списком я подразумеваюval list = remember { mutableStateListOf<Message>() }на первом экране. Во-первых, я звоню вcustomBotMessageдля взаимодействия с пользователем и добавляет первое сообщение в подготовленный мной список сообщений. При добавлении в , он попадает в ленивую колонку и отображается на экране как .

При переходе к , есть окно сообщения в и текстовое поле сразу под окном сообщения, где пользователь может ввести ввод, если сообщение, входящее вItemэто пользовательское сообщение, показать это текстовое поле ввода. Я проверил это с помощьюidвifсостояния в ленивом столбце в FirstScreen, вы можете понять, если посмотрите на файл FirstScreen. И когда пользователь вводит значение в это текстовое поле ввода, оно добавляется туда же и отображается на экране, но по мере добавления сообщений в полеlist, я хочу, чтобы экран прокручивался вниз, как я сказал выше, как я могу сделать это в своем коде?

РЕДАКТИРОВАТЬ

@GabrieleMarriotti

Спасибо за ваш ответ, но я думаю, что не объяснил точно, что я хотел, или я не понял, извините. У меня есть список, и сообщения добавляются в этот список по порядку, и по мере добавления они появляются на экране, поэтому у меня нет 100 сообщений в списке одновременно. Как и в приложении для переписки, сообщения скользят по экрану вниз, а когда доходят до нижней части экрана, последние добавленные сообщения не видны. Я хочу, чтобы пользователь мог видеть последнее добавленное сообщение, то есть экран прокручивался вниз, чтобы пользователь мог видеть последнее добавленное сообщение. Я сделал ответ, который вы дали, но он дал следующую ошибку

      @Composable invocations can only happen from the context of a @Composable function

и я не мог точно понять, как использовать его в моем вопросе. Если ваш ответ является последним индексом, он возвращает true, в противном случае он возвращает false. Если это именно ответ на мой вопрос, я не мог понять, как и где его использовать в моем коде. Может ли это быть проблемой с lazycolumn, потому что lazycolumn не должен выполнять эту задачу автоматически? спасибо за Ваш ответ

1 ответ

Пожалуйста, установитеLayColumn, вам не нужно вызывать scrollToEnd, вы добавляете в список, последние новости будут отображаться автоматически:

      LazyColumn(
     reverseLayout = true,
     state = listState,
     modifier = Modifier.fillMaxSize(),
     horizontalAlignment = Alignment.CenterHorizontally,
     verticalArrangement = Arrangement.Top) {
   // do something....
}