Android Column 的使用

774 阅读5分钟

一、基础用法(核心入门)

Column 是 Jetpack Compose 中最基础、最核心的垂直布局容器,作用是将子组件按「从上到下」的顺序垂直排列,类比原生 Android 的 LinearLayout(orientation="vertical")。它是 Compose 布局体系的基石,掌握其用法和细节,能解决 80% 的垂直排列场景。

1、最简示例(无任何配置)

@Composable
fun BasicColumnDemo() {
    // 最基础的 Column:垂直排列子组件
    Column {
        // 子组件1:文本
        Text(text = "第一项", fontSize = 16.sp)
        // 子组件2:按钮
        Button(onClick = { /* 点击逻辑 */ }) {
            Text("第二项(按钮)")
        }
        // 子组件3:图片(示例)
        Icon(
            imageVector = Icons.Default.Home,
            contentDescription = "第三项(图标)",
            modifier = Modifier.size(24.dp)
        )
    }
}
  • 效果:Text → Button → Icon 从上到下依次排列;
  • 核心特点:Column 会根据子组件的总高度自适应自身高度,宽度默认包裹子组件的最大宽度。

2、限制 Column 尺寸(必学)

默认 Column 是 “包裹内容”,实际开发中需限制其尺寸(比如占满屏幕):

@Composable
fun ColumnWithSize() {
    Column(
        modifier = Modifier
            .fillMaxSize() // 占满父容器的宽高(比如屏幕)
            .background(Color.LightGray) // 背景色,方便看范围
    ) {
        Text("占满屏幕的 Column", modifier = Modifier.padding(8.dp))
    }
}

常用尺寸修饰符:

  • fillMaxSize():占满父容器宽高;
  • fillMaxWidth():占满父容器宽度,高度包裹内容;
  • fillMaxHeight():占满父容器高度,宽度包裹内容;
  • width(200.dp)/height(300.dp):固定宽 / 高;
  • size(200.dp):固定宽高。

二、核心参数(掌握布局控制)

Column 的核心能力来自 3 个关键参数,掌握它们就能精准控制子组件的排列方式:

参数作用常用值
modifier控制 Column 自身的尺寸、背景、交互等(所有 Compose 组件通用)fillMaxSize()/background()/padding()/clickable()
horizontalAlignment子组件在水平方向的对齐方式(Column 主轴是垂直,交叉轴是水平)Alignment.Start(左对齐,默认)、Alignment.CenterHorizontally(居中)、Alignment.End(右对齐)
verticalArrangement子组件在垂直方向的排列方式(间距、对齐)Arrangement.Top(顶部,默认)、Arrangement.Center(垂直居中)、Arrangement.Bottom(底部)、Arrangement.SpacedBy(8.dp)(子项间距)

1. 水平对齐(horizontalAlignment)

@Composable
fun ColumnHorizontalAlignment() {
    Column(
        modifier = Modifier
            .fillMaxWidth() // 必须占满宽度,对齐才生效
            .background(Color.LightGray),
        // 子组件水平居中
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text("水平居中的文本")
        Button(onClick = {}) { Text("水平居中的按钮") }
    }
}

⚠️ 关键:horizontalAlignment 需配合 fillMaxWidth() 使用,否则 Column 宽度包裹内容,对齐效果不可见。

2. 垂直排列(verticalArrangement)

@Composable
fun ColumnVerticalArrangement() {
    Column(
        modifier = Modifier
            .fillMaxSize() // 占满屏幕,垂直排列才生效
            .background(Color.LightGray),
        horizontalAlignment = Alignment.CenterHorizontally,
        // 垂直居中 + 子项间距16dp
        verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterVertically)
    ) {
        Text("第一项")
        Text("第二项")
        Text("第三项")
    }
}

常用 Arrangement 类型:

  • Arrangement.Top:子组件靠顶部排列;
  • Arrangement.Center:子组件垂直居中;
  • Arrangement.Bottom:子组件靠底部排列;
  • Arrangement.SpaceBetween:子组件均匀分布(首尾贴边,中间间距相等);
  • Arrangement.SpaceAround:子组件周围间距相等;
  • Arrangement.SpacedBy(8.dp):子组件之间固定间距(最常用)。

4. 子组件权重(weight):占满剩余空间

weight 是子组件的修饰符,用于让子组件占满 Column 的剩余空间,类比原生 LinearLayout 的 layout_weight

