[Flutter 基础] - Flutter核心布局组件 - Row

514 阅读4分钟

Flutter 的 Row 组件用于在水平方向排列子组件,是构建灵活布局的核心组件之一。它的用法其实和Column基本一致,只是一个纵向列表布局,一个横向列表布局。 以下是 通过一些Row 的用法示例,包含核心属性及常见场景的解决方案。


一、基本用法

Row 的基本结构如下:

image.png

Container(
  height: 200,
  width: 300,
  decoration: BoxDecoration(
      border: Border.all(color: Colors.black, width: 2)
  ),
  child: Row(
    children: [
      Container(width: 50, color: Colors.red),
      Container(width: 50, color: Colors.green),
      Container(width: 50, color: Colors.blue),
      Container(width: 50, color: Colors.black),
    ],
  ),
),

二、核心属性

1. 主轴对齐:mainAxisAlignment

控制子组件在水平方向(主轴)的对齐方式,默认为 MainAxisAlignment.start(从左侧开始排列)。
可选值:

  • mainAxisAlignment.start:左对齐

image.png

  • mainAxisAlignment.end:右对齐

image.png

  • mainAxisAlignment.center:居中对齐

image.png

  • mainAxisAlignment.spaceBetween:均匀分布(首尾无空隙)

image.png

  • mainAxisAlignment.spaceAround:均匀分布(子组件两侧空隙相等)

image.png

  • mainAxisAlignment.spaceEvenly:完全均匀分布

image.png

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Container(width: 50, color: Colors.red),
    Container(width: 50, color: Colors.green),
    Container(width: 50, color: Colors.blue),
    Container(width: 50, color: Colors.black),
  ],
),

2. 交叉轴对齐:crossAxisAlignment

控制子组件在垂直方向(交叉轴)的对齐方式,默认为 CrossAxisAlignment.center
可选值:

  • CrossAxisAlignment.start:顶部对齐

image.png

  • CrossAxisAlignment.end:底部对齐

image.png

  • CrossAxisAlignment.center:垂直居中

image.png

  • CrossAxisAlignment.stretch:拉伸子组件高度(需子组件允许)

image.png

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  crossAxisAlignment: CrossAxisAlignment.stretch,
  children: [
    Container(width: 50, height: 100, color: Colors.red),
    Container(width: 50, height: 100, color: Colors.green),
    Container(width: 50, height: 100, color: Colors.blue),
    Container(width: 50, height: 100, color: Colors.black),
  ],
),

3. 主轴尺寸:mainAxisSize

控制 Row 自身在主轴方向的占用空间:

  • MainAxisSize.max(默认):占满父容器的宽度
  • MainAxisSize.min:根据子组件总宽度自适应
 Container(
  height: 200,
  width: 300,
  decoration: BoxDecoration(
      border: Border.all(color: Colors.black, width: 2)
  ),
  child: Row(
    mainAxisSize: MainAxisSize.max,
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      Container(width: 50, height: 100, color: Colors.red),
      Container(width: 50, height: 100, color: Colors.green),
      Container(width: 50, height: 100, color: Colors.blue),
      Container(width: 50, height: 100, color: Colors.black),
    ],
  ),
),

说明: 这个属性主要是控制Row的宽度,设置max,则Row的宽度会尽可能的大,和父组件有一样大,如果设置min,则Row只会包裹子组件的大小。

4. 文本方向:textDirection

控制子组件的排列方向(从左到右或从右到左):

Row(
  textDirection: TextDirection.rtl, // 从右到左排列
  children: [Text("A"), Text("B")],
)

5. 垂直方向:verticalDirection

控制子组件在交叉轴的排列方向(默认 VerticalDirection.down,从上到下):

Row(
  verticalDirection: VerticalDirection.up, // 从下到上排列
  children: [Container(height: 50), Container(height: 100)],
)

三、动态空间分配(Expanded与Flexible)

当需要子组件按比例分配剩余空间时,使用 ExpandedFlexible

1. Expanded

强制子组件填满剩余空间,通过 flex 设置权重(默认1):

Row(
  children: [
    Expanded(flex: 2, child: Container(color: Colors.red)),
    Expanded(flex: 1, child: Container(color: Colors.blue)),
  ],
)

上述代码中,红色容器占2/3宽度,蓝色占1/3。

2. Flexible

Expanded 类似,但允许子组件不填满剩余空间(通过 fit 属性控制):

Row(
  children: [
    Flexible(fit: FlexFit.loose, child: Container(width: 100)),
    Expanded(child: Container(color: Colors.green)),
  ],
)

四、处理溢出问题

当子组件总宽度超过屏幕宽度时,Row 会抛出溢出错误(如 Right Overflowed by 42 pixels)。

解决方案

  • 方案1:使用 SingleChildScrollView 包裹 Row,实现水平滚动:
SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  child: Row(children: [/* 长内容 */]),
)
  • 方案2:用 ListView 替代 Row
ListView.separated(
  scrollDirection: Axis.horizontal,
  itemBuilder: (_, i) => ItemWidget(),
  separatorBuilder: (_, __) => SizedBox(width: 10),
  itemCount: 10,
)
  • 方案3:通过 ExpandedFlexible 限制子组件宽度比例。

五、常见布局示例

示例1:图标与文本居中排列

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Icon(Icons.access_time),
    SizedBox(width: 8),
    Text("时间"),
  ],
)

示例2:按钮组右对齐

Row(
  mainAxisAlignment: MainAxisAlignment.end,
  children: [
    ElevatedButton(onPressed: () {}, child: Text("取消")),
    SizedBox(width: 10),
    ElevatedButton(onPressed: () {}, child: Text("确定")),
  ],
)

示例3:自适应三栏布局

Row(
  children: [
    Expanded(flex: 1, child: Sidebar()),
    Expanded(flex: 3, child: Content()),
    Expanded(flex: 1, child: Ads()),
  ],
)

六、注意事项

  1. 避免直接嵌套无约束组件:如 TextImage 可能导致溢出,应包裹 ExpandedContainer
  2. 优先使用 Expanded:需要动态分配空间时,优先选择 Expanded 而非固定宽度。
  3. 处理长内容:横向内容过长时,务必使用可滚动组件(如 ListView)。

通过灵活调整 mainAxisAlignmentcrossAxisAlignment 和子组件的尺寸,可以快速实现复杂的横向布局结构。若需滚动,务必结合可滚动组件(如 SingleChildScrollView)使用。