Jetpack Compose TopBar 在键盘显示上向上推

问题描述 投票:0回答:1

我有一个具有共享 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")
            )
        }
    }
}

No keyboard Keyboard

我希望顶部栏固定在屏幕上

kotlin android-jetpack-compose kotlin-multiplatform
1个回答
0
投票

您应该使用

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
修改器,以便在键盘打开时向上移动内容。

© www.soinside.com 2019 - 2024. All rights reserved.