You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中Surface为何无法适配Text组件的尺寸?

Jetpack Compose聊天界面Surface适配问题解决

问题描述

开发Jetpack Compose聊天界面时,MessageItem组件中的Surface无法适配内部Text的尺寸,尝试使用wrapContentSize()方法未生效。相关代码及界面截图如下:

ChatScreen代码

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ChatScreen(
    chatId: String?,
    onBack: () -> Unit
) {
    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text(
                        text = "Chat with Alice"
                    )
                }
            )
        },
        bottomBar = {
            SendMessageBox()
        }
    ) { innerPadding ->
        ListOfMessages(modifier = Modifier.padding(innerPadding))
    }
}

ListOfMessages代码

@Composable
fun ListOfMessages(modifier: Modifier = Modifier) {

    LazyColumn(
        modifier = modifier.fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        items(getFakeMessages()) { message ->
            MessageItem(message)
        }
    }
}

MessageItem代码

@Composable
fun MessageItem(message: Message) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .then(if (message.isMine) Modifier.padding(start = 48.dp) else Modifier),
        horizontalArrangement = if (message.isMine) Arrangement.End else Arrangement.Start
    ) {
        if (!message.isMine) {
            Avatar(
                imageUrl = message.senderAvatar,
                size = 40.dp,
                contentDescription = "${message.senderName}'s avatar"
            )
            Spacer(modifier = Modifier.width(8.dp))
        }
        Column {
            if (message.isMine) {
                Spacer(modifier = Modifier.height(8.dp))
            } else {
                Text(
                    text = message.senderName,
                    fontWeight = FontWeight.Bold
                )
            }
            when (val content = message.messageContent) {
                is MessageContent.TextMessage -> {
                    Surface(
                        shape = RoundedCornerShape(8.dp),
                        color = if (message.isMine) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary
                    ) {
                        Text(
                            text = content.message,
                            modifier = Modifier.padding(8.dp),
                            color = if (message.isMine) MaterialTheme.colorScheme.onPrimary else Color.White
                        )
                    }
                }

                is MessageContent.ImageMessage -> {
                    AsyncImage(
                        model = content.imageUrl,
                        contentDescription = content.contentDescription,
                        modifier = Modifier
                            .size(40.dp)
                            .clip(CircleShape),
                        contentScale = ContentScale.Crop
                    )
                }
            }
            Text(
                text = message.timestamp,
                fontSize = 12.sp
            )
        }
    }
}

聊天界面截图

问题原因及解决方案

问题根源

MessageItem中的Column默认会占满父布局(Row)的宽度,导致Surface在无宽度约束的情况下撑满整个Column宽度,无法贴合内部Text的实际尺寸。单独给Surface加wrapContentSize()没用,因为父布局Column的宽度已经被拉满了。

修复方法

给包裹Surface的Column添加Modifier.wrapContentWidth(),让Column仅包裹自身内容的宽度,这样Surface就能自动适配内部Text的大小。

修改后的MessageItem关键代码片段:

Column(modifier = Modifier.wrapContentWidth()) {
    if (message.isMine) {
        Spacer(modifier = Modifier.height(8.dp))
    } else {
        Text(
            text = message.senderName,
            fontWeight = FontWeight.Bold
        )
    }
    when (val content = message.messageContent) {
        is MessageContent.TextMessage -> {
            Surface(
                shape = RoundedCornerShape(8.dp),
                color = if (message.isMine) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary
            ) {
                Text(
                    text = content.message,
                    modifier = Modifier.padding(8.dp),
                    color = if (message.isMine) MaterialTheme.colorScheme.onPrimary else Color.White
                )
            }
        }
        is MessageContent.ImageMessage -> {
            AsyncImage(
                model = content.imageUrl,
                contentDescription = content.contentDescription,
                modifier = Modifier
                    .size(40.dp)
                    .clip(CircleShape),
                contentScale = ContentScale.Crop
            )
        }
    }
    Text(
        text = message.timestamp,
        fontSize = 12.sp
    )
}

如果希望消息文本过长时自动换行,还可以给Text添加Modifier.fillMaxWidth(0.7f),限制消息最大宽度为父布局的70%,提升界面美观度。

内容的提问来源于stack exchange,提问作者Dadky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 23:54:50