Flutter 组件:Row / Column

Row 和 Column 的基本用法

Row 示例(水平排列)

Dart 复制代码
Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Icon(Icons.star, color: Colors.yellow),
    Text(' 评分: 4.5'),
  ],
)

Column 示例(垂直排列)

Dart 复制代码
Column(
  mainAxisAlignment: MainAxisAlignment.start,
  children: [
    Text('标题', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
    Text('副标题'),
  ],
)

布局控制属性详解

1. Row / Column 的"坐标系"先搞清楚

1.1 主轴(main axis) vs 交叉轴(cross axis)

  • Row

    • 主轴:水平方向(左 ↔ 右)

    • 交叉轴:垂直方向(上 ↕ 下)

  • Column

    • 主轴:垂直方向(上 ↕ 下)

    • 交叉轴:水平方向(左 ↔ 右)

理解一个关键点:所有 "mainXXX" 控制的是子组件在主轴上的行为;所有 "crossXXX" 控制的是在交叉轴上的行为。

2. mainAxisAlignment:主轴方向"怎么排列"

控制:子组件沿主轴的对齐和间距

Dart 复制代码
Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: const [
    Icon(Icons.star),
    Icon(Icons.star),
    Icon(Icons.star),
  ],
)

枚举值(Row 为例,Column 同理,只是方向变垂直):

start

  • 默认值

  • 子组件紧挤在主轴 起点

  • Row:靠左;Column:靠上

end

  • 子组件紧挤在主轴 终点

  • Row:靠右;Column:靠下

center

  • 子组件整体居中,中间挤在一起

spaceBetween

  • 首尾贴边,中间元素之间"平均分配间距"

  • 典型效果:左一个,右一个,中间均匀散开

spaceAround

  • 子组件之间的间距 相等

  • 首尾和边界的间距 = 中间间距的一半

  • 视觉效果:两边看起来比中间稍紧一点

spaceEvenly

  • 所有间距 完全相等(包括首尾到边界)

  • 最"对称强迫症"友好的布局

心理模型:

  • 不想管"边距",只想管"元素之间":用 spaceBetween

  • 想整体看起来"对称平衡":用 spaceEvenly

  • 想两边略紧,中间舒服:用 spaceAround

3. crossAxisAlignment:交叉轴方向"怎么对齐"

控制:子组件在交叉轴上的对齐(垂直对齐 Row,水平对齐 Column)。

Dart 复制代码
Row(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: const [
    Text('短'),
    Text('一行很长很长很长的文字'),
  ],
)

枚举值(常用):

start

沿交叉轴起点对齐

Row:上对齐;Column:左对齐

end

沿交叉轴终点对齐

Row:下对齐;Column:右对齐

center

沿交叉轴居中对齐(默认)

