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

Jetpack Compose:单文本存在时消除占位空白并实现垂直居中对齐

问题原因

当categoryName为null时,文本容器(Column)的高度会因缺少一个文本而变小,而Row的verticalAlignment = Alignment.CenterVertically会让容器垂直居中,导致剩余的taskName文本位置下移,看起来顶部有空白。


修复方案

方案一:固定文本容器最小高度

通过计算两个文本的总高度,给Column设置minHeight,确保容器高度始终与两个文本都存在时一致,这样Row居中后,文本的顶部位置不会变化:

@Composable
fun TaskCard(
    modifier: Modifier = Modifier,
    task: Task,
    viewModel: TaskListViewModel = hiltViewModel()
) {
    val typography = MaterialTheme.typography
    // 计算文本行高(可根据实际样式调整)
    val categoryTextHeight = with(LocalDensity.current) { typography.titleMedium.lineHeight.toDp() }
    val taskTextHeight = with(LocalDensity.current) { typography.headlineSmall.lineHeight.toDp() }
    // 文本间距和容器内边距的总高度
    val totalContainerHeight = categoryTextHeight + taskTextHeight + 4.dp + 24.dp // 4dp是文本间距,24dp是Column上下padding(12*2)

    Card(
        colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant),
        modifier = modifier.padding()
    ) {
        Surface(
            color = MaterialTheme.colorScheme.surfaceVariant,
            modifier = modifier
        ) {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                modifier = modifier.padding(12.dp)
            ) {
                Column(
                    modifier = modifier
                        .weight(1f)
                        .padding(12.dp)
                        .minHeight(totalContainerHeight), // 固定最小高度
                    verticalArrangement = Arrangement.Top
                ) {
                    task.categoryName?.let {
                        Text(
                            text = it,
                            style = typography.titleMedium,
                            color = MaterialTheme.colorScheme.primary
                        )
                        // 仅当分类名存在时显示间距
                        Spacer(modifier = Modifier.height(4.dp))
                    }
                    Text(
                        text = task.taskName,
                        style = typography.headlineSmall,
                        color = MaterialTheme.colorScheme.onBackground
                    )
                }

                IconButton(
                    onClick = { viewModel.onEvent(TaskListEvent.OnEditTask(task)) },
                    modifier = modifier.size(36.dp)
                ) {
                    Icon(
                        imageVector = Icons.Rounded.Edit,
                        contentDescription = "编辑",
                        modifier = modifier.padding(horizontal = 2.dp),
                        tint = MaterialTheme.colorScheme.onBackground
                    )
                }
                IconButton(
                    onClick = { },
                    modifier = modifier.size(36.dp)
                ) {
                    Icon(
                        imageVector = Icons.Rounded.Notifications,
                        contentDescription = "通知",
                        modifier = modifier.padding(horizontal = 2.dp),
                        tint = MaterialTheme.colorScheme.onBackground
                    )
                }
            }
        }
    }
}

方案二:用Box作为容器,统一对齐基准

将Column包裹在Box中,设置Box的minHeight为两个文本的总高度,同时让Box内容顶部对齐,这样不管文本数量多少,容器高度不变,文本顶部位置始终与两个文本都存在时的顶部对齐:

@Composable
fun TaskCard(
    modifier: Modifier = Modifier,
    task: Task,
    viewModel: TaskListViewModel = hiltViewModel()
) {
    val typography = MaterialTheme.typography
    val categoryTextHeight = with(LocalDensity.current) { typography.titleMedium.lineHeight.toDp() }
    val taskTextHeight = with(LocalDensity.current) { typography.headlineSmall.lineHeight.toDp() }
    val totalTextHeight = categoryTextHeight + taskTextHeight + 4.dp // 4dp是文本间距

    Card(
        colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant),
        modifier = modifier.padding()
    ) {
        Surface(
            color = MaterialTheme.colorScheme.surfaceVariant,
            modifier = modifier
        ) {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                modifier = modifier.padding(12.dp)
            ) {
                Box(
                    modifier = modifier
                        .weight(1f)
                        .padding(12.dp)
                        .minHeight(totalTextHeight),
                    contentAlignment = Alignment.TopStart
                ) {
                    Column {
                        task.categoryName?.let {
                            Text(
                                text = it,
                                style = typography.titleMedium,
                                color = MaterialTheme.colorScheme.primary
                            )
                            Spacer(modifier = Modifier.height(4.dp))
                        }
                        Text(
                            text = task.taskName,
                            style = typography.headlineSmall,
                            color = MaterialTheme.colorScheme.onBackground
                        )
                    }
                }

                IconButton(
                    onClick = { viewModel.onEvent(TaskListEvent.OnEditTask(task)) },
                    modifier = modifier.size(36.dp)
                ) {
                    Icon(
                        imageVector = Icons.Rounded.Edit,
                        contentDescription = "编辑",
                        modifier = modifier.padding(horizontal = 2.dp),
                        tint = MaterialTheme.colorScheme.onBackground
                    )
                }
                IconButton(
                    onClick = { },
                    modifier = modifier.size(36.dp)
                ) {
                    Icon(
                        imageVector = Icons.Rounded.Notifications,
                        contentDescription = "通知",
                        modifier = modifier.padding(horizontal = 2.dp),
                        tint = MaterialTheme.colorScheme.onBackground
                    )
                }
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:11:48