我有一个具有共享 UI 的 KMM 项目。 我有一个聊天屏幕,其中有一个顶部栏,其中包含聊天信息、消息列表和用于编写新消息的输入字段。 我的问题是,当键盘出现时,所有内容都会被推送,包括 TopAppBar。 我希望只调整 LazyColumn 的大小并固定 TopBar。 当然,我的 AndroidApp 清单中有 android:windowSoftInputMode="adjustResize" 我在 stackoverflow 中读到了一些类似的问题,但没有一个有帮助。
代码如下
Column(
modifier = Modifier
.statusBarsPadding()
.fillMaxWidth()
.background(Color.White),
) {
TopAppBar(
modifier = Modifier
.fillMaxWidth()
.requiredHeight(56.dp),
scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(),
title = {
Row(
modifier = Modifier
.fillMaxWidth()
.requiredHeight(56.dp),
verticalAlignment = Alignment.CenterVertically
) {
Image(
modifier = Modifier.height(44.dp).width(44.dp).clickable(enabled = true) {
component.onEvent(ChatRoomEvents.BackClick)
},
contentScale = ContentScale.None,
painter = painterResource(Res.drawable.back_green),
contentDescription = Strings.getString("back")
)
SeafarerImage(
modifier = chatRoomImageModifier,
picture = component.chatRoom.pic,
placeHolder = if (component.chatRoom.isSupport) Res.drawable.nextship_logo_short else Res.drawable.empty_seafarer_chat
)
Column(
modifier = Modifier.weight(1f).height(41.dp).padding(start = 8.dp)
) {
Text(
modifier = Modifier.height(19.dp),
text = component.chatRoom.userName ?: "",
textAlign = TextAlign.Start,
style = getTypography().subtitle1,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
modifier = Modifier.height(19.dp),
text = "last seen recently", // TODO time
textAlign = TextAlign.Start,
style = getTypography().subtitle2,
fontSize = 13.sp,
color = lightGreen,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
Image(
modifier = Modifier.height(44.dp).width(44.dp).clickable(enabled = true) {
component.onEvent(ChatRoomEvents.SendMessage)
},
contentScale = ContentScale.None,
painter = painterResource(Res.drawable.trash),
contentDescription = Strings.getString("delete_chat")
)
Spacer(Modifier.width(6.dp))
}
}
)
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.background(brush),
state = listState,
reverseLayout = true
) {
item {
if (screenState.isLoading) ProgressIndicator()
}
items(
count = messages.size
) { index ->
ChatItem(messages[index], component.dateFormat)
}
}
if (!listState.isScrollInProgress) {
if (!listState.canScrollForward && listState.canScrollBackward && component.needNextPage)
component.getNextPage()
}
CommentRow(modifier = Modifier.fillMaxWidth(),
interactionSource = commentInteractionSource,
currentText = screenState.messageText ?: "",
sendEnabled = true,//!screenState.isLoading && screenState.currentText?.isNotEmpty() == true,
onTextChange = { newText -> component.onEvent(ChatRoomEvents.MessageTextChanged(newText)) },
onSendClick = { component.onEvent(ChatRoomEvents.SendMessage) }
)
评论行:
@OptIn(ExperimentalResourceApi::class)
@Composable
fun CommentRow(
modifier: Modifier,
interactionSource: MutableInteractionSource,
currentText: String,
sendEnabled: Boolean,
onTextChange: (String) -> Unit,
onSendClick: () -> Unit,
) {
Row(
modifier = modifier
.wrapContentHeight()
.navigationBarsPadding()
.background(Color.White)
) {
BasicTextField(
modifier = Modifier
.weight(1f)
.heightIn(50.dp, 100.dp)
.background(Color.White)
.padding(start = 20.dp, top = 10.dp, bottom = 10.dp),
interactionSource = interactionSource,
textStyle = getTypography().subtitle2,
value = currentText,
onValueChange = { newText -> onTextChange(newText) },
maxLines = 3,
)
Spacer(Modifier.width(10.dp))
Box(
modifier = Modifier
.width(48.dp)
) {
Image(
modifier = Modifier
.height(26.dp)
.width(26.dp)
.offset(y = 13.dp)
.clickable(enabled = sendEnabled) { onSendClick() },
painter = painterResource(if (sendEnabled) Res.drawable.send_message else Res.drawable.send_message_disabled),
contentDescription = Strings.getString("send_message")
)
}
}
}
我希望顶部栏固定在屏幕上
Scaffold
可组合项。它为诸如 TopAppBar 之类的东西提供了插槽。你可以这样使用它:
Scaffold(
topBar = {
TopAppBar(
modifier = Modifier
.fillMaxWidth()
.requiredHeight(56.dp),
backgroundColor = Color.White,
contentColor = Color.Black, // Change content color as needed
title = {
//...
}
)
},
content = { innerPadding ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
.imePadding()
) {
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.background(brush),
state = listState,
reverseLayout = true
) {
item {
if (screenState.isLoading) ProgressIndicator()
}
items(
count = messages.size
) { index ->
ChatItem(messages[index], component.dateFormat)
}
}
if (!listState.isScrollInProgress) {
if (!listState.canScrollForward && listState.canScrollBackward && component.needNextPage)
component.getNextPage()
}
CommentRow(
modifier = Modifier.fillMaxWidth(),
interactionSource = commentInteractionSource,
currentText = screenState.messageText ?: "",
sendEnabled = true,//!screenState.isLoading && screenState.currentText?.isNotEmpty() == true,
onTextChange = { newText -> component.onEvent(ChatRoomEvents.MessageTextChanged(newText)) },
onSendClick = { component.onEvent(ChatRoomEvents.SendMessage) }
)
}
}
)
Scaffold 将确保 TopAppBar 保持可见,即使内容因键盘而向上推。另外,我添加了
imePadding
修改器,以便在键盘打开时向上移动内容。