@Composable
fun ColumnWithWeight() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.LightGray)
    ) {
        // 固定高度的头部(50dp)
        Text(
            text = "头部",
            modifier = Modifier
                .height(50.dp)
                .fillMaxWidth()
                .background(Color.Gray)
        )

        // 占剩余60%空间的内容区
        Box(
            modifier = Modifier
                .weight(0.6f) // 权重0.6
                .fillMaxWidth()
                .background(Color.Blue)
        )

        // 占剩余40%空间的底部
        Box(
            modifier = Modifier
                .weight(0.4f) // 权重0.4
                .fillMaxWidth()
                .background(Color.Green)
        )
    }
}

⚠️ 注意事项:

  1. weight 必须配合 fillMaxWidth()/fillMaxHeight() 使用(否则权重失效);
  2. 给子组件加 weight 后,其 height 会被忽略(权重优先);
  3. 滚动布局(加了 verticalScroll)中,weight 失效(滚动布局无固定剩余空间)。

三、进阶技巧(解决实际开发问题)

1. 给 Column 加滚动(处理内容溢出)

Column 默认不滚动,子组件总高度超屏时会溢出报错,需手动加滚动:

@Composable
fun ScrollableColumnDemo() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            // 核心:开启垂直滚动
            .verticalScroll(rememberScrollState())
    ) {
        // 模拟30个子项(总高度超屏)
        repeat(30) {
            Text(
                text = "滚动项 $it",
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(8.dp)
            )
        }
    }
}
  • rememberScrollState():创建与 Composable 绑定的滚动状态(确保滚动位置不随重组丢失);

  • 核心限制:加滚动后,Column 仍会一次性渲染所有子项,子项 > 20 时建议换 LazyColumn

2. 给 Column 加间距(两种方式)

  • 方式 1:verticalArrangement = Arrangement.spacedBy(8.dp)(子项统一间距,推荐);
  • 方式 2:手动给子组件加 Spacer(自定义间距,灵活)。
@Composable
fun ColumnWithSpacing() {
    Column(
        modifier = Modifier.fillMaxWidth(),
        // 方式1:统一间距
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        Text("统一间距项1")
        Text("统一间距项2")

        // 方式2:自定义间距(比如加大某两个子项的间距)
        Spacer(modifier = Modifier.height(20.dp)) // 20dp间距
        Text("自定义间距项3")
    }
}

3. 嵌套 Column(局部垂直布局)

实际开发中常嵌套 Column(比如 “外层大布局 + 内层局部布局”):

@Composable
fun NestedColumnDemo() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        // 外层头部
        Text("页面头部", fontSize = 20.sp, fontWeight = FontWeight.Bold)

        // 内层 Column:局部垂直布局
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(16.dp)
                .background(Color.LightGray),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text("内层项1")
            Button(onClick = {}) { Text("内层按钮") }
        }

        // 外层底部
        Text("页面底部", modifier = Modifier.padding(top = 16.dp))
    }
}

⚠️ 避坑:内层 Column 不要加 fillMaxSize(),否则会撑满外层剩余空间,导致外层滚动异常(用 wrapContentHeight() 替代)。

4. Column 加点击事件

给 Column 整体加点击事件(覆盖所有子组件区域):

@Composable
fun ClickableColumnDemo() {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .clickable { // 整体点击事件
                println("Column 被点击了")
            }
            .padding(16.dp)
            .background(Color.LightGray)
    ) {
        Text("点击Column任意位置都响应")
        Button(onClick = { println("按钮单独点击") }) { // 子组件点击事件优先
            Text("按钮")
        }
    }
}
  • 优先级:子组件的点击事件 > Column 的点击事件;

  • 若想让 Column 点击覆盖子组件,需给子组件加 pointerEvents(PointerEvents.None)(禁用子组件点击)。

四、常见坑点 & 避坑指南

问题现象原因解决方案
Column 内容溢出报错子组件总高度超 Column 高度,且未加滚动1. 少量子项:加 verticalScroll;2. 大量子项:换 LazyColumn
水平对齐不生效Column 宽度是 “包裹内容”,无多余空间对齐给 Column 加 fillMaxWidth()
weight 不生效1. 未加 fillMaxWidth()/fillMaxHeight();2. Column 加了滚动1. 补充尺寸修饰符;2. 滚动布局中不用 weight
嵌套 Column 滚动失效内层 Column 加了 fillMaxSize(),撑满外层空间内层 Column 用 wrapContentHeight()
Column 重组卡顿子组件数量过多(>20),一次性渲染所有子项换 LazyColumn;或用 remember 缓存不变子组件