android 为什么我不能在Jetpack合成项目中使用scrollToEnd或类似函数?

xyhw6mcr  于 2023-01-15  发布在  Android
关注(0)|答案(2)|浏览(119)

我试图去lazycolumn最后一项,因为我有一个lazycolumn和空列表。我做的应用程序是一个聊天机器人应用程序,有机器人消息和用户消息。当机器人给出消息时,它被添加到list,同时,当用户输入回复时,它被添加到list,当它被添加到这个list时,空列表开始填满,lazycolumn也显示出来,但它是一个单独的东西,应该在通信应用中,随着消息的添加,也就是到了屏幕的末尾,屏幕需要向下滑动,我用了scrollToEnd或者类似的东西来做这个,但我的项目没有看到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.isScrolledToEnd() // error occurs Unresolved reference
            }
        }

        // 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,这里定义了一个空列表,这里的空列表指的是FirstScreen中的val list = remember { mutableStateListOf<Message>() }。首先,我调用customBotMessage函数与用户交互。并且它添加我准备的消息列表中的第一条消息,当添加到list时,它进入lazycolumn,并在屏幕上显示为Item
当转到Item时,Item中有一个消息框,消息框下方有一个文本字段,用户可以在其中输入,如果传入Item的消息是用户消息,则显示此输入文本字段。我使用FirstScreen中lazycolumn中if状态中的id检查了此问题,如果你看一下FirstScreen,你就会明白,当用户在输入文本域中输入一个值时,它会被添加到相同的list中并显示在屏幕上,但是当消息被添加到list中时,我希望屏幕向下滚动,正如我上面所说的,我如何在代码中做到这一点?

ukdjmx9f

ukdjmx9f1#

listState.isScrolledToEnd() // error occurs Unresolved reference

函数listState.isScrolledToEnd()当前不存在于合成中。
1.4.0-alpha03开始,您可以使用**LazyListState#canScrollForward**检查您是否位于列表末尾。

val listState = rememberLazyListState()
val isAtBottom = listState.canScrollForward

1.4.0-alpha03之前,您必须构建一个自定义函数,如下所示:

@Composable
private fun LazyListState.isAtBottom(): Boolean {

    return remember(this) {
        derivedStateOf {
            val visibleItemsInfo = layoutInfo.visibleItemsInfo
            if (layoutInfo.totalItemsCount == 0) {
                false
            } else {
                val lastVisibleItem = visibleItemsInfo.last()
                val viewportHeight = layoutInfo.viewportEndOffset + layoutInfo.viewportStartOffset

                (lastVisibleItem.index + 1 == layoutInfo.totalItemsCount &&
                        lastVisibleItem.offset + lastVisibleItem.size <= viewportHeight)
            }
        }
    }.value
}
ttp71kqs

ttp71kqs2#

请设置您的LayColumn,您不需要调用scrollToEnd,您添加到列表中,最新消息将自动显示:

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

相关问题