Flutter 布局核心:构建交互式文档应用
项目概览 该项目创建了一个名为 "Flutter 布局核心文档" 的应用。它利用
ListView和ExpansionTile构建了一个可滚动、可折叠的文档查阅界面。
核心功能:
- 界面结构: 使用
Scaffold提供基础页面结构,AppBar显示标题。 - 内容展示: 使用
ListView包含多个Card组件。 - 交互效果: 使用
ExpansionTile实现点击标题展开/折叠详细内容的效果。 - 数据模拟: 通过常量字符串(
const)模拟 Markdown 文本内容,分为四个核心章节。
完整效果

成功运行效果

完整代码展示
dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter 布局组件详解',
theme: ThemeData(
primarySwatch: Colors.blue,
fontFamily: 'Roboto',
),
home: const DocsPage(),
debugShowCheckedModeBanner: false,
);
}
}
class DocsPage extends StatelessWidget {
const DocsPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter 布局核心文档'),
centerTitle: true,
),
body: ListView(
padding: const EdgeInsets.all(16.0),
children: const [
// 文档 1: Row 与 Column 核心
DocCard(
title: "1. 核心基石:主轴与交叉轴",
content: kRowColumnConcepts,
),
SizedBox(height: 16),
// 文档 2: 对齐方式
DocCard(
title: "2. 对齐的艺术:mainAxisAlignment 与 crossAxisAlignment",
content: kAxisAlignmentGuide,
),
SizedBox(height: 16),
// 文档 3: Expanded vs Flexible
DocCard(
title: "3. 弹性空间:Expanded 与 Flexible 的深度辨析",
content: kExpandedFlexibleGuide,
),
SizedBox(height: 16),
// 文档 4: 实战代码
DocCard(
title: "4. 完整布局代码示例",
content: kFullCodeExample,
),
],
),
);
}
}
// 单独的 Widget 类,用于复用卡片样式
class DocCard extends StatelessWidget {
final String title;
final String content;
const DocCard({super.key, required this.title, required this.content});
@override
Widget build(BuildContext context) {
return Card(
elevation: 4,
child: ExpansionTile(
title: Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
content,
style: const TextStyle(height: 1.7),
),
),
],
),
);
}
}
// ******************************************
// 以下为文档内容常量 (模拟 Markdown 文本)
// ******************************************
// 1. Row 与 Column 概念
const kRowColumnConcepts = '''
在 Flutter 中,Row 和 Column 是最基础的布局组件。
主轴 (Main Axis)
- Row:水平方向(从左到右)。
- Column:垂直方向(从上到下)。
交叉轴 (Cross Axis)
- Row:垂直方向。
- Column:水平方向。
约束行为(关键)
- Row:给子组件的**水平约束是无限的**,垂直约束是紧致的。
- Column:给子组件的**垂直约束是无限的**,水平约束是紧致的。
避坑
在 Row 中,子组件不能直接设置 width: double.infinity,会报错。因为父级给的是"无限"约束,无法计算"撑满"。解决方法:使用 Expanded。
''';
// 2. 对齐方式
const kAxisAlignmentGuide = '''
这两个属性控制子组件的排列和对齐。
mainAxisAlignment (主轴对齐)
控制子组件在主轴上的分布:
- start / end:靠起点/终点。
- center:居中。
- spaceBetween:两端对齐,中间均匀分布(常用于导航栏)。
- spaceAround:每个子项周围留有相等空间。
crossAxisAlignment (交叉轴对齐)
控制子组件在交叉轴上的对齐:
- start / end / center:顾名思义。
- stretch:默认值。强制子组件拉伸填满交叉轴。
注意:在 Column 中,Text 默认会拉伸占满全屏宽度。如不需要,请设置为 start。*
''';
// 3. Expanded vs Flexible
const kExpandedFlexibleGuide = '''
Expanded:强制填满
- 本质:Flexible(fit: FlexFit.tight)。
- 行为:强制子组件填满分配的空间。
- 无视子组件原本设置的宽高。
- 适用场景:严格按比例分配空间,或强制撑满剩余区域。
Flexible:灵活收缩
- 本质:fit: FlexFit.loose。
- 行为:允许子组件根据内容决定大小。
- 如果有多余空间,它可以利用;如果没有,它只包裹内容。
- 适用场景:子组件有固定内容大小,但希望在大屏上能变宽。
总结
如果子组件有固定尺寸,Expanded 会强制拉伸覆盖,而 Flexible 会优先尊重该尺寸。
''';
// 4. 代码示例
const kFullCodeExample = '''
// Row 示例:水平排列
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(color: Colors.red, width: 50, height: 50),
Container(color: Colors.green, width: 50, height: 50),
Container(color: Colors.blue, width: 50, height: 50),
],
)
// Column 示例:垂直排列
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(color: Colors.purple, height: 40),
Container(color: Colors.orange, height: 80),
],
)
// Expanded 示例:强制填满
Row(
children: [
Container(color: Colors.grey, width: 40),
Expanded( // 占据剩余所有空间
flex: 2,
child: Container(color: Colors.red),
),
Expanded( // 按比例 (1:2)
flex: 1,
child: Container(color: Colors.blue),
),
],
)
''';
⚙️ 核心代码详细解析
代码结构非常清晰,主要分为三个部分:主入口与页面构建 、复用组件 、数据常量。
1. 主入口与页面结构 (main.dart)
这是应用的骨架,负责初始化应用并构建页面的整体视觉。
dart
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
// ... (Standard MaterialApp setup)
// 设置应用标题、主题,并指定首页为 DocsPage
}
class DocsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter 布局核心文档'),
centerTitle: true, // 标题居中
),
body: ListView(
padding: const EdgeInsets.all(16.0), // 列表内边距
children: const [
// 通过自定义组件 DocCard 构建四个文档卡片
DocCard(title: "1. 核心基石...", content: kRowColumnConcepts),
SizedBox(height: 16), // 间距
DocCard(title: "2. 对齐的艺术...", content: kAxisAlignmentGuide),
// ... 其他卡片
],
),
);
}
}

