Я пытаюсь разработать интерфейс чата 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
Lazycolumn не плавно прокручивать с клавиатурой ⇐ Android
Форум для тех, кто программирует под Android
-
Anonymous
1739374209
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",
)
}
}
}
}
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79433620/lazycolumn-not-scrolling-smoothly-with-keyboard[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия