Lazycolumn не плавно прокручивать с клавиатуройAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Lazycolumn не плавно прокручивать с клавиатурой

Сообщение Anonymous »

Я пытаюсь разработать интерфейс чата AI в JetPack Compose, аналогичный функциональности с DeepSeek. Я использую Lazycolumn, чтобы показать историю разговоров. Когда появляется мягкая клавиатура, я хочу, чтобы Lazycolumn плавно прокручивался вверх и синхронно с анимацией клавиатуры, сохраняя последние сообщения, видимые над клавиатурой. < /P>
В настоящее время клавиатура скрывает нижнюю часть из Lazycolumn, включая самые последние сообщения и само поле ввода. Контент корректируется только после того, как клавиатура полностью заметна, что создает плохой пользовательский опыт. Я ищу гладкий, анимированный переход. 50) < /code> делает Lazycolumn Scroll не гладко.
Ниже приведены некоторые из моего кода < /p>
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class, FlowPreview::class)
@Composable
fun Chat(chatModel: AIChatModel = AIChatModel(), modifier: Modifier = Modifier) {

val listState = rememberLazyListState()
var lastKnownLastVisibleItemIndex by remember { mutableIntStateOf(aiChatModel.chatHistory.size-1) }
var lastKnownLastVisibleItemOffset by remember { mutableIntStateOf(0) }
var lastKnownHeight by remember { mutableIntStateOf(0) }

Scaffold(
modifier = modifier,
topBar = {
TopAppBar(
title = {
Column(modifier= Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Text("DeepSeek")
}
}
)
},
) { padding ->
Column(modifier= Modifier
.padding(padding)
.fillMaxSize()) {
// listening listState
LaunchedEffect(key1 = listState) {
println("listState changed")
snapshotFlow {
val visibleItemsInfo = listState.layoutInfo.visibleItemsInfo
if (visibleItemsInfo.isNotEmpty()) {
val lastVisibleItem = visibleItemsInfo.last()
val viewportHeight = listState.layoutInfo.viewportEndOffset - listState.layoutInfo.viewportStartOffset
if (viewportHeight != lastKnownHeight) {
println("viewportHeight: $viewportHeight")
Triple(lastKnownLastVisibleItemIndex, lastKnownLastVisibleItemOffset, viewportHeight)
}else {
println("lastVisibleItemIndex: ${lastVisibleItem.index}, lastVisibleItemOffset: ${lastVisibleItem.offset}")
Triple(lastVisibleItem.index, lastVisibleItem.offset, lastKnownHeight)
}
} else {
Triple(lastKnownLastVisibleItemIndex, lastKnownLastVisibleItemOffset, lastKnownHeight)
}
}
.filter {
it.first != lastKnownLastVisibleItemIndex || it.second != lastKnownLastVisibleItemOffset || it.third != lastKnownHeight
}
.debounce(50)
.collect { (index, offset, height) ->

if(height != lastKnownHeight && index > 0){
listState.scrollToItem(lastKnownLastVisibleItemIndex, -lastKnownLastVisibleItemOffset+lastKnownHeight-height)
println("scrollToItem: $lastKnownLastVisibleItemIndex, ${lastKnownLastVisibleItemOffset+lastKnownHeight-height}")
}

lastKnownLastVisibleItemIndex = index
lastKnownLastVisibleItemOffset = offset
lastKnownHeight = height
}
}

LazyColumn(
modifier = Modifier
.fillMaxWidth()
.weight(1f),
state = listState
) {
items(chatModel.chatHistory) { message ->
MessageBubble(message = message)
}
if (chatModel.output.isNotEmpty()) {
item {
MessageBubble(role = "assistant", content = chatModel.output)
}
}

}
OutlinedTextField(
value = chatModel.input,
onValueChange = {
chatModel.input = it
},
placeholder = {
Text("Enter text")
},
maxLines = 6,
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.padding(end = 0.dp)
)
Row(modifier = Modifier
.imePadding()
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End) {
IconButton(
modifier = Modifier.padding(bottom = 8.dp, start = 8.dp),
onClick = {
chatModel.clearHistory()
},
enabled = chatModel.chatHistory.isNotEmpty()
) {
Icon(
imageVector = Icons.Outlined.Delete,
contentDescription = "Clear",
)
}
if (chatModel.isEnding) {
IconButton(
modifier = Modifier.padding(bottom = 8.dp, end = 16.dp, start = 8.dp),
onClick = {
chatModel.sendMessage()
},
enabled = chatModel.input.isNotEmpty() && chatModel.input.isNotBlank(),
) {
Icon(
imageVector = Icons.AutoMirrored.Filled.Send,
contentDescription = "Send",
)
}
}else{
IconButton(
modifier = Modifier.padding(bottom = 8.dp, end = 16.dp, start = 8.dp),
onClick = {
chatModel.endResponse()
},
) {
Icon(
imageVector = Icons.Outlined.Add,
contentDescription = "Send",
)
}
}

}
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/794 ... h-keyboard
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»