关键点分析:
ListView: 由于文档内容较多,使用ListView确保页面可以滚动。SizedBox: 在卡片之间插入空的SizedBox是 Flutter 中控制间距的常用且高效的方式。const构造函数: 在children列表和Text组件中广泛使用const,这有助于编译器优化性能,因为这些 widget 的属性在编译时就已经确定了。
2. 可复用的卡片组件 (DocCard)
这是一个封装良好的原子组件,用于统一管理所有文档卡片的样式,体现组件化思想。
dart
class DocCard extends StatelessWidget {
final String title; // 标题
final String content; // 正文内容
const DocCard({super.key, required this.title, required this.content});
@override
Widget build(BuildContext context) {
return Card(
elevation: 4, // 阴影深度,增加立体感
child: ExpansionTile(
title: Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
children: [
Padding(
padding: const EdgeInsets.all(16.0), // 内容内边距
child: Text(
content,
style: const TextStyle(height: 1.7), // 行高,提升阅读体验
),
),
],
),
);
}
}

关键点分析:
Card: 提供了 Material Design 风格的卡片容器,带有圆角和阴影(elevation)。ExpansionTile: 这是核心交互组件。它默认只显示标题,点击后展开显示children中的内容。非常适合用于 FAQ 或详细文档展示。Padding: 在展开的内容区域添加内边距,防止文字紧贴卡片边缘。
3. 模拟数据常量
这部分定义了展示在 ExpansionTile 中的具体文本内容。
dart
// ******************************************
// 以下为文档内容常量 (模拟 Markdown 文本)
// ******************************************
const kRowColumnConcepts = '''
在 Flutter 中,Row 和 Column 是最基础的布局组件。
...
''';
const kFullCodeExample = '''
// Row 示例:水平排列
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
...
}
''';

内容特点:
- 使用 Dart 的多行字符串(三个单引号
''')来存储格式化文本。 - 内容涵盖了 Row/Column 原理 、对齐方式 (
MainAxisAlignment/CrossAxisAlignment)、弹性组件辨析 (ExpandedvsFlexible) 以及 实战代码。
📊 代码逻辑与布局原理总结
这段代码本身就是一个关于布局的教学示例,它巧妙地运用了 Flutter 的核心布局原理:
| 原理 | 在代码中的体现 | 说明 |
|---|---|---|
| 线性布局 (Row/Column) | ListView 是特殊的 Column |
ListView 本质上是一个可滚动的 Column。代码中 ListView 的子项(DocCard 和 SizedBox)是沿着垂直方向(主轴)排列的。 |
| 对齐方式 (Alignment) | mainAxisAlignment & crossAxisAlignment |
虽然代码中没有直接展示调节对齐的滑块,但常量 kAxisAlignmentGuide 中详细解释了如何使用 center、spaceBetween 等属性。 |
| 弹性布局 (Flex) | Expanded & Flexible |
在 kExpandedFlexibleGuide 中深入讲解了这两个组件。虽然主 UI 代码中未强制使用 Expanded(因为 ExpansionTile 高度自适应),但在示例代码字符串中展示了它们的用法。 |
| 盒模型 (Box Model) | Padding & EdgeInsets |
在 DocCard 的展开内容中使用了 Padding,这是 Flutter 盒模型的基础,用于控制元素内部空间。 |
💡 总结与结尾
总结:
这段代码展示了一个结构优良的 Flutter 应用架构。
- 分层清晰: 将 UI 结构(
DocsPage)与视觉样式(DocCard)分离,便于维护。 - 性能优化: 大量使用
const关键字,体现了对性能细节的关注。 - 用户体验: 通过
ExpansionTile折叠长文内容,避免了首屏信息过载,配合Card的阴影效果,提供了良好的视觉层级。
🌐 加入社区
欢迎加入 开源鸿蒙跨平台开发者社区 ,获取最新资源与技术支持:
技术因分享而进步,生态因共建而繁荣 。
------ 晚霞的不甘 · 与您共赴鸿蒙跨平台开发之旅