一.基础组件1.MaterialApp常见属性: title theme hometitle: 用来展示窗口的标题内容(可以不设置)theme: 用来设置整个应用的主题home: 用来展示窗口的主体内容void main(List<String> args) { runApp( MaterialApp( title: "Flutter组件初体验", theme: ThemeData(scaffoldBackgroundColor: Colors.greenAccent), home: Scaffold(), ), ); }2.Scaffold用于构建MaterialDesign风格页面的核心布局组件，提供标准、灵活配置的页面骨架属性主要作用说明appBar页面顶部的应用栏，通常用于显示标题、导航按钮和操作菜单body页面的主要内容区域，可以放置任何其他组件，是页面的核心bottomNavigationBar底部导航栏，方便用户在不同核心功能页面间切换backgroungColor设置整个Scaffold的背景颜色floatingActionButton悬浮操作按钮，常用于触发页面的主要动作...其他void main(List<String> args) { runApp( MaterialApp( title: "Flutter组件初体验", theme: ThemeData(scaffoldBackgroundColor: Colors.greenAccent), home: Scaffold( appBar: AppBar( title: Text("头部区域"), centerTitle: true ), body: Container( child: Center( child: Text("中间区域") ) ), bottomNavigationBar: Container( height: 80, child: Center( child: Text("底部区域") ), ), ), ), ); }二.自定义组件定义：根据自己特定的需求创建自己的widget分类：Flutter分为无状态组件和有状态组件特性StatelessWidget(无状态)StatefulWidget(有状态)核心特征一旦创建，内部状态不可变持有可在其生命周期内改变的状态使用场景静态内容展示，外观仅由配置参数决定交互式组件，如计数器、可切换开关、表单输入框生命周期相对简单，主要是构建（build)更为复杂，包含状态创建、更新和销毁代码结构单个类两个关联的类：Widget 本身和单独的 State类1.无状态组件定义：创建一个新的类，继承StatelessWidget类并实现build方法要点：build返回一个widget场景：纯展示型组件，没有用户交互操作需求：把之前案例的骨架换成无状态组件void main(List<String> args) { runApp(MainPage()); } // 无状态组件 自定义组件中的一种 class MainPage extends StatelessWidget { @override Widget build(BuildContext context) { return Container(); } }2.有状态组件定义：有状态组件是构建动态交互界面的核心，能够管理变化的内部状态，当状态改变时，组件会更新显示内容实现1：创建两个类，第一个类继承Statefulwidget类，主要接收和定义最终参数，核心作用是创建State对象实现2：第二个类继承State<第一个类名>，负责管理所有可变的数据和业务逻辑，并实现build构建方法要点：build方法需要返回一个Widget需求：将之前骨架组件换成有状态组件// 有状态组件 第一个类 对外 class MainPage extends StatefulWidget { @override State<StatefulWidget> createState() { // return 第二个类 return _MainPageState(); } } // 有状态组件 第二个类 内部类 负责管理数据 处理业务逻辑 并且渲染视图 class _MainPageState extends State<MainPage> { @override Widget build(Object context) { return Container(); } }三.生命周期1.无状态组件生命周期无状态组件-唯一阶段build方法当组件被创建或父组件状态变化导致其需要重新构建时，build方法会被调用class MainPage extends StatelessWidget { const MainPage({super.key}); @override Widget build(BuildContext context) { print("无状态组件构建执行..."); return Container(); } }2.有状态组件生命周期有状态组件-三个阶段1.创建阶段Statefulwidget被创建 -> createState -> State对象创建 -> initState -> didChangeDependencies -> build2.更新阶段父组件重建-配置变更 -> didUpdateWidget -> build3.销毁阶段组件被移除 -> deactivate -> dispose生命周期阶段函数名调用时机与核心任务创建阶段createState()Widget 初始化时调用，创建 State 对象创建阶段initState()State 对象插入 Widget 树后立刻执行，仅执行一次创建阶段didChangeDependencies()initState 后立刻执行，当依赖的 InheritedWidget 更新时调用，可能多次构建与更新阶段build()构建 UI 的方法，在初始化或更新后多次调用构建与更新阶段didUpdateWidget()父组件传入新配置时调用，用于比较新旧配置销毁阶段deactivate()当 State 对象从树中暂时移除时调用销毁阶段dispose()当 State 对象被永久移除时调用，释放资源，仅执行一次class MainPage extends StatefulWidget { const MainPage({super.key}); // 创建阶段 @override State<MainPage> createState(){ print("1.createState阶段执行"); return _MainPageState(); } } class _MainPageState extends State<MainPage> { @override void initState() { print("2.initState阶段执行"); super.initState(); } @override void didChangeDependencies() { print("3.didChangeDependencies阶段执行"); super.didChangeDependencies(); } // 更新阶段 @override Widget build(BuildContext context) { print("4.build阶段执行"); return Container(); } @override void didUpdateWidget(covariant MainPage oldWidget) { print("5.didUpdateWidget阶段执行"); super.didUpdateWidget(oldWidget); } // 销毁阶段 @override void deactivate() { print("6.deactivate阶段执行"); super.deactivate(); } @override void dispose() { print("7.dispose阶段执行"); super.dispose(); } }3.生命周期总结无状态组件（StatelessWidget）仅执行 build 方法有状态组件（StatefulWidget）1.创建阶段: createState() -> initState -> didChangeDependencies -> build2.更新阶段: didUpdateWidget -> build3.销毁阶段: deactivate -> dispose仅执行一次的函数: createState、initState、disposeInheritedWidget: 专门用于在Widget树中自顶向下高效共享数据, 顶层组件提供数据, 子孙节点直接获取。四.事件1.点击事件GestureDetector事件：用户与应用程序交互时触发的各种动作，比如触摸屏幕、滑动、点击等点击事件：当点击某个元素触发的动作常规方案：GestureDetector 是 Flutter 中最常用、功能最丰富的手势检测组件。// 有状态组件 MaterialApp( home: Scaffold( body: Container( child: Center( child: GestureDetector( // 点击事件 onTap: () { print("点击了该区域"); }, // 双击事件 onDoubleTap: () { print("双击了该区域"); }, child: Text("中间区域"), ) ) ), ) );2.组件点击事件Flutter 提供了多种方式为组件添加点击交互。组件类别核心组件主要特点 / 使用场景专用按钮组件ElevatedButton、TextButton、OutlineButton、FloatingActionButton内置点击动画和样式，通过 onPressed 参数处理点击逻辑视觉反馈组件InkWell提供点击事件（onTap），有 Material Design 风格的水纹扩散效果其他交互组件IconButton、Switch、Checkbox具有特定功能的交互式控件，点击事件（onPressed）// 有状态组件 MaterialApp( home: Scaffold( body: Container( child: Center( child: TextButton(onPressed:() { print("点击了按钮"); }, child: Text("按钮")), ) ), ) );五.状态更新-setState场景：计数器，点击 + 进行数量 +1，点击 - 进行数量 -1，UI 视图需要进行相应更新语法：数据的变化要更新 UI 视图，需要执行 setState 方法，setState 方法会造成 build 的重新执行。实现计数器示例：// 有状态组件 class _MainPageState extends State<MainPage> { int count = 0; // 状态变量 @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: Row( children: [ TextButton(onPressed: () { setState(() { count--; }); }, child: Text("减")), Text("$count"), TextButton(onPressed: () { count++; setState(() { // 只要执行了setState()方法，就会重新执行build方法 }); }, child: Text("加")), ], ), ), ), ); } }六.Flutter组件布局组件-介绍Flutter 提供了丰富强大的布局组件来构建各种用户界面。下面这个表格汇总了最核心的几类布局组件。组件类别核心组件主要特点 / 使用场景基础容器Container、Center、Align、Padding提供装饰、对齐、边距等基础样式和布局控制，是使用频率极高的组件线性布局Row、Column在水平或垂直方向线性排列子组件，是构建界面的基础弹性布局Flex、Expanded、Flexible按照比例分配剩余空间，实现自适应布局，常与 Row 和 Column 配合使用层叠布局Stack、Positioned让子组件重叠堆叠，用于实现如图片上叠加文字、悬浮按钮等效果流式布局Wrap、Flow当主轴空间不足时自动换行或换列，常用于标签、滤镜等动态宽高内容的排列滚动布局ListView、GridView提供可滚动的列表或网格视图，高效展示大量数据1.基础容器Container-容器组件定义：Container 是功能丰富的布局组件，是一个多功能组合容器尺寸控制：可通过多种方式定义大小，有明确优先级规则优先级：明确宽高 > constraints 约束 > 父组件约束 > 自适应组件大小装饰系统：通过 decoration 属性实现视觉效果，但和 color 属性互斥布局控制：提供内外边距和对齐方式可选变化：支持绘制时进行矩阵变换，如旋转、倾斜、平移等Container 常用属性属性类别关键属性作用说明布局定位alignment控制其 child（子组件）在容器内部的对齐方式。例如：Alignment.center（居中）、Alignment.topLeft（左上角）尺寸控制width / height / constraints设置容器的宽度和高度 / 为容器设置更复杂的尺寸约束（如最小/最大宽高）间距留白padding / margin按照比例分配剩余空间，实现自适应布局，常与 Row 和 Column 配合使用装饰效果color / decoration为容器设置一个简单的背景颜色 / 为容器设置复杂的背景装饰变换效果transform对容器及其内容进行矩阵变换子组件child容器内包含的唯一直接子组件代码示例：MaterialApp( home: Scaffold( body: Container( transform: Matrix4.rotationZ(0.05), // 旋转 alignment: Alignment.center, // 居中 width: 200, height: 200, margin: EdgeInsets.all(20), // 外边距 // color: Colors.blueAccent, // 简单的背景与颜色 decoration: BoxDecoration( color: Colors.blueAccent, borderRadius: BorderRadius.circular(15), // 圆角 border: Border.all(width: 5, color: Colors.amber), ), child: Center( child: Text( "Hello Container", style: TextStyle(fontSize: 20, color: Colors.white), ), ), ), ), );Center-居中组件作用：将其子组件在父容器空间内进行水平和垂直方向上的居中排列应用场景：页面内容整体居中，如将一个登录表单或一个加载中的提示图标在页面正中显示注意事项：Center 自身不能设置宽高，其最终大小取决于父组件传递的约束Center 会向父组件申请尽可能大的空间实现固定宽高且居中的组件：用 Center 包裹一个具有固定宽高的子组件（如 Container / SizedBox）代码示例:MaterialApp( home: Scaffold( appBar: AppBar(title: Text("Center代码示例"), centerTitle: true), body: Center( child: Container( width: 100, height: 100, color: Colors.cyan, child: Center(child: Text("居中内容")), ), ), ), );Align-对齐组件作用：精确控制其子组件在父容器空间内的对齐位置alignment（对齐方式）：子组件在父容器内的对齐方式widthFactor（宽度因子）：Align 的宽度将是子组件宽度乘以该因子heightFactor（高度因子）：Align 的高度将是子组件高度乘以该因子代码示例:MaterialApp( home: Scaffold( appBar: AppBar(title: Text("Align代码示例"), centerTitle: true), body: Container( color: Colors.blue, child: Align( alignment: Alignment.center, // 对其方式 // widthFactor: 3, // Align的宽度是子图标宽度的3倍 // heightFactor: 3, // Align的高度是子图标高度的3倍 child: Icon(Icons.star, size: 150, color: Colors.yellow), ), ), ), );与 Center 的区别：Center 是 Align 的一个特例，继承自 Align，相当于将 alignment 属性固定为 Alignment.center 的 Align。使用场景：当需要将一个组件放置在父容器的特定角落时，Align 是理想选择。动态尺寸：通过 widthFactor 和 heightFactor，可以创建出与子组件大小成比例的容器，在动态布局中很有用。Padding-内边距组件作用：为其子组件添加内边距属性类型作用说明paddingEdgeInsetsGeometry必需。定义内边距的大小和方向，通常使用 EdgeInsets 类来设置childWidget需要被添加内边距的子组件四个方向设置相同间距：使用 EdgeInsets.all 进行四个方向统一设置四个方向设置不同间距：使用 EdgeInsets.only 进行四个方向分别设置设置对称方向的内边距: 使用 EdgeInsets.symmetric 进行设置代码示例:MaterialApp( home: Scaffold( appBar: AppBar(title: Text("Padding代码示例"), centerTitle: true), body: Container( // padding: EdgeInsets.all(20), // 属性 decoration: BoxDecoration(color: Colors.amber), child: Padding( // 容器 // padding: EdgeInsets.all(20), // 上下左右的四个内边距 // padding: EdgeInsets.only(left: 20, right: 20, top: 20, bottom: 20), // 单独设置上下左右 padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20), // 对称方向 child: Container(color: Colors.blue), ), ), ), );Padding 总结特点：功能单一而纯粹，就是添加内边距。如果需求仅是为组件添加间距，那么直接使用 Padding 组件区别：Container 也有 padding 属性；单一需求用 Padding 组件，复杂样式用 Container2.线性布局Column-垂直布局作用：用于垂直排列其子组件的核心布局容器。属性类型作用说明mainAxisAlignmentMainAxisAlignment控制子组件在主轴（垂直方向）上的排列方式，如顶部对齐、居中或均匀分布。crossAxisAlignmentCrossAxisAlignment控制子组件在交叉轴（水平方向）上的对齐方式，如左对齐、右对齐或拉伸填满。mainAxisSizeMainAxisSize决定 Column 本身在垂直方向上的尺寸策略：是占满所有可用空间（max），还是仅仅包裹子组件内容（min）。childrenList需要被垂直排列的子组件列表。代码示例:MaterialApp( home: Scaffold( appBar: AppBar(title: Text("Column代码示例"), centerTitle: true), body: Container( width: double.infinity, // 宽度尽可能占满父组件 decoration: BoxDecoration(color: Colors.amber), child: Column( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // 两头对齐 // mainAxisAlignment: MainAxisAlignment.spaceAround, // 环绕模式 // mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 环绕模式 // mainAxisAlignment: MainAxisAlignment.start, // 从头排列 // mainAxisAlignment: MainAxisAlignment.end, // 从尾排列 mainAxisAlignment: MainAxisAlignment.center, // 居中排列 // crossAxisAlignment: CrossAxisAlignment.start, // 交叉轴start // crossAxisAlignment: CrossAxisAlignment.center, // 交叉轴居中 // crossAxisAlignment: CrossAxisAlignment.end, // 交叉轴end crossAxisAlignment: CrossAxisAlignment.stretch, // 填充交叉轴 children: [ Container(width: 100, height: 100, color: Colors.blue), Container( margin: EdgeInsets.only(top: 10, bottom: 10), width: 100, height: 100, color: Colors.blue, ), Container(width: 100, height: 100, color: Colors.blue), ], ), ), ), );适用场景:几乎在所有需要垂直排列元素的界面中都能看到它的身影。表单：如登录页面的用户名输入框、密码输入框和登录按钮的垂直排列。设置列表：如设置页面中多个选项项的垂直堆叠。卡片布局：如新闻流中多个新闻卡片的垂直排列。图文混排：如商品详情页的图片、标题、描述和价格等信息从上到下的展示。注意事项:Column 本身不支持滚动；若内容超出，需用 ListView 或 SingleChildScrollView 包裹。明确尺寸约束：父组件的大小直接影响 Column 的最终尺寸及子组件的布局行为。避免过度嵌套：过深的嵌套会影响性能并增加代码维护难度。Row-水平布局作用：用于水平排列其子组件的核心布局容器。属性类型作用说明mainAxisAlignmentMainAxisAlignment控制子组件在主轴（水平方向）上的排列方式，如起始对齐、居中或均匀分布。crossAxisAlignmentCrossAxisAlignment控制子组件在交叉轴（垂直方向）上的对齐方式，如顶部对齐、底部对齐或拉伸填满。mainAxisSizeMainAxisSize决定 Row 本身在水平方向上的尺寸策略：占满所有可用空间（max）或仅包裹子组件内容（min）。childrenList需要被水平排列的子组件列表。代码示例:MaterialApp( home: Scaffold( appBar: AppBar(title: Text("Row代码示例"), centerTitle: true), body: Container( width: double.infinity, // 宽度尽可能占满父组件 height: double.infinity, // 高度尽可能占满父组件 decoration: BoxDecoration(color: Colors.amber), child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // 两头对齐 // mainAxisAlignment: MainAxisAlignment.spaceAround, // 环绕模式 // mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 环绕模式 // mainAxisAlignment: MainAxisAlignment.start, // 从头排列 // mainAxisAlignment: MainAxisAlignment.end, // 从尾排列 mainAxisAlignment: MainAxisAlignment.center, // 居中排列 // crossAxisAlignment: CrossAxisAlignment.start, // 交叉轴start // crossAxisAlignment: CrossAxisAlignment.center, // 交叉轴居中 // crossAxisAlignment: CrossAxisAlignment.end, // 交叉轴end // crossAxisAlignment: CrossAxisAlignment.stretch, // 填充交叉轴 children: [ Container(width: 100, height: 100, color: Colors.blue), Container( margin: EdgeInsets.only(left: 10, right: 10), // 注意:与Column不同 width: 100, height: 100, color: Colors.blue, ), Container(width: 100, height: 100, color: Colors.blue), ], ), ), ), );适用场景几乎所有需要水平排列元素的界面都能看到它的身影。导航栏：如顶部或底部的标签栏、按钮组。图文混排：如列表项左侧的图标与右侧的文本描述。表单行：如标签和输入框的组合。注意事项Row 本身不支持滚动；若内容超出，需用 ListView 或 SingleChildScrollView 包裹。明确尺寸约束：父组件的大小直接影响 Row 的最终尺寸及子组件的布局行为。3.弹性布局Flex-弹性布局作用：允许沿一个主轴（水平或垂直）排列其子组件，灵活地控制这些子组件在主轴上的尺寸比例和空间分配。属性类型作用说明directionAxis.horizontal 或 Axis.vertical主轴方向，决定子组件的排列方向。mainAxisAlignmentMainAxisAlignment子组件在主轴方向上的对齐方式。crossAxisAlignmentCrossAxisAlignment子组件在交叉轴方向上的对齐方式。mainAxisSizeMainAxisSizeFlex 容器自身在主轴上的尺寸策略。子组件：Flex的子组件常使用Expanded或Flexible来控制空间分配Flex是Column和Row的结合体Expanded/Flexible-弹性子组件Expanded/Flexible作为Flex的子组件通过flex属性来分配Flex组件空间布局约束：Flex 布局受父组件传递的约束影响，务必确保父组件提供了适当的布局约束。Expanded vs FlexibleExpanded：强制子组件填满所有剩余空间。Flexible：仅根据自身大小调整，不强制占满空间。代码示例:Flex( direction: Axis.horizontal, // 方向: 水平 children: [ Expanded( // Flexible // fit: FlexFit.tight, flex: 2, // 占2份 child: Container(color: Colors.red, height: 100, width: 100,), ), Expanded( // Flexible // fit: FlexFit.tight, flex: 1, // 占1份 child: Container(color: Colors.green, height: 100, width: 100,), ), ], )案例代码:Flex( direction: Axis.vertical, children: [ Container(color: Colors.blue, height: 100), Expanded( child: Container(color: Colors.grey), ), Container(color: Colors.red, height: 100), ], )4.流式布局Wrap-流式布局容器作用: 流式布局容器；当子组件在主轴方向排不下时，自动换行（或换列）。属性常用值作用说明directionAxis.horizontal / Axis.vertical主轴方向，即排列方向。spacing数值主轴方向上子组件之间的间距。runSpacing数值交叉轴方向上“行/列”之间的间距。alignmentWrapAlignment子组件在主轴方向上的对齐方式。runAlignmentWrapAlignment交叉轴方向上的对齐方式。注意: Column / Row / Flex 内容超出均不会换行。Wrap 可视为“带换行能力的 Flex”。代码示例:// 创建10个容器 List<Widget> getList() { return List.generate(10, (index) { return Container(width: 100, height: 100, color: Colors.blue); }); } Wrap( spacing: 10, // 主轴 runSpacing: 10, // 交叉轴 alignment: WrapAlignment.spaceBetween, // 主轴对齐方式 direction: Axis.horizontal, children: getList() // 创建10个容器 )5.层叠布局Stack/Positioned-层叠布局容器作用：层叠布局容器，允许多个子组件沿 Z 轴（深度方向）叠加排列。属性类型作用说明alignmentAlignmentGeometry控制非定位子组件在 Stack 内的对齐方式，默认左上角。fitStackFit控制非定位子组件如何适应 Stack 的尺寸。clipBehaviorClip控制子组件超出 Stack 边界时的裁剪方式。childrenList需要被层叠排列的子组件列表。黄金搭档：Positioned, 必须作为 Stack 的直接子组件。通过 left / right / top / bottom 四个属性将子组件“钉”在 Stack 的任意角落或边缘，实现精确定位。Stack基础用法:Stack( alignment: Alignment.center, // 对齐方式 children: [ Container(width: 300, height: 300, color: Colors.blue), Container(width: 200, height: 200, color: Colors.red), Container(width: 100, height: 100, color: Colors.amber), Container(width: 80, height: 80, color: Colors.green), ], )Positioned用法:Stack( children: [ Container(width: 300, height: 300, color: Colors.grey), Positioned( left: 10, top: 10, child: Container(width: 100, height: 100, color: Colors.red), ), Positioned( right: 10, bottom: 10, child: Container(width: 100, height: 100, color: Colors.blue), ), // Positioned( // left: 0, // right: 0, // top: 0, // bottom: 0, // 实现占满整个容器 // child: Container(width: 100, height: 100, color: Colors.green), // ) ], )适用场景: 几乎所有需要叠加效果的界面都能看到它的身影。叠加效果：图像上的水印、文本、徽章。浮层交互：模态对话框、提示弹窗、操作菜单。悬浮按钮：按钮悬浮在特定内容之上。注意事项层叠顺序由 children 列表中的先后顺序决定，后出现者居上。必须明确尺寸约束：父组件的大小直接影响 Stack 的最终尺寸及子组件的布局行为。6.滚动布局常用滚动组件组件特点典型使用场景SingleChildScrollView仅支持单个子组件滚动，内容一次性全部渲染。长表单、设置页、内容总量不多的页面。ListView线性列表；可通过 builder 实现懒加载，性能优异。聊天记录、新闻流、单列数据列表。GridView网格布局列表；支持懒加载，可固定列数。图片墙、商品网格、应用图标列表。CustomScrollView组合多个 Sliver 实现复杂滚动效果，布局灵活。电商首页、社交 App 个人主页、多区域联动滚动。PageView整页滚动，支持横向/纵向切换，自带页面指示器。应用引导页、图片轮播、电子书翻页。SingleChildScrollView-单子组件滚动用法：包裹一个子组件，让单个子组件具备滚动能力controller：给组件的controller绑定ScrollController对象只能包含一个子组件；若要滚动多个组件，通常将其嵌套在 Column 或 Row 中滚动方向：通过 scrollDirection 属性控制，默认为垂直方向（Axis.vertical），也可设置为水平方向（Axis.horizontal）特点：一次性构建所有子组件；若嵌套的 Column 或 Row 中包含大量子项，可能会导致性能问题，建议使用 ListView控制滚动：绑定一个 ScrollController 对象给 controller 属性，使用 animateTo / jumpTo 方法控制滚动滚动到顶部：controller.jumpTo(0)滚动到底部：controller.jumpTo(controller.position.maxScrollExtent)示例代码:class _MainPageState extends State<MainPage> { ScrollController _controller = ScrollController(); // 滚动控制器 @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text("登录"), centerTitle: true), body: Stack( children: [ SingleChildScrollView( controller: _controller, padding: EdgeInsets.all(20), child: Column( children: List.generate(100, (index) { return Container( margin: EdgeInsets.only(top: 10), width: double.infinity, height: 100, color: Colors.blue, child: Text( "我是第${index + 1}个", style: TextStyle(fontSize: 20, color: Colors.white), ), alignment: Alignment.center, ); }), ), ), Positioned( right: 10, top: 10, child: GestureDetector( onTap: () { // _controller.jumpTo(_controller.position.maxScrollExtent); // 直接跳转 _controller.animateTo( // 动画跳转 _controller.position.maxScrollExtent, duration: Duration(seconds: 1), curve: Curves.ease, ); }, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(40), color: Colors.red, ), width: 80, height: 80, alignment: Alignment.center, child: Text("去底部", style: TextStyle(color: Colors.white)), ), ), ), Positioned( right: 10, bottom: 10, child: GestureDetector( onTap: () { _controller.jumpTo(_controller.position.minScrollExtent); }, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(40), color: Colors.red, ), width: 80, height: 80, alignment: Alignment.center, child: Text("去顶部", style: TextStyle(color: Colors.white)), ), ), ), ], ), ), ); } }ListView-线性列表作用：用于构建可滚动列表的核心部件，并提供流畅滚动体验。方式：提供多种构造函数，如默认构造函数、ListView.builder、ListView.separated。机制：采用按需渲染（懒加载），只构建当前可见区域的列表项，极大提升长列表性能。默认构造函数ListView( children: List.generate(100, (index) { return Container( margin: EdgeInsets.only(top: 10), color: Colors.blue, width: double.infinity, height: 80, child: Text( "第${index + 1}个", style: TextStyle(fontSize: 30, color: Colors.white), ), alignment: Alignment.center, ); }), )builder模式作用：处理长列表或动态数据的首选和推荐方式。方式：接受一个 itemBuilder 回调函数来按需构建列表项，通过 itemCount 控制列表长度。ListView.builder( itemCount: 100, // 列表项的长度 itemBuilder: (BuildContext context, int index) { return Container( margin: EdgeInsets.only(top: 10), color: Colors.blue, width: double.infinity, height: 80, child: Text( "第${index + 1}个", style: TextStyle(fontSize: 30, color: Colors.white), ), alignment: Alignment.center, ); }, )separated模式作用：在 ListView.builder 的基础上，额外提供了构建分割线的能力。方式：需要同时提供 itemBuilder、separatorBuilder、itemCount 三个属性。ListView.separated( itemCount: 100, // 列表项的长度 itemBuilder: (BuildContext context, int index) { return Container( color: Colors.blue, width: double.infinity, height: 80, child: Text( "第${index + 1}个", style: TextStyle(fontSize: 30, color: Colors.white), ), alignment: Alignment.center, ); }, // 分割线 separatorBuilder: (context, index) { return Container(height: 5, color: Colors.red); }, )GridView-网格列表作用：用于创建二维可滚动网格布局的核心组件。方式：提供多种构建方式GridView 默认构造 —— 写法最繁琐，很少使用。GridView.count —— 基于固定列数的网格布局（最常用之一）。GridView.extent —— 基于固定子项最大宽度/高度的网格布局（最常用之二）。GridView.builder —— 用于网格项数量巨大或动态生成的情况，需接收 gridDelegate 布局委托属性。gridDelegateSliverGridDelegateWithFixedCrossAxisCount：固定列数，mainAxisSpacing 主轴间距。SliverGridDelegateWithMaxCrossAxisExtent：最大宽度，crossAxisSpacing 交叉轴间距。scrollDirection：设置滚动方向横向/纵向（默认纵向）。GridView.count构造作用：使用GridView.count创建固定列数网格Gridview.count以列数为优先。指定网格多少列，Flutter自动计算列的宽度，在空间内均匀排列GridView.count( scrollDirection: Axis.horizontal, // 横向滚动 padding: EdgeInsets.all(10), crossAxisCount: 3, // 设置固定的列数或者行数 mainAxisSpacing: 10, // 主轴间隔 crossAxisSpacing: 10, // 交叉轴间隔 children: List.generate(100, (index) { return Container( alignment: Alignment.center, color: Colors.blue, child: Text( "第${index + 1}个Item", style: TextStyle(color: Colors.white, fontSize: 20), ), ); }), )GridView.extent构造作用：使用GridView.extent指定子项最大宽度或者高度Gridview.extent通过maxCrossAxisExtent设置子项最大宽度或者高度来计算横向或者纵向的列数GridView.extent( maxCrossAxisExtent: 100, // 表示网格中每个子项的最大宽度为 100 像素 mainAxisSpacing: 10, // 主轴间隔 crossAxisSpacing: 10, // 交叉轴间隔 children: List.generate(100, (index) { return Container( alignment: Alignment.center, color: Colors.blue, child: Text( "第${index + 1}个", style: TextStyle(color: Colors.white, fontSize: 20), ), ); }), )GridView.builder构造作用：使用 GridView.builder 实现动态长网格（懒加载，仅渲染可见区域）。注意：需接收 gridDelegate 布局委托、itemBuilder 构建函数、itemCount 构建数量。GridView.builder( // 布局委托 // 按照最大宽度进行布局 gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 100, mainAxisSpacing: 10, crossAxisSpacing: 10, childAspectRatio: 1.5, // 宽高比 ), // 按照列数进行布局 // gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( // crossAxisCount: 4, // mainAxisSpacing: 10, // crossAxisSpacing: 10, // ), itemCount: 100, itemBuilder: (context, index) { return Container( alignment: Alignment.center, color: Colors.blue, child: Text( "第${index + 1}个", style: TextStyle(color: Colors.white, fontSize: 20), ), ); }, )CustomScrollView-自定义滚动作用：用于组合多个可滚动组件（如列表、网格），实现统一协调的滚动效果。sliver：Flutter 中描述可滚动视图内部一部分内容的组件，它是滚动视图的切片。用法：通过 slivers 属性接收一个 Sliver 组件列表。sliver 组件对应关系SliverList 对应 ListViewSliverGrid 对应 GridViewSliverAppBar 对应 AppBarSliverPadding 对应 PaddingSliverToBoxAdapter 对应 ToBoxAdapter（用于包裹普通 Widget）SliverPersistentHeader：粘性吸顶代码示例:CustomScrollView( slivers: [ // 切片列表 SliverToBoxAdapter( // 包裹普通的widget child: Container( color: Colors.blue, alignment: Alignment.center, height: 260, child: Text( "轮播图", style: TextStyle(color: Colors.white, fontSize: 20), ), ), ), SliverToBoxAdapter(child: SizedBox(height: 10)), SliverPersistentHeader( delegate: _StickyCategory(), // 吸顶组件 pinned: true, // 固定吸顶 ), SliverList.separated( itemCount: 100, itemBuilder: (context, index) { return Container( color: Colors.blue, alignment: Alignment.center, height: 100, child: Text( "商品$index", style: TextStyle(color: Colors.white, fontSize: 20), ), ); }, separatorBuilder: (context, index) { return SizedBox(height: 10); }, ), ], ) class _StickyCategory extends SliverPersistentHeaderDelegate { @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent,) { return Container( color: Colors.white, child: ListView.builder( itemCount: 30, scrollDirection: Axis.horizontal, itemBuilder: (context, index) { return Container( width: 100, margin: EdgeInsets.symmetric(horizontal: 10), color: Colors.blue, alignment: Alignment.center, child: Text("分类$index", style: TextStyle(color: Colors.white)), ); }, ), ); } @override // 最大展开高度 double get maxExtent => 100; @override // 最小折叠高度 double get minExtent => 60; @override bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { // 是否需要重新构建 return false; } }PageView-整页滚动作用：用于实现分页滚动视图的核心组件。方式：提供多种构建方式，如默认构造方式、PageView.builder 等。优势：支持懒加载（按需渲染）。*轮播图代码示例: class _MainPageState extends State<MainPage> { PageController _pageController = PageController(); // 页面控制器 int _currentIndex = 0; // 当前激活索引 @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: CustomScrollView( slivers: [ SliverToBoxAdapter( child: Stack( children: [ Container( color: Colors.blue, alignment: Alignment.center, height: 260, child: PageView.builder( controller: _pageController, // 页面控制器 itemCount: 10, itemBuilder: (context, index) { return Container( alignment: Alignment.center, child: Text( '轮播图$index', style: TextStyle(fontSize: 20, color: Colors.white), ), ); }, ), ), Positioned( bottom: 0, left: 0, right: 0, height: 20, child: Container( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(10, (index) { return GestureDetector( // 点击事件 onTap: () { // _pageController.jumpToPage(index); // 跳转到指定页面 _pageController.animateToPage( index, duration: Duration(milliseconds: 500), curve: Curves.ease, ); setState(() { _currentIndex = index; }); }, child: Container( margin: EdgeInsets.only(left: 5), width: 10, height: 10, decoration: BoxDecoration( color: _currentIndex == index ? Colors.red : Colors.white, borderRadius: BorderRadius.circular(5), ), ), ); }), ), ), ), ], ), ), ], ), ), ); } }7.其他Text-文本组件作用: 在用户界面中显示文本的基础组件。属性类型作用说明dataString必需。要显示的文本内容。styleTextStyle文本样式，可设置颜色、字号、字重等。textAlignTextAlign文本在自身容器内的水平对齐方式，如 left、center。maxLinesint文本允许显示的最大行数，超出部分默认截断并省略。示例代码:// 基本使用 Text( "Hello Flutter!", style: TextStyle( fontSize: 20, // 字体大小 color: Colors.blue, // 字体颜色 fontStyle: FontStyle.italic, // 字体样式 fontWeight: FontWeight.w900, // 字体粗细 decoration: TextDecoration.underline, // 字体装饰 decorationColor: Colors.red // 字体装饰颜色 ) ) // 截断并省略 Text( "今天是一个好日子, 今天是一个好日子, 今天是一个好日子, 今天是一个好日子, 今天是一个好日子, 今天是一个好日子", style: TextStyle(color: Colors.blue, fontSize: 30), maxLines: 1, // 最大行数 overflow: TextOverflow.ellipsis, // 超出省略号 )TextSpan-文本片段如果需要在同一段文本中显示不同样式，可用Text.rich构造函数配合TextSpan来实现代码示例:Text.rich( TextSpan( text: "Hello ", children: [ TextSpan( text: "Flutter", style: TextStyle(color: Colors.blue), ), TextSpan(text: "!"), ], style: TextStyle( fontSize: 30, color: Colors.red, fontWeight: FontWeight.bold, ), ), )适用场景: 所有文本展示都必须使用 Text 组件。注意事项:优先级：Text 自身属性 > TextStyle 中的同名属性（如 overflow）。长文本务必显式设置 maxLines 与 overflow，防止布局异常。对大量重复出现的文本样式，请统一定义成共享 TextStyle，既保证视觉一致，又能提升渲染性能。Image-图片组件作用: 在用户界面中显示图片的核心部件。图片分类:分类作用说明Image.asset()加载项目资源目录（assets）中的图片；需在 pubspec.yaml 声明资源路径。Image.network()直接从网络地址加载图片。Image.file()加载设备本地存储中的图片文件。Image.memory()加载内存中的图片数据（Uint8List）。常用属性:分类类型作用说明width / heightdouble设置图片显示区域的宽度与高度。fitBoxFit控制图片如何适应显示区域（拉伸、裁剪、保持比例等）。alignmentAlignmentGeometry图片在显示区域内的对齐方式，如 Alignment.center。repeatImageRepeat当图片小于显示区域时，设置是否及如何重复平铺。以Image.network为例:Image.network( "图片链接", width: 100, height: 100, fit: BoxFit.fill, // 填充方式 )TextField-文本输入组件作用: 实现文本输入功能的核心组件属性作用说明controller文本编辑控制器，用于获取/设置文档内容并监听变化。decoration控制输入框外观，如标签、提示文字、图标、边框等。style定义输入文本的样式。maxLines最大行数。onChanged输入内容发生变化时执行的回调函数。onSubmitted用户提交输入（如按回车）时的回调函数。登录页面案例:class MainPage extends StatefulWidget { const MainPage({super.key}); @override State<MainPage> createState() => _MainPageState(); } class _MainPageState extends State<MainPage> { TextEditingController _phoneController = TextEditingController(); // 账号控制器 TextEditingController _codeController = TextEditingController(); // 密码控制器 @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text("登录"), centerTitle: true), body: Container( padding: EdgeInsets.all(20), color: Colors.white, child: Column( children: [ TextField( controller: _phoneController, onChanged: (value) { // 输入框内容改变 print("用户名->$value"); }, onSubmitted: (value) { // 键盘回车键 print("用户名->$value"); }, decoration: InputDecoration( hintText: "请输入用户名", filled: true, fillColor: Colors.amber[50], border: OutlineInputBorder( borderSide: BorderSide.none, // 除去边框 borderRadius: BorderRadius.circular(25), // 圆角 ), ), ), SizedBox(height: 20), TextField( controller: _codeController, obscureText: true, // 不显示实际内容 decoration: InputDecoration( hintText: "请输入密码", // 提示文本 filled: true, // 允许填充 fillColor: Colors.amber[50], border: OutlineInputBorder( borderSide: BorderSide.none, // 除去边框 borderRadius: BorderRadius.circular(25), // 圆角 ), ), ), SizedBox(height: 20), Container( height: 50, width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(25), color: Colors.black, ), child: TextButton( onPressed: () { print( "登录->${_phoneController.text}-${_codeController.text}", ); }, child: Text( "登录", style: TextStyle(color: Colors.white, fontSize: 16), ), ), ), ], ), ), ), ); } }TextField 使用要点必须使用有状态组件使用 TextField 时必须将其放在 StatefulWidget 中。内容管理用 TextEditingController 控制输入内容；通过 onChanged 监听实时变化。外观定制借助 decoration: InputDecoration(...) 设置边框、背景、提示文字等样式。密码输入设置 obscureText: true 即可隐藏输入内容，用于密码框。七.组件通信通信方式方向适用场景构造函数传递父 => 子简单的数据传递回调函数子 => 父子组件通知父组件InheritedWidget祖先 => 后代跨层级数据共享Provider任意组件间状态管理推荐方案EventBus任意组件间全局事件通信Bloc/Riverpod任意组件间复杂状态管理1.父传子(构造函数传参数)步骤：子组件定义接收属性子组件在构造函数中接收参数父组件传递属性给子组件有状态组件在‘对外的类’接收属性，‘对内的类’通过widget对象获取对应属性注意⚠️：子组件定义接收属性需要使用final关键字-因为属性由父组件决定，子组件不能随意更改需求: 定义父子组件，父组件传递一个message变量给子组件并显示// 父组件 class MainPage extends StatelessWidget { const MainPage({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Container( alignment: Alignment.center, child: Column( children: [ Text("父组件", style: TextStyle(fontSize: 20, color: Colors.blue)), Child(message: "父组件给子组件传递的数据"), ], ), ), ), ); } } // 无状态组件子组件 class Child extends StatelessWidget { final String? message; // 定义属性 const Child({super.key, this.message}); @override Widget build(BuildContext context) { return Container( child: Text( "子组件-$message", style: TextStyle(fontSize: 20, color: Colors.red), ), ); } } // 有状态组件子组件 class Child extends StatefulWidget { final String message; const Child({super.key, required this.message}); @override State<Child> createState() => _ChildState(); } class _ChildState extends State<Child> { @override Widget build(BuildContext context) { return Text( "子组件-${widget.message}", style: TextStyle(fontSize: 20, color: Colors.red), ); } }案例// 父组件 class MainPage extends StatefulWidget { const MainPage({super.key}); @override State<MainPage> createState() => _MainPageState(); } class _MainPageState extends State<MainPage> { List<String> _list = ["鱼香肉丝", "宫保鸡丁", "西红柿鸡蛋", "尖椒肉丝", "小炒肉"]; @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: GridView.count( crossAxisCount: 2, mainAxisSpacing: 10, crossAxisSpacing: 10, children: List.generate(_list.length, (index) { return Child(foodName: _list[index]); }), ), ), ); } } // 子组件 class Child extends StatefulWidget { final String foodName; const Child({super.key, required this.foodName}); @override State<Child> createState() => _ChildState(); } class _ChildState extends State<Child> { @override Widget build(BuildContext context) { return Container( alignment: Alignment.center, color: Colors.blue, child: Text( widget.foodName, style: TextStyle(fontSize: 20, color: Colors.white), ), ); } }2.子传父(回调函数)步骤：父组件传递一个函数给子组件子组件调用该函数父组件通过回调函数获取参数需求：点击子组件删除父组件的菜品数据并更新列表// 父组件 class MainPage extends StatefulWidget { const MainPage({super.key}); @override State<MainPage> createState() => _MainPageState(); } class _MainPageState extends State<MainPage> { List<String> _list = ["鱼香肉丝", "宫保鸡丁", "西红柿鸡蛋", "尖椒肉丝", "小炒肉"]; @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: GridView.count( crossAxisCount: 2, mainAxisSpacing: 10, crossAxisSpacing: 10, children: List.generate(_list.length, (index) { return Child( foodName: _list[index], index: index, delFood: (int i) { setState(() { _list.removeAt(i); }); }, ); }), ), ), ); } } // 子组件 class Child extends StatefulWidget { final String foodName; // 食物名称 final int index; // 索引 final Function(int index) delFood; // 声明函数 const Child({ super.key, required this.foodName, required this.index, required this.delFood, }); @override State<Child> createState() => _ChildState(); } class _ChildState extends State<Child> { @override Widget build(BuildContext context) { return Stack( children: [ Container( alignment: Alignment.center, color: Colors.blue, child: Text( widget.foodName, style: TextStyle(fontSize: 20, color: Colors.white), ), ), Positioned( top: 10, right: 10, child: IconButton( color: Colors.red, onPressed: () { print("点击了删除, 删除的是${widget.index}"); widget.delFood(widget.index); }, icon: Icon(Icons.delete), ), ), ], ); } }其它的组件通信在后续综合案例里八.网络请求DIO插件使用网络请求是Fluter移动应用开发的核心功能，最常用的网络请求工具是使用Dio插件安装dio:flutter pub add dio基本使用：Dio().get(地址).then().catchError()DIO网络请求案例1.创建DIO工具类class DioUtils { final Dio _dio = Dio(); // 创建dio实例 DioUtils() { // 做一些基本的操作 // 配置基础地址 和 超时时间 // _dio.options.baseUrl = "https://geek.itheima.net/v1_0/"; // _dio.options.connectTimeout = Duration(seconds: 5); // 连接超时 // _dio.options.sendTimeout = Duration(seconds: 10); // 发送超时 // _dio.options.receiveTimeout = Duration(seconds: 10); // 接收超时 // 简写: ..连续赋值写法 _dio.options ..baseUrl = "https://geek.itheima.net/v1_0/" ..connectTimeout = Duration(seconds: 5) ..sendTimeout = Duration(seconds: 10) ..receiveTimeout = Duration(seconds: 10); // 拦截器(请求/响应/错误) _addInterceptor(); } void _addInterceptor() { _dio.interceptors.add( InterceptorsWrapper( // 请求拦截器 onRequest: (options, handler) { // return handler.next(requestOptions); // 放过请求 // return handler.reject(error); // 拦截请求 return handler.next(options); }, // 响应拦截器 onResponse: (reponse, handler) { // http状态码 2xx 3xx 4xx 5xx // return handler.reject(error); if (reponse.statusCode! >= 200 && reponse.statusCode! < 300) { return handler.next(reponse); } // 说明出异常 return handler.reject( DioException(requestOptions: reponse.requestOptions), ); }, // 错误拦截器 onError: (error, handler) { return handler.reject(error); // 直接抛出异常 }, ), ); } // 向外暴露一个get方法 get(String url, {Map<String, dynamic>? params}) { return _dio.get(url, queryParameters: params); } }2.初始化获取数据class _MainPageState extends State<MainPage> { @override void initState() { super.initState(); // 发起网络请求 _getChannels(); } List<Map<String, dynamic>> _list = []; // 用来接收数据 void _getChannels() async { DioUtils dioUtils = DioUtils(); Response<dynamic> result = await dioUtils.get("/channels"); Map<String, dynamic> res = result.data as Map<String, dynamic>; // print(res["data"]["channels"] as List<Map<String, dynamic>>); List data = res["data"]["channels"] as List; // print(data.cast<Map<String,dynamic>>() as List<Map<String, dynamic>>); _list = data.cast<Map<String, dynamic>>(); // cast方法强制转化列表项的类型 setState(() { print(_list); }); // channels是一个后端支持前端跨域访问的接口 cros 支持任何域名进行访问 } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text("频道管理"), centerTitle: true), body: Center(child: Text("频道管理")), ), ); } }3.解决web端的跨域问题默认情况下，flutter 运行 web 端加载网络资源会报跨域提示错误。以下是解决步骤：在 flutter/packages/flutter_tools/lib/src/web/chrome.dart 文件中，添加 --disable-web-security 参数，如图：删除 flutter/bin/cache/ 下的 flutter_tools.snapshot 和 flutter_tools.stamp 文件。执行 flutter doctor -v 命令，然后重新运行项目。4.父传子实现// 父组件 @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text("频道管理"), centerTitle: true), body: GridView.extent( maxCrossAxisExtent: 140, children: List.generate(_list.length, (index) { return ChannelItem(item: _list[index]); }), ), ), ); } // 子组件 class ChannelItem extends StatelessWidget { final Map<String, dynamic> item; const ChannelItem({super.key, required this.item}); @override Widget build(BuildContext context) { return Card( child: Container( alignment: Alignment.center, child: Text(item['name'] ?? "空", style: TextStyle(fontSize: 20)), ), ); } }九.路由管理定义：路由管理是构建多页面应用的核心，它通过 Navigator 和 Route 来管理页面栈，实现页面跳转与返回。跳转方法方法核心作用使用场景典型场景pushNamed进入新页面[A,B] → [A,B,C]常规跳转，如列表页进详情页pushReplacementNamed替换当前页面[A,B] → [A,C]登录成功后进主页，无法返回登录页pushNamedAndRemoveUntil跳转新页面并清空栈[A,B,C,D] → [A,E]退出登录后跳登录页并清空历史popAndPushNamed返回并立即跳转新页面[A,B,C] → [A,B,D]购物车结算后返回商品列表并跳订单页popUntil连续返回直到条件满足[A,B,C,D] → [A,B]从深层设置页一键回到主设置页1.基本路由场景：基本路由适合页面不多、跳转逻辑简单的场景。用法：无需提前注册路由，跳转时创建 MaterialPageRoute 实例即可。跳转新页面：Navigator.push(BuildContext context, Route route)返回上一页：Navigator.pop(BuildContext context)// 路由跳转-Material风格 只能有一个MaterialApp class MainPage extends StatelessWidget { const MainPage({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: ListPage(), // 列表页 详情页 ); } } // 列表页 class ListPage extends StatefulWidget { const ListPage({super.key}); @override State<ListPage> createState() => _ListPageState(); } class _ListPageState extends State<ListPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('列表页')), body: ListView.builder( itemCount: 100, itemBuilder: (context, index) { return GestureDetector( onTap: () { // 跳转到详情页 Navigator.push( context, MaterialPageRoute(builder: (context) => DetailPage()), ); }, child: Container( color: Colors.blue, alignment: Alignment.center, margin: EdgeInsets.all(5), height: 50, child: Text( "列表项$index", style: TextStyle(color: Colors.white, fontSize: 20), ), ), ); }, ), ); } } // 详情页 class DetailPage extends StatefulWidget { const DetailPage({super.key}); @override State<DetailPage> createState() => _DetailPageState(); } class _DetailPageState extends State<DetailPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('详情')), body: Center( child: TextButton( onPressed: () { Navigator.pop(context); }, child: Text("返回上一个页面"), ), ), ); } }2.命名路由场景：应用页面增多后，使用命名路由提升代码可维护性。用法：需先在 MaterialApp 中注册路由表（routes）并设置 initialRoute（首页）。// 路由跳转-Material风格 只能有一个MaterialApp class MainPage extends StatelessWidget { const MainPage({super.key}); @override Widget build(BuildContext context) { return MaterialApp( initialRoute: "/list", // 初始路由 routes: { // 路由表 "/list": (context) => ListPage(), "/detail": (context) => DetailPage(), }, home: ListPage(), // 列表页 详情页 ); } } // 使用方法 Navigator.pushNamed(context, '/detail');命名路由 vs 简单路由命名路由：需在 MaterialApp 的 routes 中预先注册路由表，适合中大型项目管理。简单路由：直接构建页面，更灵活，适合简单应用或快速原型开发。3.传递参数作用：通过路由传递参数是实现页面间数据通信的常用方式。命名路由传递参数（命名路由）：Navigator.pushNamed(context, '地址', arguments: 参数)接收参数（命名路由）：ModalRoute.of(context)?.settings.arguments接收时机：initState 中拿不到路由参数，需放在 Future.microtask((){ ... }) 里异步获取。// 路由跳转 传递参数 Navigator.pushNamed( context, '/detail', arguments: {'id': index + 1}, ); // 子组件获取参数 String _id = ""; @override void initState() { super.initState(); // 开启一个微任务，微任务会等所有的同步任务以及当前队列的任务执行完成才会执行 Future.microtask(() { // 获取路由参数 if (ModalRoute.of(context) != null) { // 能获取路由参数 print("获取路由参数成功"); Map<String, dynamic> params = ModalRoute.of(context)?.settings.arguments as Map<String, dynamic>; print(params["id"]); _id = params["id"].toString(); setState(() {}); } else { // 无法获取路由参数 print("获取路由参数失败"); } }); }基础路由传递参数（基础路由）：通过组件构造函数传递参数（父传子）。接收参数（基础路由）：通过组件构造函数接收参数（父传子）。接收时机：initState 中可直接获取构造函数传参。// 跳转到详情页 Navigator.push( context, MaterialPageRoute( builder: (context) => DetailPage(id: index + 1), ), ); // 详情页 class DetailPage extends StatefulWidget { final int id; const DetailPage({super.key, required this.id}); @override State<DetailPage> createState() => _DetailPageState(); } class _DetailPageState extends State<DetailPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('详情${widget.id}')), body: Center( child: TextButton( onPressed: () { Navigator.pop(context); }, child: Text("返回上一个页面"), ), ), ); } }4.动态路由与高级控制场景：更复杂的场景，如需根据参数动态生成页面，或实现路由拦截，可使用 onGenerateRoute 与 onUnknownRoute。onGenerateRouteonGenerateRoute：允许根据 RouteSettings（含路由名称与参数）动态创建不同 Route。class MainPage extends StatelessWidget { const MainPage({super.key}); @override Widget build(BuildContext context) { return MaterialApp( initialRoute: "/goodsList", routes: {"/goodsList": (context) => GoodsList()}, // 登录页和购物车页面不在路由表里面 onGenerateRoute: (settings) { // 路由表里面没有的页面 // settings.name print(settings.name); // 去的是不是购物车列表页 if (settings.name == "/cartList") { bool isLogin = false; // 检查是否登录 if (isLogin) { return MaterialPageRoute(builder: (context) => CartList()); } else { return MaterialPageRoute(builder: (context) => LoginPage()); } } }, ); } } // 商品列表 class GoodsList extends StatefulWidget { const GoodsList({super.key}); @override State<GoodsList> createState() => _GoodsListState(); } class _GoodsListState extends State<GoodsList> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("商品列表")), body: Center( child: TextButton( onPressed: () { Navigator.pushNamed(context, "/cartList"); }, child: Text("加入购物车"), ), ), ); } } // 购物车列表 class CartList extends StatefulWidget { const CartList({super.key}); @override State<CartList> createState() => _CartListState(); } class _CartListState extends State<CartList> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("购物车列表")), body: Center( child: TextButton(onPressed: () {}, child: Text("去支付")), ), ); } } // 登录界面 class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State<LoginPage> createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("登录")), body: Center( child: TextButton(onPressed: () {}, child: Text("去登录")), ), ); } }onUnknownRouteonUnknownRoute：当跳转到既未在路由表注册、也未被 onGenerateRoute 处理的路由时调用，通常用于展示“404 页面”。onUnknownRoute: (settings) { return MaterialPageRoute( builder: (context) => Scaffold( body: Center(child: Text("404")), ), ); }