stretch

  1. 子组件在交叉轴方向被拉伸填满 Row/Column
  2. 前提:子组件在交叉轴方向不能设置"固定尺寸"(比如 width / height

示例(Column 中):

Dart 复制代码
Column(
  crossAxisAlignment: CrossAxisAlignment.stretch,
  children: [
    Container(height: 40, color: Colors.red),
    Container(height: 40, color: Colors.green),
  ],
)

效果:两个 Container 自动铺满宽度 (等同于 width = double.infinity

baseline(只对 Row 有意义)

  • 文字基线 对齐,通常与 Text 搭配

  • 使用时需要指定 textBaseline,否则会报错

Dart 复制代码
Row(
  crossAxisAlignment: CrossAxisAlignment.baseline,
  textBaseline: TextBaseline.alphabetic,
  children: const [
    Text('Hello', style: TextStyle(fontSize: 30)),
    Text('World', style: TextStyle(fontSize: 16)),
  ],
)

效果:两段文字底部基线对齐,而不是按顶部 / 底部对齐。

4. mainAxisSize:主轴方向"占多大空间"

控制:Row / Column 本身在主轴方向上占用多少空间

默认:MainAxisSize.max

4.1 MainAxisSize.max(默认)

  • Row / Column 尽可能占满主轴可用空间

  • Column 中,如果子组件是 Row(mainAxisSize: max),Row 会横向撑满整行。

Dart 复制代码
Column(
  children: [
    Container(color: Colors.grey, height: 200, child: Row(
      mainAxisSize: MainAxisSize.max,
      children: const [
        Text('A'),
        Text('B'),
      ],
    )),
  ],
)

Row 会占满这 200 高容器的宽度。

4.2 MainAxisSize.min

  • Row / Column 在主轴上只包裹子组件所需大小

  • 很适合:居中小块内容 + 外层加对齐控制

Dart 复制代码
Center(
  child: Row(
    mainAxisSize: MainAxisSize.min,
    children: const [
      Icon(Icons.favorite),
      SizedBox(width: 8),
      Text('Like'),
    ],
  ),
)

Row 只会围着 Icon + Text 那一小块内容,而不是横向占满整个屏幕。

5. textDirection / verticalDirection:方向"反过来"

有时候你会发现:start 对齐的方向到底是左还是右?上还是下?

答案:textDirection / verticalDirection 有关。

5.1 textDirection

  • 控制主轴的"起点"是左还是右,常见于 Row

  • 常用值:

    • TextDirection.ltr:左 → 右(默认)

    • TextDirection.rtl:右 → 左(适配阿拉伯语等)

Dart 复制代码
Row(
  textDirection: TextDirection.rtl,
  mainAxisAlignment: MainAxisAlignment.start,
  children: const [
    Text('1'),
    Text('2'),
    Text('3'),
  ],
)

此时 start 是"右边",所以 1、2、3 会从 右向左排。

5.2 verticalDirection

  • 控制交叉轴的"起点"是上还是下,常见于:

    • Column 的主轴(垂直方向)

    • 交叉轴的对齐 start/end 的含义

常用值:

  • VerticalDirection.down(默认):从上往下

  • VerticalDirection.up:从下往上

Dart 复制代码
Column(
  verticalDirection: VerticalDirection.up,
  children: const [
    Text('A'),
    Text('B'),
    Text('C'),
  ],
)

渲染顺序:C 在最上,A 在最下(因为"起点"在下方)。

6. Expanded / Flexible:在主轴上"怎么分配剩余空间"

Row / Column 本身只是"容器",真正控制剩余空间怎么分配 ,要靠 Expanded / Flexible

6.1 Expanded

  • 语义:"把剩余空间都分掉,且子组件必须填满自己的份额"

  • flex 用来控制比例

Dart 复制代码
Row(
  children: [
    Expanded(
      flex: 1,
      child: Container(color: Colors.red, height: 50),
    ),
    Expanded(
      flex: 2,
      child: Container(color: Colors.blue, height: 50),
    ),
  ],
)

效果:红:蓝 = 1 : 2 占主轴宽度。

特点:

  • 会忽略子组件在主轴方向上的尺寸(比如 width),统一按"平分策略"来分配。

6.2 Flexible

  • 语义:"按比例给你一个上限,但你可以比这个小"

  • 子组件可以根据自身 width / height 需要更小的空间,不强制撑满。

常用写法:

Dart 复制代码
Row(
  children: [
    Flexible(
      flex: 1,
      child: Container(
        color: Colors.red,
        height: 50,
        // 宽度可能小于分配给它的那一份
      ),
    ),
    const Text('固定大小的文字'),
  ],
)
Dart 复制代码
Row(
  children: const [
    Expanded(child: Center(child: Text('Tab1'))),
    Expanded(child: Center(child: Text('Tab2'))),
    Expanded(child: Center(child: Text('Tab3'))),
  ],
)

简单记忆:

  • 想让子组件 "铺满自己的份额"Expanded

  • 想让子组件 "最多这么大,多余空间我不一定用完"Flexible

6.3 Spacer:只是"占空位"的 Expanded

Dart 复制代码
Row(
  children: const [
    Text('左'),
    Spacer(),      // 等价于 Expanded(flex: 1, child: SizedBox.shrink())
    Text('右'),
  ],
)

用来快速制造"弹簧"空白区域。

7. 常见布局组合示例

7.1 顶部标题 + 右侧操作按钮

Dart 复制代码
Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: const [
    Text('标题', style: TextStyle(fontSize: 18)),
    Icon(Icons.more_vert),
  ],
)

效果:左标题,右按钮,中间自动拉开。

7.2 三等分底部 Tab

Dart 复制代码
Row(
  children: const [
    Expanded(child: Center(child: Text('Tab1'))),
    Expanded(child: Center(child: Text('Tab2'))),
    Expanded(child: Center(child: Text('Tab3'))),
  ],
)

每个 Tab 自动占 1/3 宽度,居中显示文字。

7.3 内容居中的小块 Tag

Dart 复制代码
Center(
  child: Row(
    mainAxisSize: MainAxisSize.min,
    children: [
      const Icon(Icons.tag),
      const SizedBox(width: 4),
      const Text('Flutter'),
    ],
  ),
)

Row 不会撑满整行,只包裹 Icon + 文字一小块。

7.4 左图 + 右侧标题和描述(典型 ListItem)

Dart 复制代码
Row(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    const Icon(Icons.image, size: 40),
    const SizedBox(width: 8),
    Expanded(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: const [
          Text('标题', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
          SizedBox(height: 4),
          Text('一段比较长的描述文字......', maxLines: 2, overflow: TextOverflow.ellipsis),
        ],
      ),
    ),
  ],
)
  • 外层 Row 控制左右结构

  • 右侧用 Expanded + Column,内部再用 crossAxisAlignment 控制左对齐

8. Row / Column 调试小技巧

  1. 加背景色看布局范围

    Dart 复制代码
    Container(
      color: Colors.yellow.withOpacity(0.2),
      child: Row(...),
    )
  2. 再嵌一层 Container,指定宽高,看"主轴 vs 交叉轴":

    Dart 复制代码
    SizedBox(
      width: 200,
      height: 100,
      child: Container(
        color: Colors.blue.withOpacity(0.1),
        child: Row(...),
      ),
    )
  3. 配合 debugPaintSizeEnabled = true (在 main() 里开启)
    可以看到组件的边界线,帮你看清楚到底是谁在撑大 / 撑满。

相关推荐
程序员老刘4 小时前
Flutter版本选择指南:3.35稳定,3.38发布 | 2025年11月
flutter·客户端
kirk_wang5 小时前
Flutter 3.38和Dart 3.10中最大的更新
flutter
前端小伙计6 小时前
Flutter 配置国内镜像,加速项目加载!
flutter
zonda的地盘9 小时前
开发 Flutter Plugin 之 初始配置
flutter
消失的旧时光-19431 天前
Flutter TextField 从入门到精通:掌握输入框的完整指南
flutter
wordbaby1 天前
Flutter Form Builder 完全指南:告别 Controller 地狱
前端·flutter
tbit1 天前
fluwx 拉起小程序WXLog:Error:fail to load Keychain status:-25300, keyData null:1
flutter·ios·微信小程序
QuantumLeap丶1 天前
《Flutter全栈开发实战指南:从零到高级》- 19 -手势识别
flutter·ios·前端框架
卢叁1 天前
Flutter之阿里云视频播放器支持 iOS模拟器解决方案
flutter