文章目录
前言
上一篇我们迎来了 Flutter 第一个项目,代码已经出现了几个常用组件 MaterialApp、Scaffold ,我们再多认识一个Container(类似html中的 div,万金油般的存在),它们是三个不同层级和用途的 Widget
dart
...
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Container(
width: 100,
height: 100,
color: Colors.blue,
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(20),
child: Text('内容'),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
...
MaterialApp - 应用级根组件
dart
MaterialApp(
title: 'My App',
home: MyHomePage(),
theme: ThemeData(primarySwatch: Colors.blue),
)
- 层级最高:通常是整个应用的入口 Widget
- 功能:
- 提供 Material Design 应用框架
- 管理应用级的配置(路由、主题、本地化等)
- 包裹整个应用的内容
- 提供 Navigator 用于页面导航
Scaffold - 页面骨架
dart
Scaffold(
appBar: AppBar(title: Text('主页')),
body: Container(color: Colors.red),
drawer: Drawer(),
floatingActionButton: FloatingActionButton(onPressed: () {}),
)
- 层级居中:通常作为单个页面的容器
- 功能:
- 提供 Material Design 页面的基本布局结构
- 包含 appBar、body、drawer、bottomNavigationBar 等标准区域
- 处理状态栏、键盘遮挡等系统交互
Container - 通用布局容器
dart
Container(
width: 100,
height: 100,
color: Colors.blue,
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(20),
child: Text('内容'),
)
- 层级最低:用于布局和样式的通用容器
- 功能:
- 控制子 Widget 的尺寸、间距、对齐等
- 可以设置装饰(颜色、边框、阴影等)
- 非常灵活,几乎可以包裹任何 Widget
关系对比
| 特性 | MaterialApp | Scaffold | Container |
|---|---|---|---|
| 层级 | 最高(应用级) | 中间(页面级) | 最低(组件级) |
| 用途 | 应用框架 | 页面骨架 | 布局容器 |
| Material Design | 必需 | 可选 | 无关 |
| 包含关系 | 包含 Scaffold | 包含 Container | 被包含 |
| 典型使用 | 应用入口 | 页面结构 | 布局控制 |
典型嵌套结构
dart
void main() {
runApp(
MaterialApp( // 1. 应用框架
home: Scaffold( // 2. 页面骨架
body: Container( // 3. 布局容器
child: Text('Hello World'),
),
),
),
);
}
简单记忆:MaterialApp 是整本书,Scaffold 是书中的一页,Container 是页面上的一个段落框。
页面数量与组件关系
dart
void main() {
runApp(
MaterialApp( // ← 只有一个
home: HomePage(), // ← 第一个页面
routes: {
'/detail': (context) => DetailPage(), // ← 第二个页面
'/profile': (context) => ProfilePage(), // ← 第三个页面
},
),
);
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold( // ← 第一个 Scaffold
body: Container( // ← 第一个页面的 Container
child: Text('首页'),
),
);
}
}
class DetailPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold( // ← 第二个 Scaffold
body: Container( // ← 第二个页面的 Container
child: Text('详情页'),
),
);
}
}
数量对比
| 组件 | 数量 | 说明 |
|---|---|---|
| MaterialApp | 1个 | 整个应用只需要一个 |
| Scaffold | 每个页面一个 | 每个独立页面通常有自己的 Scaffold |
| Container | N个 | 每个页面中可能有多个 Container |
典型多页面结构
dart
MaterialApp (1个)
├── HomePage (页面1)
│ ├── Scaffold (第1个)
│ │ ├── Container (可能多个)
│ │ ├── Container
│ │ └── ...
│ └── ...
├── DetailPage (页面2)
│ ├── Scaffold (第2个)
│ │ ├── Container (可能多个)
│ │ └── ...
│ └── ...
└── ProfilePage (页面3)
├── Scaffold (第3个)
│ ├── Container (可能多个)
│ └── ...
└── ...
实际场景示例
MaterialApp 的独特性
dart
// 整个应用只有一个 MaterialApp
void main() {
runApp(
MaterialApp( // ← 这是唯一的 MaterialApp
title: '多页面应用',
initialRoute: '/',
routes: {
'/': (context) => HomePage(),
'/list': (context) => ListPage(),
'/detail': (context) => DetailPage(),
},
),
);
}
每个页面的 Scaffold
dart
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold( // ← HomePage 的 Scaffold
appBar: AppBar(title: Text('首页')),
body: Center(child: Text('首页内容')),
);
}
}
class ListPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold( // ← ListPage 的 Scaffold
appBar: AppBar(title: Text('列表页')),
body: ListView.builder(itemBuilder: ...),
);
}
}
Container 的数量不确定性
dart
class DetailPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Container( // ← 第1个 Container
padding: EdgeInsets.all(16),
child: Text('标题'),
),
Container( // ← 第2个 Container
margin: EdgeInsets.all(8),
child: Image.network('...'),
),
Container( // ← 第3个 Container
padding: EdgeInsets.all(16),
child: Text('描述'),
),
],
),
);
}
}
重要注意事项
-
MaterialApp 必须唯一
- 整个应用只能有一个
MaterialApp - 如果需要嵌套(如在一个应用中嵌入另一个应用),应使用
WidgetsApp
- 整个应用只能有一个
-
Scaffold 通常每页一个
- 大多数页面使用一个
Scaffold作为根 - 但也可以没有
Scaffold(如全屏对话框、透明页面)
- 大多数页面使用一个
-
Container 随意使用
- 一个页面中可以有任意数量的
Container - 甚至可以嵌套多个
Container
- 一个页面中可以有任意数量的
总结
| 组件 | 数量规律 | 比喻 |
|---|---|---|
| MaterialApp | 唯一(整个应用1个) | 整栋大楼的建筑图纸 |
| Scaffold | 每个页面通常1个 | 每个房间的框架结构 |
| Container | 任意数量(一个页面多个) | 房间里的各种家具/箱子 |
这种设计让 Flutter 保持了清晰的层级关系:一个应用框架(MaterialApp)管理多个页面结构(Scaffold),每个页面中包含多个布局容器(Container)。