Flutter 从入门到精通(水)

216 阅读2分钟

第4章:布局与样式系统

Flutter 中一切皆是 Widget,而布局的核心在于理解“盒模型”和“约束系统”。掌握这些,可以构建出结构清晰、样式统一、适配良好的界面。


一、Flutter 的盒模型与布局约束机制

🔹 Flutter 的布局规则:

  1. 父组件向子组件 传递约束(constraints);
  2. 子组件在这些约束内 决定自己的尺寸
  3. 子组件将尺寸反馈给父组件,父组件据此决定布局。

例如:Container(width: 100, height: 50) 会给子组件固定宽高的约束。

🔹 Flutter 中的盒模型:

类似前端 CSS,Flutter 的组件结构也具备:

  • Padding(内边距)
  • Margin(外边距)
  • Alignment(对齐方式)
  • Constraints(尺寸约束)

二、常用布局控制组件

1. Padding & Margin(内外边距)

Padding(
  padding: EdgeInsets.all(16.0),
  child: Text("Inside padding"),
)

Margin 不存在单独组件,可通过 Container 实现:

Container(
  margin: EdgeInsets.only(top: 20),
  child: Text("With margin"),
)

2. Align(对齐方式)

Align(
  alignment: Alignment.centerRight,
  child: Text("Aligned Text"),
)

常见对齐位置有:topLeftcenterbottomRight 等。


3. Expanded(自适应空间填充)

Row(
  children: [
    Expanded(child: Container(color: Colors.blue, height: 50)),
    Container(width: 50, color: Colors.red),
  ],
)

Expanded 用于在 RowColumn 中按比例占满空间。


三、自定义样式与主题(Theme)

使用全局 Theme 控制字体、颜色、按钮等样式统一风格。

示例:配置全局主题

MaterialApp(
  theme: ThemeData(
    primarySwatch: Colors.teal,
    textTheme: TextTheme(
      bodyMedium: TextStyle(fontSize: 16),
    ),
  ),
  home: MyHomePage(),
)

获取当前主题样式

Text(
  "Title",
  style: Theme.of(context).textTheme.titleLarge,
)

四、响应式设计:MediaQuery & LayoutBuilder

1. MediaQuery(设备信息)

double screenWidth = MediaQuery.of(context).size.width;

可获取屏幕宽高、系统字体缩放、设备方向等。


2. LayoutBuilder(根据布局环境动态构建)

LayoutBuilder(
  builder: (context, constraints) {
    if (constraints.maxWidth < 600) {
      return Text("手机布局");
    } else {
      return Text("平板/桌面布局");
    }
  },
)

用于实现响应式布局切换,常用于平板或 Web 端适配。


五、常见问题解析

❗ 问题 1:布局不生效的原因

常见症状:
  • Container 无显示
  • 设置宽高无效
  • 对齐方式不起作用
常见原因:
  • 子组件尺寸未明确,未受到有效约束
  • 忘记设置 ExpandedFlexible
  • 忘记指定父布局(如 Row/Column/Stack)
示例:
// 错误示例:Text 不换行溢出
Container(
  width: 100,
  child: Text('这是一段非常长的文字内容这是一段非常长的文字内容'),
)
// 正确:
Container(
  width: 100,
  child: Text(
    '这是一段非常长的文字内容',
    softWrap: true,
    overflow: TextOverflow.ellipsis,
  ),
)

❗ 问题 2:Expanded 与 Flexible 的区别

特性ExpandedFlexible
自动占满剩余空间✅ 是❌ 不是(需设置 fit
控制占比❌ 固定平分(或通过 flex✅ 可以更灵活控制
常用场景简单平分布局自定义占比、复杂嵌套结构
示例:
// Expanded 平分剩余空间
Row(
  children: [
    Expanded(child: Container(color: Colors.blue)),
    Expanded(child: Container(color: Colors.green)),
  ],
)

// Flexible 可控制是否占满空间
Flexible(
  flex: 2,
  fit: FlexFit.tight, // 紧凑占满
  child: Container(color: Colors.orange),
)