您的位置:首页 > 健康 > 美食 > 做亚马逊一个月挣10万_广州腾虎网络科技有限公司_链接搜索_深圳专业seo

做亚马逊一个月挣10万_广州腾虎网络科技有限公司_链接搜索_深圳专业seo

2024/10/30 7:09:13 来源:https://blog.csdn.net/qq_55272229/article/details/143082308  浏览:    关键词:做亚马逊一个月挣10万_广州腾虎网络科技有限公司_链接搜索_深圳专业seo
做亚马逊一个月挣10万_广州腾虎网络科技有限公司_链接搜索_深圳专业seo

flutter

161·`·由于官方的汉化文档感觉还是有很多没有汉化的地方 ,所以自己打一遍的同时写下了以下笔记

在这里插入图片描述

社区生态

官方文档 所有的控件:Widget 目录 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter

官方论坛的教程 Flutter Widget框架概述 - Flutter中文网 (flutterchina.club)

全球开发者写的flutter插件查找网站 Easy Flutter Pubs - Finding Flutter packages more easier (pubdev.top)

基本上各个开发者开发的查找凭借就可以凭借一款不错的app了

由于flutter是使用dart语言,所以需要熟悉dart (很简单 80%的java 和20%js的感觉)

目录结构:

my_flutter_app/
├── android/
├── build/
├── ios/
├── lib/
│ ├── main.dart
│ ├── pages/
│ │ ├── home_page.dart
│ │ ├── settings_page.dart
│ │ └──…
│ ├── models/
│ │ ├── user.dart
│ │ └──…
│ ├── services/
│ │ ├── api_service.dart
│ │ └──…
│ ├── utils/
│ │ ├── constants.dart
│ │ ├── helpers.dart
│ │ └──…
│ └── widgets/
│ ├── custom_button.dart
│ └──…
├── test/
├──.gitignore
├──.metadata
├── pubspec.yaml
├── README.md
└── analysis_options.yaml

pubspec.yaml :管理第三方依赖

还有一个lock 当运行编译产生文件

目录结构

而 ios 和 android 文件夹中的代码是用于集成 Flutter 应用到 iOS 和 Android 平台的原生部分。
所有的adrt代码写到lib目录 编译运行时候

快速入门

android studo 下载flutter插件后 进入lib目录进行启动

main是入口 app.run 是将widget(控件)渲染到屏幕上 flutter应用中的所有显示效果都是采用控件的形式
比如改成 显示一个文本

  /*** widget 组件// * runapp 渲染组件到屏幕上// * 渲染构造眼熟时候就要求静态化// */runApp(const Text("你好 我是显示文本的组件",textDirection:TextDirection.ltr,style: TextStyle(shadows:[],fontSize: 30,color: Colors.pink,)));

值得注意的是需要表明 标明控件的方向, 否则会进行报错

布局应用app(脚手架)

void main() {/*** aterialApp 是 Flutter 框架中的一个顶级组件,用于构建一个基于 Material Design 风格的应用程序。Material Design 是 Google 推出的设计规范,强调简洁、响应式、多平台的一致用户体验,Flutter 提供了 MaterialApp 这个类来帮助开发者快速构建符合 Material Design 的应用。MaterialApp 作用MaterialApp 是 Flutter 应用的入口,负责管理应用的路由、主题、导航、以及一些全局的设置。它类似于 Android 中的 Application 类或是 iOS 中的 AppDelegate。为app 开发提供了模板 在其中写的组件 除开防线组件不需要写模板*///1. 定义 TextThemeTextTheme textTheme = const TextTheme(bodyLarge:  TextStyle(fontSize: 18, color: Colors.red),// 可以定义更多的文本样式...);runApp(MaterialApp(theme: ThemeData(primarySwatch: Colors.blue,
//      2.  全局使用textTheme:textTheme),//为 Material Design 微件创建可视化基架。home: Scaffold(appBar: AppBar(//左边的图标leading: const Icon(Icons.access_alarms),// 中间区域 titletitle: const Center(child:   Text("测试app主页",style: TextStyle(shadows:[],color: Colors.cyan,)),),
//          右边区域actions:[//3.  全局使用Text("详细查看", style: textTheme.bodyLarge, ),const Icon(Icons.ac_unit_sharp),],),// 内容部分   垂直布局  采用容器列进行布局body: Column(children: [Expanded(flex: 40, // 表示占据的比例child: Container(color: Colors.red,child: Center(child: Column(  // 使用 Column 允许在同一区域放置多个控件mainAxisAlignment: MainAxisAlignment.center,  // 垂直居中对齐children: [Container(width: 100,height: 100,color: Colors.amberAccent,child: TextButton(onPressed: () => print("用户点击了按钮"),onLongPress: () => print("长按触发事件"),child: const Text("点击即可"),),),const SizedBox(height: 20),  // 增加一个空隙Container(width: 100,height: 100,color: Colors.lightBlue,child: TextButton(onPressed: () => print("用户点击了另一个按钮"),child: const Text("另一个按钮"),),),],),),),),
//              占位分割符const Spacer(),Expanded(flex: 20,//直接监听区域事件child: GestureDetector(// 单击onTap: () {print("监听点击了按钮");},child: Container(color: Colors.amber,child: Container(color: Colors.blue,child:const Center(child: Text("蓝色容器")),),),),),const Spacer(),Expanded(flex: 20,child: Container(color: Colors.green,child: Center(child: Text("绿色容器")),),),],),//浮动按钮 可以点击 点击时触发事件 容器预一营好的布局 改按钮是在容器中 右下角floatingActionButton: FloatingActionButton(child:  Icon(Icons.account_balance_wallet_sharp),onPressed: () {print("点击了按钮");},tooltip: "长按触发事件",),//底部的导航栏 有items 属性 当前位置 索引 点击时时间等bottomNavigationBar: buildBtoomnNavigationBar()),));
}Widget buildBtoomnNavigationBar() {return BottomNavigationBar(items: const <BottomNavigationBarItem>[BottomNavigationBarItem(icon: Icon(Icons.home),label: '首页',),BottomNavigationBarItem(icon: Icon(Icons.search),label: '搜索',),BottomNavigationBarItem(icon: Icon(Icons.person),label: '个人中心',),],// 初始索引位置currentIndex: 0, // 选中的索引onTap: (index) {// 处理点击事件// 例如,切换页面print('点击了第$index 个按钮');},);
}

MaterialApp 就是一个快入搭建material风格的app脚手架 其中可以有各种空间
Scaffold 是 Flutter 中的一个基本结构组件,提供了一个应用程序的框架。它包含一个 AppBar(应用栏)、一个主内容区域(body)和一个底部导航栏(bottomNavigationBar)。
它让你更方便地构建具有 Material Design 风格的界面
Scaffold 的主要组成部分
Scaffold 提供了以下几个主要部分:
appBar:位于屏幕顶部的应用栏(AppBar)。
body:屏幕的主要内容区域。
bottomNavigationBar:位于屏幕底部的导航栏(BottomNavigationBar)。
floatingActionButton:浮动操作按钮(FloatingActionButton)。
drawer:侧边抽屉(Drawer)。
endDrawer:右侧边抽屉(EndDrawer)。
backgroundColor:背景颜色。
resizeToAvoidBottomInset:是否调整大小以避免底部内边距。
resizeToAvoidBottomPadding:是否调整大小以避免底部填充。
primary:是否是主要的屏幕。
extendBody:是否扩展到屏幕边缘。
extendBodyBehindAppBar:是否在 AppBar 后面扩展内容。
persistentFooterButtons:底部固定的按钮。
navigationMode:导航模式。
bottomSheet:底部表单(BottomSheet)。

这样看的话 flutter 就像是把各个ui控件拼接到各个布局组成app

并且跟web前端很相似

由于每一个布局的位置的参数都是控件 可以进行拆分成方法

所以这个给文档主要就是说各个控件以及相关api

布局控件

再任何布局前,官方推荐根布局嵌套一个safearea(安全区),自适应,不会被状态栏给挡住的内容区域

body:SafeArea(child: ListView(......)
)

在body部分 ,这部分的控件主要是手机的主要显示区域 ,往往是一个列包裹多个行 (手机是竖屏显示)

contaier

body 部分确实经常使用像 Container 这样的组件来布局页面,但与前端开发中的 div 不完全相同。Flutter 提供了许多灵活的布局控件,开发者在实际开发中会根据需求来组合使用这些控件,而不仅仅依赖 Container

Flutter 和前端布局的对比

  • 前端 div:在前端开发中,div 是一种非常基础的布局标签,几乎什么都可以包裹。开发者通常使用 CSS 来为 div 设置布局属性,比如 flexgridpaddingmargin 等。
  • Flutter ContainerContainer 是 Flutter 中类似 div 的通用容器控件。它可以包裹其他控件,并允许设置 paddingmarginbordercolorwidthheight 等属性。除此之外,Flutter 提供了更多的布局控件,如 RowColumnStackExpanded 等,专门用于实现不同的布局。

实际开发中的 body 布局

在实际开发中,body 部分通常使用多个 Flutter 的布局控件进行嵌套组合,而不仅仅是使用 Container。这使得布局更加灵活和响应式。下面是一些常见的布局控件及其用法:

1. ColumnRow

ColumnRow 是最常见的布局控件,用于垂直或水平排列子组件。它们可以像前端的 flex 布局一样使用(不可以直接设置宽度高度 需要根据子容器来)

body: Column(children: [Container(width: double.infinity,height: 200,color: Colors.red,child: Center(child: Text("顶部区域")),),Row(children: [Expanded(child: Container(color: Colors.blue, height: 100)),Expanded(child: Container(color: Colors.green, height: 100)),],),Container(width: double.infinity,height: 200,color: Colors.yellow,child: Center(child: Text("底部区域")),),],
)

并且row和col 都有俩个相同的api

主轴和副轴的对称方式

  		 mainAxisAlignment: MainAxisAlignment.spaceBetween, // 主轴对齐方式crossAxisAlignment: CrossAxisAlignment.center, // 副轴对齐方式

比如当布局时row 时候,主轴就是行,副轴就是列

当然这种包裹的子组件是children 如果类似多个控件数组,有多种方式批量生成

list.generate

   List<String> items = ['Apple', 'Banana', 'Cherry'];List<Widget> widgetList = List.generate(items.length, (index) {return Text(items[index]);});

map (类似java stream 流)

   List<String> items = ['Apple', 'Banana', 'Cherry'];List<Widget> widgetList = items.map((item) => Text(item)).toList();

builder

   ListView.builder(itemCount: items.length,itemBuilder: (BuildContext context, int index) {return Text(items[index]);},);

最简单的for 构建控件数组

   List<Widget> widgetList = [];for (var item in items) {widgetList.add(Text(item));}
2. Stack

Stack 类似于 HTML/CSS 中的 position: absolute,允许在同一个布局中叠加多个组件。

body: Stack(children: [Container(width: double.infinity,height: 300,color: Colors.blue,),//搭配这个属性可以实现类似z-index:999的效果Positioned(top: 100,left: 50,child: Container(width: 100,height: 100,color: Colors.red,),),],
)
3. ListView

对于需要滚动的内容,ListView 是一个非常常用的控件,类似于 HTML 中的 ul 或者 ol

dart复制代码body: ListView(children: [Container(height: 100,color: Colors.red,child: Center(child: Text("第一个Item")),),Container(height: 100,color: Colors.blue,child: Center(child: Text("第二个Item")),),// 更多的Item],
)
4. ExpandedFlexible

当你想要让某些子组件根据父组件的剩余空间自动调整大小时,ExpandedFlexible 是非常有用的。

dart复制代码body: Row(children: [Container(width: 100, height: 100, color: Colors.red),Expanded(child: Container(height: 100,color: Colors.blue,child: Text("我会填满剩下的空间"),),),],
)

注意

往往使用这个expanded来进行达到flex布局的效果时候 (只看内容部分 ) ,如果是Row的属性 flex 比列就是行宽占比 ,Colum 就是列

void main() {/*** aterialApp 是 Flutter 框架中的一个顶级组件,用于构建一个基于 Material Design 风格的应用程序。Material Design 是 Google 推出的设计规范,强调简洁、响应式、多平台的一致用户体验,Flutter 提供了 MaterialApp 这个类来帮助开发者快速构建符合 Material Design 的应用。MaterialApp 作用MaterialApp 是 Flutter 应用的入口,负责管理应用的路由、主题、导航、以及一些全局的设置。它类似于 Android 中的 Application 类或是 iOS 中的 AppDelegate。为app 开发提供了模板 在其中写的组件 除开防线组件不需要写模板*///1. 定义 TextThemeTextTheme textTheme = const TextTheme(bodyLarge:  TextStyle(fontSize: 18, color: Colors.red),// 可以定义更多的文本样式...);runApp(MaterialApp(theme: ThemeData(primarySwatch: Colors.blue,
//      2.  全局使用textTheme:textTheme),//为 Material Design 微件创建可视化基架。home: Scaffold(appBar: AppBar(//左边的图标leading: const Icon(Icons.access_alarms),// 中间区域 titletitle: const Center(child:   Text("测试app主页",style: TextStyle(shadows:[],color: Colors.cyan,)),),
//          右边区域actions:[//3.  全局使用Text("详细查看", style: textTheme.bodyLarge, ),const Icon(Icons.ac_unit_sharp),],),// 内容部分body: Column(children: [// 使用 Expanded 来占据屏幕宽度的剩余空间Expanded(flex: 2, // 表示占据的比例,值越大占据的空间越多child: Container(color: Colors.red,child: Center(child: Text("红色容器")),),),Expanded(flex: 1, // 这里的比例是1:1:1child: Container(color: Colors.blue,child: Center(child: Text("蓝色容器")),),),Expanded(flex: 1, // 这里的比例是1:1:1child: Container(color: Colors.green,child: Center(child: Text("绿色容器")),),),],),//浮动按钮 可以点击 点击时触发事件 容器预一营好的布局 改按钮是在容器中 右下角floatingActionButton: FloatingActionButton(child: const Icon(Icons.add),onPressed: () {print("点击了按钮");},tooltip: "长按触发事件",),//底部的导航栏 有items 属性 当前位置 索引 点击时时间等bottomNavigationBar: buildBtoomnNavigationBar()),));
}

示例:实际应用中的 body 布局

body: Column(children: [Container(height: 200,color: Colors.blue,child: Center(child: Text("顶部区域")),),Expanded(child: ListView(children: [Container(height: 100,color: Colors.red,child: Center(child: Text("第一个Item")),),Container(height: 100,color: Colors.green,child: Center(child: Text("第二个Item")),),],),),Container(height: 100,color: Colors.yellow,child: Center(child: Text("底部区域")),),],
)

动态布局

在 Flutter 中,Expanded 是一种非常常用的控件,它允许子控件在父容器中根据可用空间进行扩展,以实现响应式布局。但并不是只有 Expanded 可以实现响应式布局,Flutter 提供了多种方式实现响应式布局,取决于具体的需求和场景。下面是几种实现响应式布局的常见方法:

ExpandedFlexible

  • Expanded:可以让子控件在父容器中占据剩余的可用空间。所有使用 Expanded 的子控件都会均匀分配可用空间。

    示例:

    Row(children: [Expanded(child: Container(color: Colors.red),),Expanded(child: Container(color: Colors.green),),],
    )
    

    在这个例子中,两个 Container 会各自占据一半的可用空间。

  • Flexible:与 Expanded 类似,但 Flexible 可以让子控件在父容器中根据比例分配空间,且子控件不会强制填满空间。

    示例:

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

    这里,Container 会按照 2:1 的比例来分配剩余空间。

MediaQuery

MediaQuery 是 Flutter 中用于获取屏幕尺寸和设备信息的工具。你可以使用它来根据屏幕的大小调整布局,从而实现响应式设计。

示例:

double screenWidth = MediaQuery.of(context).size.width;Container(width: screenWidth * 0.5,  // 设置容器宽度为屏幕宽度的50%height: 100,color: Colors.blue,
)

在这个例子中,我们根据屏幕的宽度调整了 Container 的大小,从而实现了响应式布局。

LayoutBuilder

LayoutBuilder 允许你根据父容器的尺寸来动态调整子控件的布局。它特别适合处理不同尺寸的布局需求。

示例:

LayoutBuilder(builder: (context, constraints) {if (constraints.maxWidth > 600) {return Text("大屏布局");} else {return Text("小屏布局");}}
)

在这个例子中,根据父容器的宽度,Text 的内容会发生变化。

AspectRatio

AspectRatio 控件可以帮助你控制子控件的宽高比,确保其响应式调整大小。

示例:

AspectRatio(aspectRatio: 16/9,child: Container(color: Colors.red),
)

这个 AspectRatio 控件会确保 Container 以 16:9 的比例进行缩放,无论父容器的大小如何。

FittedBox

FittedBox 用于调整子控件的大小以适应父容器,并保持子控件内容的比例。

示例:

FittedBox(child: Text('这是一个长文本'),
)

FittedBox 会自动缩放 Text,以确保它能够适应可用的空间。

Wrap

Wrap 是一种类似 RowColumn 的布局方式,但它允许子控件在空间不足时换行,因此在处理动态数量的子控件时非常有用。

示例:

Wrap(children: [Container(width: 100, height: 100, color: Colors.red),Container(width: 100, height: 100, color: Colors.green),Container(width: 100, height: 100, color: Colors.blue),Container(width: 100, height: 100, color: Colors.yellow),],
)

在这个例子中,Wrap 会在一行容不下所有 Container 时自动换行,从而实现响应式布局。

分割符

Spacer(),

用来做容器中的内容分割,点击源码 发现默认是一个一个占比的 所有整个 容器的占比 就至少根据这个情况来

  const Spacer({super.key, this.flex = 1}): assert(flex > 0);

比如

          body: Column(children: [Expanded(flex: 20, // 表示占据的比例child: Container(color: Colors.red,child: Center(child: Column(  // 使用 Column 允许在同一区域放置多个控件mainAxisAlignment: MainAxisAlignment.center,  // 垂直居中对齐children: [Container(width: 100,height: 100,color: Colors.amberAccent,child: TextButton(onPressed: () => print("用户点击了按钮"),onLongPress: () => print("长按触发事件"),child: const Text("点击即可"),),),const SizedBox(height: 20),  // 增加一个空隙Container(width: 100,height: 100,color: Colors.lightBlue,child: TextButton(onPressed: () => print("用户点击了另一个按钮"),child: const Text("另一个按钮"),),),],),),),),
//              占位分割符Spacer(),Expanded(flex: 10,child: Container(color: Colors.blue,child: Center(child: Text("蓝色容器")),),),Spacer(),Expanded(flex: 10,child: Container(color: Colors.green,child: Center(child: Text("绿色容器")),),),],),

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用户交互:手势检测

手势控件(如 GestureDetectorInkWell 等)主要是用于捕捉和处理用户的手势操作,它们通常应用于需要处理交互的局部区域,而不是全局应用。因此,它们不需要放在全局的 MaterialApp 中,而是用于包裹具体的 UI 组件(如按钮、图片、容器等),以检测用户在这些组件上的手势操作。

   Expanded(flex: 20,child: GestureDetector(// 单击onTap: () {print("监听点击了按钮");},// 双击onDoubleTap: () {print("监听该区域双击了按钮");},// 长按onLongPress: () {print("监听长按触发事件");},// 长按抬起onLongPressUp: () {print("监听长按后松手");},// 按下onTapDown: (details) {print("监听手指按下");},// 点击抬起onTapUp: (details) {print("监听手指松开");},// 点击取消onTapCancel: () {print("监听点击取消");},onPanStart: (details) {print("监听任意方向拖动开始");},onPanUpdate: (details) {print("监听任意方向拖动更新");},onPanEnd: (details) {print("监听任意方向拖动结束");},// 垂直拖动更新// onVerticalDragUpdate: (details) {//   print("监听垂直拖动更新");// },// 垂直拖动结束// onVerticalDragEnd: (details) {//   print("监听垂直拖动结束");// },// 缩放开始// onScaleStart: (details) {//   print("监听缩放开始");// },// 缩放更新// onScaleUpdate: (details) {//   print("监听缩放更新");// },// 缩放结束// onScaleEnd: (details) {//   print("监听缩放结束");// }, //监听的区域child: Container(color: Colors.amber,child: Container(color: Colors.blue,child:const Center(child: Text("蓝色容器")),),),),),

注意:

同时设置了水平拖动 (onHorizontalDrag)、垂直拖动 (onVerticalDrag) 和缩放手势 (onScale)。这三种手势在一起时会冲突,因为它们都涉及拖动,导致缩放手势被忽略。

其他交互相关: 交互性 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter

页面响应式–有状态控件

和react 和vue 一样,可以根据携带状态的改变刷新页面,对应react的usestatte,vue的响应式ref,也可以全局状态管理pinia等状态管理工具

  • 有状态的控件指的是在 Flutter 中可以通过修改其内部状态来响应用户交互或其他事件的控件。
    这些控件可以是按钮、文本框、复选框、单选按钮等,
  • 它们在内部都有自己的状态,例如按钮的选中状态、文本框的输入内容等。

之前使用的class Text extends StatelessWidget 基本都是继承无状态控件

有状态控件 可以把无状态控制包裹起来实现动态渲染

使用步骤

1.自定义控件继承 StatefulWidget ,重写起创建方法createState.(调用构造函数时候默认调用)

2.自定义状态包含初始状态,并且继承State<自定义控件> 重写起build 方法(一个返回控件的初始化方法)

3.此时自定义内的数据(状态是收到监听的,当使用setState方法的时候 ,重新渲染控件build 方法)从而实现更新

/*** 有状态的控件指的是在 Flutter 中可以通过修改其内部状态来响应用户交互或其他事件的控件。这些控件可以是按钮、文本框、复选框、单选按钮等,* 它们在内部都有自己的状态,例如按钮的选中状态、文本框的输入内容等。*/import 'package:flutter/material.dart';/*** 1.继承自 StatefulWidget 的有状态控件通常需要实现一个 State 类来管理其内部状态。*/
class CounterWidget extends StatefulWidget {State<StatefulWidget> createState() {// TODO: implement createStatereturn CountState();}}// 在使用有状态控件时,通常需要在 State 类中定义一些方法来处理用户交互或其他事件,例如点击按钮时增加计数器的值。
class CountState extends State<CounterWidget> {int _counter = 0;//state// 2.重写build方法 每次页面刷新 时候都会执行一下 build方法Widget build(BuildContext context) {print("页面刷新"+DateTime.now().toString());return Scaffold(appBar: AppBar(title: Text('有状态控件示例')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Text('按钮被按下了这么多次:'),Text('$_counter',style: Theme.of(context).textTheme.headlineMedium,),],),),// 浮动按钮floatingActionButton: FloatingActionButton(onPressed: _incrementCounter,//调用自增action 改变了state 后 state数据改变,会重新执行build 方法进行渲染更新新数据到视图上,tooltip: '自增按钮',child: Icon(Icons.add),),);}//action// 更新状态void _incrementCounter() {//调用setState方法后 页面会重新执行build方法进行渲染setState(() {_counter++;});}// 清理资源void dispose() {print('控件被销毁');super.dispose();}}void main() {//使用构造函数返回携带状态的视图runApp(MaterialApp(home: CounterWidget()));
}
/**}**/

setState方法是状态控件的父类方法

android studio快捷健 stful

全局状态

Provider 是 Flutter 中的一种状态管理方式,它基于 InheritedWidget,但比直接使用 InheritedWidget 更简洁和强大。Provider 通常用于全局管理状态、共享数据,以及在不同的组件之间进行数据传递。并且由于flutter是嵌套组件进行构建app,如果子孙组件,因为父类选择的item,需要刷新,但是父级组件状态改变,然后嵌套深的无关子孙组件也要跟着重新渲染,这样就造成了性能损失,所以下面我将详细解释 Provider 的使用。

1. 引入 Provider

在开始使用 Provider 之前,需要将它添加到项目的 pubspec.yaml 文件中:

dependencies:provider: ^6.1.2

然后在 Dart 文件中引入 provider 包:

import 'package:provider/provider.dart';

2. 基本概念

  • ChangeNotifier:这是一个可监听的类,用于保存状态。通过调用 notifyListeners() 方法,可以通知所有监听者更新数据。
  • ChangeNotifierProvider:这是 Provider 提供的一种具体实现,它与 ChangeNotifier 搭配使用,能够提供状态和监听变化。
  • Consumer:它是用来读取 Provider 中的状态并构建 UI 的小部件。它能够订阅某个状态,并在状态发生变化时自动重建 UI。

3. ChangeNotifierChangeNotifierProvider

ChangeNotifier 是一个简化的状态管理类。可以创建一个 ChangeNotifier 类来管理应用的状态:

示例:计数器的状态管理

  1. 创建 ChangeNotifier
//类似dart 对多集成的实现
class Counter with ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners(); // 通知所有监听这个状态的Widget}
}
  1. 在应用中提供 ChangeNotifierProvider

在根组件(或任意父组件)中使用 ChangeNotifierProvider 来提供 Counter 状态:

void main() {runApp(ChangeNotifierProvider(create: (context) => Counter(), // 创建并提供Counter实例child: MyApp(),),);
}
  1. 在子组件中使用 ConsumerProvider.of 获取状态

可以通过 ConsumerProvider.of 来监听状态,并在状态发生变化时更新 UI。

  • 使用 Consumer
class CounterScreen extends StatelessWidget {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Counter App'),),body: Center(//局部渲染的组件 使用conumer 包裹child: Consumer<Counter>(builder: (context, counter, child) {return Text('Count: ${counter.count}', // 获取计数状态style: TextStyle(fontSize: 40),);},),),floatingActionButton: FloatingActionButton(onPressed: () {//由于在顶级组件树注入的状态,所以偶可以使用上下文read来进行读取context.read<Counter>().increment(); // 修改计数状态},child: Icon(Icons.add),),);}
}
  • 使用 Provider.of
class CounterScreen extends StatelessWidget {Widget build(BuildContext context) {final counter = Provider.of<Counter>(context);return Scaffold(appBar: AppBar(title: Text('Counter App'),),body: Center(child: Text('Count: ${counter.count}', // 获取计数状态style: TextStyle(fontSize: 40),),),floatingActionButton: FloatingActionButton(onPressed: () {counter.increment(); // 修改计数状态},child: Icon(Icons.add),),);}
}

4. 多个 Provider 的使用

有时应用需要管理多个状态。可以通过 MultiProvider 来提供多个 Provider

示例:多个状态管理

  1. 创建多个 ChangeNotifier
class Counter with ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners();}
}class Message with ChangeNotifier {String _message = "Hello";String get message => _message;void changeMessage(String newMessage) {_message = newMessage;notifyListeners();}
}
  1. 使用 MultiProvider
void main() {runApp(MultiProvider(providers: [ChangeNotifierProvider(create: (context) => Counter()),ChangeNotifierProvider(create: (context) => Message()),],child: MyApp(),),);
}
  1. 在子组件中获取不同的状态
class MultipleStateScreen extends StatelessWidget {Widget build(BuildContext context) {final counter = Provider.of<Counter>(context);final message = Provider.of<Message>(context);return Scaffold(appBar: AppBar(title: Text('Multi Provider Example'),),body: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Text('Count: ${counter.count}',style: TextStyle(fontSize: 40),),Text('Message: ${message.message}',style: TextStyle(fontSize: 20),),],),floatingActionButton: FloatingActionButton(onPressed: () {counter.increment();message.changeMessage("New Message");},child: Icon(Icons.add),),);}
}

5. Provider.ofConsumerSelector 的区别

  • Provider.of:立即获取 Provider 中的值。如果 listentrue(默认值),则当值发生变化时,组件会重建。
  • Consumer:专门用于监听 Provider 中的数据变化,并且只会更新 Consumer 里面的部分组件,这可以避免不必要的组件重建。
  • Selector:可以选择监听 Provider 中的某个部分数据变化,避免整个对象变化时导致不必要的重建。

使用 Selector

class CounterScreen extends StatelessWidget {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Selector Example'),),body: Center(child: Selector<Counter, int>(selector: (context, counter) => counter.count, // 只监听 count 的变化builder: (context, count, child) {return Text('Count: $count',style: TextStyle(fontSize: 40),);},),),floatingActionButton: FloatingActionButton(onPressed: () {context.read<Counter>().increment();},child: Icon(Icons.add),),);}
}

6. 总结

Provider 是一种简便且高效的状态管理方式,和react 一样将全局状态在顶级组件树木注入,让子组件上下文可以直接使用读取,并且可以使用conmuer包裹监听渲染特定部分,状态改变时候,之刷新comsumer 包裹部分

尤其适用于较小的 Flutter 应用或状态较简单的情况。通过使用 ChangeNotifierChangeNotifierProvider,可以轻松实现状态的全局管理。同时,通过 ConsumerSelector 等机制,能够精准控制组件的重建,从而提升应用性能。

无状态控件

快捷健stless

main(){runApp(MaterialApp(home: myState()));
}
class myState extends StatelessWidget {const myState({super.key});Widget build(BuildContext context) {int i = 100;print("自定义无状态组件初始化");return Placeholder(child: Column(children: <Widget>[ElevatedButton(onPressed: ()=>{i++,print("$i"),}, child: Text("点击输出当前控件的数值")),],),);}
}

点击屏幕 发现控件内的数据i虽然变化了,但是页面不会渲染也就是所谓的无状态,不会随着状态改变


生命周期

只有有状态控件才会有生命周期,并且flutter的生命周期感觉和react还有一些相似

都是挂载组件/控件树

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在Flutter中,生命周期的管理类似于React,尤其是在组件的创建、更新和销毁过程中,都会触发不同的生命周期方法。在你的Flutter代码中,你定义了一个StatefulWidget,因为只有有状态的组件才有生命周期方法。接下来我会详细介绍这些生命周期方法并补充完整。

Flutter 生命周期方法解析:

  1. createState()

    • MyHome这个StatefulWidget中,createState()方法是首先被调用的,用于创建与该组件关联的状态对象_MyHomeState
    • 打印输出:“1.初始化控件 执行了createState方法”
  2. initState()

    • initState()State类的第一个生命周期方法,它在状态对象被创建时调用。通常用于组件的初始化操作,比如获取数据、订阅事件等。
    • 你在initState()中进行了网络图片的初始化加载,这种做法类似于React中的componentDidMount()
    • 打印输出:“2.执行了state的initState方法”
    • 注意:必须调用super.initState(),以确保父类的初始化逻辑也被执行。
  3. build()

    • build() 方法在组件每次需要更新UI时被调用。这就类似于React中的render()方法。Flutter会根据你在setState()中触发的状态变更,调用build()重新渲染UI。
    • 每次点击按钮后调用setState(),Flutter会再次调用build()方法。
    • 打印输出:“3.执行了build方法 渲染控件”
  4. didUpdateWidget() (可选):

    • StatefulWidget的配置发生变化时,didUpdateWidget() 会被调用。可以通过这个方法来处理父组件传递给子组件的新数据。类似于React的componentDidUpdate()
    • 如果你修改父组件的数据传递给子组件,比如你在外部改变了MyHome的某些参数,Flutter会调用这个方法。

    示例

    
    void didUpdateWidget(covariant MyHome oldWidget) {super.didUpdateWidget(oldWidget);print("4.执行了didUpdateWidget方法");
    }
    
  5. dispose()

    • 当组件不再需要时,dispose() 会被调用,用来释放资源,比如取消网络请求、监听器、动画等。
    • 你在代码中正确地使用了dispose()来释放组件。
    • 打印输出:“释放资源控件销毁”
  6. deactivate() (可选):

    • deactivate() 方法在组件从树中被移除时调用,通常用于从父组件或其他依赖的地方解除绑定。这和dispose()不同,dispose()是在彻底销毁前调用,而deactivate()在组件可能还会重新插入树中时调用。

    示例

    
    void deactivate() {super.deactivate();print("5.执行了deactivate方法");
    }
    
  7. reassemble() (可选):

    • 该方法主要用于热重载(hot reload)期间,开发时重新编译代码后,reassemble() 会被调用。正常情况下应用不会用到这个方法。

    示例

    
    void reassemble() {super.reassemble();print("执行了reassemble方法");
    }
    

完整的生命周期顺序:

  • createState()
  • initState()
  • build()
  • didUpdateWidget()(在组件重新构建时,如果父组件传入新参数)
  • deactivate()(组件从树中被移除)
  • dispose()(释放资源,销毁组件)

生命周期优化:

Flutter与React相似,使用setState()来更新UI,触发build()的重新渲染。为了避免不必要的重绘,通常需要谨慎使用setState(),确保它只在需要更新的地方调用,类似于React中的shouldComponentUpdate。可以使用全局状态插件provider

void main() {runApp(MaterialApp(home: Scaffold(appBar: AppBar(title: Text('演示控件的生命周期'),),body: MyHome())));
}class MyHome extends StatefulWidget {int a = 10;MyHome({super.key});State<MyHome> createState() {print("1.初始化控件 执行了createState方法");return _MyHomeState();}
}class _MyHomeState extends State<MyHome> {List<String> images = [];int index = 0;// 2. initState: 初始化状态void initState() {print("2.执行了state的initState方法");images.addAll(['https://img.zcool.cn/community/017f51563447666ac7259e0f1522ea.jpg@1280w_1l_2o_100sh.jpg',"https://img.zcool.cn/community/01129957723f4b0000018c1b6692bb.jpg@2o.jpg","https://n.sinaimg.cn/sinacn10113/332/w1024h1708/20190806/3afd-iatixpm8624881.jpg","http://image.yjcf360.com/u/cms/www/201905/25084330vx4w.jpg"]);super.initState();}// 3. didChangeDependencies: 当依赖的对象发生变化时调用(比如 InheritedWidget)void didChangeDependencies() {super.didChangeDependencies();print("3.执行了didChangeDependencies方法");}// 4. build: 构建UI界面Widget build(BuildContext context) {print("4.执行了build方法 渲染控件");return Column(children: [Expanded(flex: 80,child: Image.network(// 宽度充满父容器 高度自适应 这个参数标识无穷大width: double.infinity,// 加载网络图片images[index],fit: BoxFit.cover,),),Expanded(flex: 20,child: Center(child: ElevatedButton(style: ButtonStyle(side: MaterialStateProperty.all<BorderSide>(BorderSide(color: Colors.black,width: 2.0,)),),onPressed: () => {setState(() {index = (index + 1) % images.length;})},child: Text("点击切换图片"))),)],);}// 5. didUpdateWidget: 当组件状态改变时(比如父组件传递新的数据),调用此方法void didUpdateWidget(covariant MyHome oldWidget) {super.didUpdateWidget(oldWidget);print("5.执行了didUpdateWidget方法");}// 6. reassemble: 热重载时会调用(开发调试用)void reassemble() {super.reassemble();print("6.执行了reassemble方法(热重载时调用)");}// 7. deactivate: 当组件从树中移除时调用(还没被销毁)void deactivate() {super.deactivate();print("7.执行了deactivate方法");}// 8. dispose: 销毁组件时调用,释放资源void dispose() {print("8.释放资源 执行了dispose方法");super.dispose();}
}

滑动布局

当行列布局如果超出容器后 会出现话花屏的感觉 比如 我某个区间容器是row 布局 但是·是多个文本 ,当数据过长时候 发现竟然不会自动换行 而是渲染花屏

main(){runApp(MaterialApp(home: MyrowLogout(),));
}
class MyrowLogout  extends StatefulWidget {const MyrowLogout ({super.key});State<MyrowLogout > createState() => _MyrowLogoutState();
}class _MyrowLogoutState extends State<MyrowLogout > {Widget build(BuildContext context) {return Row(children: [//此时  文本内容  超出屏幕后 右边会显示花屏Text("我是一条超级长显示的文本内容,哈哈哈哈你好")],);}
}

在这里插入图片描述

当你的文本内容超出一行的宽度时,Row 布局不会自动换行,这也是为什么你会看到渲染失败的黄屏。Row 是一个水平布局控件,默认情况下,它会尝试将所有的子控件在同一行上显示,如果内容超出可用宽度,就会出现布局溢出问题。

要解决这个问题,可以考虑以下几种方法:

**使用 ExpandedFlexible**等动态布局

你可以使用 ExpandedFlexible 控件包裹row布局的子控件 Text,让文本根据屏幕的宽度自动换行并避免超出布局。它们会自动占用 Row 的可用空间,并将文本换行。

main(){runApp(MaterialApp(home: MyrowLogout(),));
}class MyrowLogout extends StatefulWidget {const MyrowLogout({super.key});State<MyrowLogout> createState() => _MyrowLogoutState();
}class _MyrowLogoutState extends State<MyrowLogout> {Widget build(BuildContext context) {return Row(mainAxisAlignment: MainAxisAlignment.center,children: [Expanded( // 使用 Expanded 包裹 Text 控件child: Text("我是一条超级长显示的文本内容,哈哈哈哈你好",style: TextStyle(fontSize: 10),),),Expanded(child: Text("我是一条超级长显示的文本内容,哈哈哈哈你好"),),Expanded(child: Text("我是一条超级长显示的文本内容,哈哈哈哈你好"),),],);}
}

布局依旧是row 对于布局的每个子容器 如果出现无法装载的情况 就会换行

在这里插入图片描述

使用 Wrap 控件

Wrap 是一个专门用于自动换行的控件,它会自动将子控件换到下一行或下一列,以避免布局溢出。对于这种情况,使用 Wrap 来代替 Row 可以很好地解决问题。

main(){runApp(MaterialApp(home: MyrowLogout(),));
}class MyrowLogout extends StatefulWidget {const MyrowLogout({super.key});State<MyrowLogout> createState() => _MyrowLogoutState();
}class _MyrowLogoutState extends State<MyrowLogout> {Widget build(BuildContext context) {return Wrap(// Wrap 会自动换行,当内容超出时children: [Text("我是一条超级长显示的文本内容,哈哈哈哈你好",style: TextStyle(fontSize: 10),),Text("我是一条超级长显示的文本内容,哈哈哈哈你好"),Text("我是一条超级长显示的文本内容,哈哈哈哈你好"),],);}
}

这种效果类似col布局了

在这里插入图片描述

使用 SingleChildScrollView 控件

如果你希望保留 Row 布局,并让超出部分可以水平滚动,而不是换行,可以使用 SingleChildScrollView 来包裹 Row,实现水平滚动。

main(){runApp(MaterialApp(home: MyrowLogout(),));
}class MyrowLogout extends StatefulWidget {const MyrowLogout({super.key});State<MyrowLogout> createState() => _MyrowLogoutState();
}class _MyrowLogoutState extends State<MyrowLogout> {Widget build(BuildContext context) {return SingleChildScrollView(scrollDirection: Axis.horizontal, // 水平滚动child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [Text("我是一条超级长显示的文本内容,哈哈哈哈你好",style: TextStyle(fontSize: 10),),Text("我是一条超级长显示的文本内容,哈哈哈哈你好"),Text("我是一条超级长显示的文本内容,哈哈哈哈你好"),],),);}
}

  • ExpandedFlexible:让文本根据可用空间自动换行,适合你希望内容按比例分配空间的情况。
  • Wrap:适合需要自动换行的场景,不再局限于一行显示。
  • SingleChildScrollView:适合需要水平滚动的场景。

根据你的需求选择合适的布局控件即可避免渲染失败的黄屏问题。

在 Flutter 中,实现滑动区域的内容时,有多种可滑动的视图组件,每个组件在不同的场景下适用,尤其是像你提到的图文应用(如小红书)中,涉及到图片、文本内容的滑动。以下是一些常用的可滑动视图组件及它们的区别:

SingleChildScrollView 适用于内容较少的情况,允许在一个方向上(水平或垂直)滚动其子元素。

  • 适用场景

    • 需要将所有内容包裹在一个滚动区域里。
    • 内容较小,可以一次性加载完成,不需要懒加载或分页加载。
  • 缺点

    • 不能在需要大量数据滚动时使用,因为它不会在视图外部丢弃不可见的子元素,可能会导致性能问题。

ListView(动态页面推荐)

ListView 是最常用的滚动组件之一,适合垂直方向上大量的可滚动内容,通常用于显示列表数据。

  • 适用场景

    • 适用于垂直方向的长列表内容,比如新闻列表、图片集等。
    • 支持懒加载,即只渲染当前视口内的元素,不会加载所有内容,性能表现优越。
    • 支持无限滚动和分段加载。
  • 种类

    • ListView.builder():适用于大量数据,动态创建视图。
    • ListView.separated():用于在列表项之间添加分割线。
    • ListView.custom():高度自定义列表的行为。
  • 示例

    静态

    ListView(padding: const EdgeInsets.all(8),children: <Widget>[Container(height: 50,color: Colors.amber[600],child: const Center(child: Text('Entry A')),),Container(height: 50,color: Colors.amber[500],child: const Center(child: Text('Entry B')),),Container(height: 50,color: Colors.amber[100],child: const Center(child: Text('Entry C')),),],
    )
    

    动态(懒加载数据 视图到哪里才加载哪里)

          ListView.builder(itemCount: 1000,  // 列表项的数量itemBuilder: (context, index) {return  Container(height: 50,color: Colors.amber[500],child: Center(child: Text(' 区域 ')),);},)
    

GridView

GridView 适用于以网格形式显示内容,比如图片墙、商品展示等。

  • 适用场景

    • 适合在横向和纵向上都需要滑动的网格布局场景,如图片展示、商品卡片。
    • 支持懒加载,仅渲染当前视图内的元素。
  • 种类

    • GridView.builder():动态构建网格项,适合大量数据。
    • GridView.count():预设固定数量的列。
    • GridView.custom():自定义网格行为。
  • 示例

    GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, // 每行两列),itemCount: 20,itemBuilder: (context, index) {return Card(child: Column(children: [Image.network('https://example.com/image.jpg'),Text('商品 $index'),],),);},
    )
    

PageView (实现轮播图)

PageView 用于水平或垂直方向的分页滑动视图,比如显示类似于轮播图、教程页面的效果。

  • 适用场景

    • 用于展示分屏效果,比如分页显示内容、图片轮播。
    • 可以自定义滑动动画、页面指示器。
  • 示例

    PageView(children: [Image.network('https://example.com/image1.jpg'),Image.network('https://example.com/image2.jpg'),Image.network('https://example.com/image3.jpg'),],
    )
    

**CustomScrollView + Slivers ** (推荐)

CustomScrollView 是 Flutter 中非常灵活的可滚动区域,用于构建复杂的滚动效果。Sliver 是构建这种滚动区域的基础,它允许创建灵活的自定义布局,比如带有吸顶效果的 SliverAppBar 或自定义的滚动动画。

  • 适用场景

    • 适用于复杂的滚动效果,比如头部吸附、分段显示列表、网格与列表组合等。
    • 可以组合不同类型的 Sliver,如 SliverListSliverGridSliverAppBar
    • 适用于构建如小红书这样复杂的 UI 布局。
  • 示例

    CustomScrollView(slivers: [SliverAppBar(expandedHeight: 200.0,flexibleSpace: FlexibleSpaceBar(title: Text('小红书风格页面'),background: Image.network('https://example.com/banner.jpg', fit: BoxFit.cover),),),SliverList(delegate: SliverChildBuilderDelegate((BuildContext context, int index) {return ListTile(title: Text('Item $index'),);},childCount: 50,),),],
    )
    

NestedScrollView

NestedScrollView 允许在一个页面中同时包含两个滚动视图,通常用于顶部有 SliverAppBar 并且页面内部还有可以滚动的内容,比如一个列表或网格。

  • 适用场景

    • 适用于需要同时滚动头部(如 AppBar)和内容(如列表或网格)的场景。
    • 实现类似于下拉刷新的效果,或头部滑动隐藏与显示效果。
  • 示例

    NestedScrollView(headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {return <Widget>[SliverAppBar(expandedHeight: 200.0,floating: false,pinned: true,flexibleSpace: FlexibleSpaceBar(title: Text("NestedScrollView Demo"),),),];},body: ListView.builder(itemCount: 50,itemBuilder: (BuildContext context, int index) {return ListTile(title: Text('Item $index'),);},),
    )
    

Scrollable

Scrollable 是最基础的滚动组件,几乎所有其他滚动组件(如 ListViewGridView)都基于它构建。一般情况下,开发者不会直接使用 Scrollable,而是使用封装好的组件。

  • 适用场景

    • 在需要高度自定义滚动行为时使用。
  • 示例

    Scrollable(axisDirection: AxisDirection.down,viewportBuilder: (context, position) {return Viewport(offset: position,slivers: [SliverToBoxAdapter(child: Text('这是一个自定义滚动视图'),),],);},
    )
    

结论

  • 单一页面滑动:如果页面内容较少或需要垂直滚动,SingleChildScrollView 是一个简单的选择,但当内容量大时,建议使用 ListViewGridView
  • 分页滑动PageView 适合实现类似轮播图或教程分屏的效果。
  • 复杂布局:如果你需要构建类似于小红书的复杂页面布局,可以考虑使用 CustomScrollView,结合 SliverListSliverGrid 等构建高度灵活的滑动内容。
  • 头部和内容同时滚动NestedScrollView 适合在页面中既有滚动头部,又有内容滚动的情况。

根据你的需求,选择最合适的组件可以提升开发效率和用户体验。

路由跳转

Navigator

Navigator 是一个全局访问点,用于推送和弹出路由。它是 Flutter 中管理页面导航的中央对象。

和vue,react一样,flutter的路由也是路由栈,一个页面一个页面的往上叠

  • Navigator.push()
    这个方法会将一个新的路由添加到路由栈的顶部,并触发页面转换动画。它返回一个 Future,该 Future 在新页面通过 Navigator.pop 被弹出时完成。

    Navigator.push(context,MaterialPageRoute(builder: (context) => NewScreen()),
    ).then((value) {// 新页面通过 Navigator.pop 返回的结果
    });
  • Navigator.pop()
    这个方法用于从路由栈中移除当前路由,并返回到前一个路由。如果提供了参数,它将作为结果返回给前一个页面。

    Navigator.pop(context, result);
    
  • Navigator.popUntil()
    这个方法弹出当前路由,直到遇到符合给定条件的路由。这允许你一次性弹出多个路由。

    Navigator.popUntil(context, (route) {return route.settings.name == 'target_route_name';
    });
    
  • Navigator.canPop()
    这个方法返回一个布尔值,指示当前路由是否可以被弹出。

    final canPop = Navigator.canPop(context);
    

Route

Route 是表示导航路径的基类。它定义了路由的基本接口,包括 buildContent(), popped(), willShow(), didShow() 等方法。

  • PageRoute
    PageRouteRoute 的具体实现,它表示一个全屏页面,并提供了页面转换动画。PageRoute 需要被实现以创建自定义的路由。

    class MyCustomRoute extends PageRoute {Widget buildContent(BuildContext context) {return NewScreen();}Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {// 自定义过渡动画return FadeTransition(opacity: animation, child: child);}
    }
    
  • MaterialPageRoute
    MaterialPageRoutePageRoute 的具体实现,它提供了 Material Design 风格的过渡动画。

    MaterialPageRoute(builder: (context) => NewScreen(),settings: RouteSettings(name: 'new_screen_route'),
    )
    

PageRouteBuilder

PageRouteBuilder 允许你以编程方式构建路由,而不是在 MaterialApproutes 字典中静态定义。

Navigator.push(context,PageRouteBuilder(pageBuilder: (context, animation, secondaryAnimation) => NewScreen(),transitionsBuilder: (context, animation, secondaryAnimation, child) {return FadeTransition(opacity: animation,child: child,);},),
);

Navigator.restorablePush() 方法

这个方法类似于 Navigator.push(),但它允许你保存和恢复路由状态。

Navigator.restorablePush(context,MaterialPageRoute(builder: (context) => NewScreen()),
);

ModalRoute

ModalRoutePageRoute 的子类,表示一个模态路由。它提供了当前路由的状态和信息,如 isCurrent, isFirst, isLast 等。

final route = ModalRoute.of(context);
if (route.isCurrent) {// 当前路由是显示的路由
}

Navigator.onGenerateRoute() 方法

MaterialAppCupertinoApp 中,你可以使用 onGenerateRoute 回调来动态生成路由。

MaterialApp(onGenerateRoute: (settings) {if (settings.name == '/path') {return MaterialPageRoute(builder: (context) => NewScreen());}return null;},
);

Navigator.obscureBehavior 属性

这个属性定义了当新路由出现时,如何模糊或隐藏当前的路由。它接受一个 ObscureBehavior 值,可以是 ObscureBehavior.none, ObscureBehavior.fade, ObscureBehavior.blur 等。

Navigator(obscureBehavior: ObscureBehavior.fadeIn,pages: [MaterialPage(child: HomeScreen())],
);

路由传递参数

你可以通过 RouteSettings 来传递参数给下一个路由。

Navigator.push(context,MaterialPageRoute(builder: (context) => NewScreen(),settings: RouteSettings(arguments: 'some arguments'),),
).then((value) {// 处理返回值
});// 在新页面中获取参数
final args = ModalRoute.of(context)!.settings.arguments;

路由结果

你可以在弹出路由时返回一个结果给前一个路由。

// 在新页面中
Navigator.pop(context, 'result');// 在前一个页面中
Navigator.push(context,MaterialPageRoute(builder: (context) => NewScreen(),),
).then((value) {if (value == 'result') {// 处理结果}
});

封装一个路由管理类

现在的路由跳转时api 编程式跳转,并且便于进行权限校验

        Padding(padding: const EdgeInsets.all(10.0),child: SizedBox(height: 300,child: ListView(scrollDirection: Axis.horizontal,children: cards.map((card) {return CardAnimationHover(card: card,width: 200,showAnimation: false,onTap: () {Navigator.push(context,MaterialPageRoute(builder: (context) => DetailsPage(title: card['header'].toString(),coverUrl: card['image'].toString(),),),);},);}).toList(),),),),

跳转具体页面


/// 详情页面
class DetailsPage extends StatefulWidget {
// 确保 title 在构造函数中被初始化String title;
//   封面urlString coverUrl;DetailsPage({super.key, required this.title, required this.coverUrl}  );State<DetailsPage> createState() => _DetailsPageState();
}class _DetailsPageState extends State<DetailsPage> with SingleTickerProviderStateMixin {late AnimationController _controller;void initState() {super.initState();_controller = AnimationController(vsync: this);}void dispose() {_controller.dispose();super.dispose();}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(leading: const BackButton(),actions: [IconButton(icon: const Icon(Icons.search),tooltip: '查找',onPressed: () {ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('This is a snackbar')));},),IconButton(onPressed: (){Navigator.pop(context);}, icon: const Icon(Icons.more_vert))],title: Text(widget.title),),body: SafeArea(child: Column(children: [// 封面Container(height: 200,width: double.infinity,decoration: BoxDecoration(borderRadius: BorderRadius.circular(16.0), // 设置圆角半径),child: Image.network(widget.coverUrl,fit: BoxFit.fill),),Expanded(child: Text("这是详细页面"))],)));}
}

除开构造器获取路由传递的数值还可以生命周期获取

import 'package:flutter/material.dart';class DetailsPage extends StatefulWidget {_DetailsPageState createState() => _DetailsPageState();
}class _DetailsPageState extends State<DetailsPage> {String? title;String? coverUrl;void initState() {super.initState();// 在初始化时获取传递的参数WidgetsBinding.instance.addPostFrameCallback((_) {final args = ModalRoute.of(context)?.settings.arguments as DetailPageArgs?;if (args != null) {setState(() {title = args.title;coverUrl = args.coverUrl;});}});}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(title ?? 'Details')),body: Center(child: coverUrl != null? Image.network(coverUrl!): const Text('No cover image available'),),);}
}

但是一般开发会封装一个专门的路由跳转的类 (鉴权,错误页面处理等)

基于navigator api封装的路由管理类


import 'package:flutter/material.dart';class AppRouter {// 跳转到指定路由并传递参数static Future<T?> navigateTo<T>(BuildContext context, String routeName, {Object? arguments}) {return Navigator.pushNamed<T>(context, routeName, arguments: arguments);}// 跳转到指定路由并清除之前所有的路由(通常用于登录页面)static Future<T?> navigateAndReplaceAll<T>(BuildContext context, String routeName, {Object? arguments}) {return Navigator.pushNamedAndRemoveUntil<T>(context, routeName, (route) => false, arguments: arguments);}// 跳转到指定路由并替换当前路由static Future<T?> navigateAndReplace<T>(BuildContext context, String routeName, {Object? arguments}) {return Navigator.pushReplacementNamed<T, dynamic>(context, routeName,arguments: arguments);}// 返回上一页并传递数据static void goBack<T>(BuildContext context, [T? result]) {Navigator.pop<T>(context, result);}// 判断是否可以返回static bool canGoBack(BuildContext context) {return Navigator.canPop(context);}
}

路由类

根据不同路由返回不同的组件

// 路由生成器类
class RouteGenerator {static Route<dynamic> generateRoute(RouteSettings settings) {// 获取传递的参数final args = settings.arguments;switch (settings.name) {case '/':// 验证参数类型并传递if (args != null) {return _errorRoute();}// 参数不正确,跳转错误页面return MaterialPageRoute(builder: (_) => const Myhome());case '/details':// 期待传入一个带多个属性的对象(比如一个 Map 或自定义类)if (args is DetailPageArgs) {return MaterialPageRoute(builder: (_) => DetailsPage(title: args.title,coverUrl: args.coverUrl,));}return _errorRoute();// case '/login'://   return MaterialPageRoute(builder: (_) => LoginScreen());default:return _errorRoute();}}// 错误路由页面static Route<dynamic> _errorRoute() {return MaterialPageRoute(builder: (_) => Scaffold(appBar: AppBar(title: const Text('出错啦')),body: const Center(child: Text('Page not found!',style: TextStyle(fontSize: 30),)),),);}
}

项目入口main中进行配置

void main() {runApp( MyApp());
}class MyApp extends StatelessWidget {Widget build(BuildContext context) {return const MaterialApp(title: '一乐动漫',initialRoute: '/',onGenerateRoute: RouteGenerator.generateRoute, // 使用路由管理器);}
}

具体使用

   onTap: () {AppRouter.navigateTo(context, '/details', arguments:DetailPageArgs(title: card['header'].toString(), coverUrl: card['image'].toString()));},

页面返回时携带数据

// 跳转时传递参数
AppRouter.navigateTo(context, '/details', arguments: 'Some data').then((result) {// 接收返回的结果if (result != null) {print('返回结果: $result');}
});//跳转的具体页面 点击返回的
Navigator.pop(context, 'This is the result');

抽屉

Flutter 提供了一个专门用于实现这种侧边菜单抽屉的控件,叫做 Drawer。它可以和 Scaffold 结合使用,提供左侧或右侧的抽屉菜单(类似于移动应用中常见的滑动菜单)。

典型的 Drawer 使用示例

以下是一个在 Flutter 中使用 Drawer 的基本示例。点击左上角的菜单图标(hamburger icon)可以打开从左侧滑出的抽屉菜单。

import 'package:flutter/material.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {Widget build(BuildContext context) {return MaterialApp(title: 'Drawer Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: HomePage(),);}
}class HomePage extends StatelessWidget {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Drawer Demo'),),// 左侧抽屉菜单drawer: Drawer(child: ListView(padding: EdgeInsets.zero,children: <Widget>[DrawerHeader(decoration: BoxDecoration(color: Colors.blue,),child: Text('Menu',style: TextStyle(color: Colors.white,fontSize: 24,),),),ListTile(leading: Icon(Icons.home),title: Text('Home'),onTap: () {// 点击菜单后关闭抽屉Navigator.pop(context);},),ListTile(leading: Icon(Icons.settings),title: Text('Settings'),onTap: () {Navigator.pop(context);},),ListTile(leading: Icon(Icons.logout),title: Text('Logout'),onTap: () {Navigator.pop(context);},),],),),body: Center(child: Text('Swipe from left or click the menu icon to open drawer'),),);}
}

关键点解析:

  • Scaffold: Flutter 提供的基本页面布局结构,Scaffold 可以帮助你快速搭建包含 AppBar、Drawer、BottomNavigationBar 等常见 UI 组件的页面。

  • drawer: Scaffolddrawer 属性允许你定义从左侧滑出的抽屉。可以在 Drawer 中放置任何 widget,常见的是使用 ListView 结合 ListTile 来创建菜单项。

  • DrawerHeader: 用于在抽屉顶部显示自定义内容(如头像、用户名等)。

  • 关闭抽屉: 使用 Navigator.pop(context) 关闭抽屉菜单。

从右侧弹出的抽屉

如果你想要从右侧滑出菜单,可以使用 ScaffoldendDrawer 属性。它的用法与 drawer 类似,但菜单会从右侧弹出。

Scaffold(appBar: AppBar(title: Text('End Drawer Demo'),),// 右侧抽屉endDrawer: Drawer(child: ListView(padding: EdgeInsets.zero,children: <Widget>[DrawerHeader(decoration: BoxDecoration(color: Colors.blue,),child: Text('Right Menu',style: TextStyle(color: Colors.white,fontSize: 24,),),),ListTile(leading: Icon(Icons.home),title: Text('Home'),onTap: () {Navigator.pop(context);},),ListTile(leading: Icon(Icons.settings),title: Text('Settings'),onTap: () {Navigator.pop(context);},),],),),body: Center(child: Text('Swipe from right or click the menu icon to open end drawer'),),
)

网络请求和json解析

在 Flutter 中,网络请求和 JSON 数据处理是非常常见的需求。通过使用 http 包进行网络请求,以及结合 Dart 自带的 dart:convert 库处理 JSON 数据,可以非常方便地实现与服务端的交互。下面我将详细介绍网络请求和 JSON 处理的具体步骤。

1. 导入依赖

在 Flutter 中使用 http 库来发起网络请求。在 pubspec.yaml 中添加依赖:

dependencies:http: ^0.13.3

然后在代码中导入 httpdart:convert

import 'package:http/http.dart' as http;
import 'dart:convert';

2. 发起网络请求

(1) GET 请求

GET 请求用于从服务器获取数据。以下是一个简单的 GET 请求示例:

Future<void> fetchData() async {final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));if (response.statusCode == 200) {// 请求成功,将响应体解析为 JSONvar jsonResponse = jsonDecode(response.body);print('Title: ${jsonResponse['title']}');} else {// 请求失败,抛出异常throw Exception('Failed to load data');}
}

http.get 方法返回一个 Future<http.Response> 对象,异步等待请求完成。我们可以通过 jsonDecode 函数将返回的 JSON 数据转为 Dart 的 Map 或 List。

(2) POST 请求

POST 请求用于向服务器发送数据,例如提交表单。以下是一个简单的 POST 请求示例:

Future<void> postData() async {final response = await http.post(Uri.parse('https://jsonplaceholder.typicode.com/posts'),headers: {'Content-Type': 'application/json; charset=UTF-8'},body: jsonEncode(<String, String>{'title': 'Flutter','body': 'Network request example','userId': '1',}),);if (response.statusCode == 201) {// 请求成功,解析响应var jsonResponse = jsonDecode(response.body);print('Post created: ${jsonResponse['id']}');} else {// 请求失败,抛出异常throw Exception('Failed to create post');}
}

在 POST 请求中,body 是通过 jsonEncode 将 Dart 对象转为 JSON 字符串,然后发送给服务器。响应的处理与 GET 请求类似。

3. JSON 处理

(1) 解析 JSON 字符串

dart:convert 库中的 jsonDecode 函数可以将 JSON 字符串转换为 Dart 对象。

String jsonString = '{"name": "John", "age": 30}';
Map<String, dynamic> user = jsonDecode(jsonString);print('Name: ${user['name']}');
print('Age: ${user['age']}');

在上面的例子中,jsonDecode 会将 JSON 字符串解析为 Map<String, dynamic> 对象。

(2) 将 Dart 对象转换为 JSON 字符串

jsonEncode 函数可以将 Dart 对象转换为 JSON 字符串,通常用于发送 POST 请求时。

Map<String, dynamic> user = {'name': 'John','age': 30,
};String jsonString = jsonEncode(user);
print(jsonString); // 输出 {"name":"John","age":30}

4. 结合模型类处理 JSON

为了简化代码,并确保 JSON 解析和序列化的正确性,建议将 JSON 转换为模型类对象。以下是一个简单的例子。

(1) 创建模型类
class Post {final int id;final String title;final String body;Post({required this.id, required this.title, required this.body});// 工厂方法:从 JSON 构造 Post 对象factory Post.fromJson(Map<String, dynamic> json) {return Post(id: json['id'],title: json['title'],body: json['body'],);}// 将 Post 对象转换为 JSONMap<String, dynamic> toJson() {return {'id': id,'title': title,'body': body,};}
}
(2) 使用模型类解析 JSON
Future<void> fetchPost() async {final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));if (response.statusCode == 200) {// 解析 JSON 并创建 Post 对象var jsonResponse = jsonDecode(response.body);Post post = Post.fromJson(jsonResponse);print('Post title: ${post.title}');} else {throw Exception('Failed to load post');}
}
(3) 将对象转换为 JSON
Post post = Post(id: 1, title: 'Flutter', body: 'Network request example');
String jsonPost = jsonEncode(post.toJson());
print(jsonPost);

通过将 JSON 数据映射到模型类,可以使代码更加清晰、易于维护。

5. 异常处理

在进行网络请求时,可能会出现各种错误,例如网络不可用、请求超时等。可以通过 try-catch 进行异常捕获。

Future<void> fetchData() async {try {final response = await http.get(Uri.parse('https://example.com/data'));if (response.statusCode == 200) {var jsonResponse = jsonDecode(response.body);print(jsonResponse);} else {print('Server error: ${response.statusCode}');}} catch (error) {print('Error: $error');}
}

没错!在 Flutter 中,尽管 http 模块是内置的网络请求解决方案,但很多开发者更倾向于使用功能更丰富的第三方库,比如 DioDio 是一个强大且易用的网络请求库,提供了丰富的功能,如拦截器、全局配置、文件上传和下载、取消请求等。

http 插件dio

为什么使用 Dio?

  1. 更强的功能:Dio 支持网络请求的拦截器、全局配置、文件上传/下载、表单数据提交等。
  2. 错误处理更灵活:Dio 提供了更全面的错误处理机制,方便管理和追踪各种类型的错误。
  3. 更好的性能:Dio 在某些场景下比 http 更加优化,并且支持配置请求超时时间和请求重试等功能。
  4. 容易集成拦截器:可以轻松添加拦截器以处理请求、响应、错误等,便于实现例如日志记录、权限校验等功能。

1. 在 pubspec.yaml 中添加 Dio 依赖

dependencies:dio: ^5.3.1

然后在代码中导入 Dio:

import 'package:dio/dio.dart';

2. 基本使用

(1) 发起 GET 请求
Future<void> fetchData() async {Dio dio = Dio();try {Response response = await dio.get('https://jsonplaceholder.typicode.com/posts/1');print('Response data: ${response.data}');} catch (e) {print('Error occurred: $e');}
}

dio.get() 返回一个 Response 对象,其中 response.data 可以直接访问返回的数据,Dio 会自动处理 JSON 解码。


void main() {test('测试dio网络请求', () async {Dio dio = Dio();try {Response response = await dio.get('http://localhost:8080/api/users');/*** 响应数据: {t: {name: 测试对象, age: 666}, msg: success, code: 0}*/print('响应数据: ${response.data}');// 直接使用 response.datavar data = response.data;print(data);// 如果可以直接读取dio解析的json对象,但是这样的话 不易阅读if (data['code'] == 0) {var t = data['t'];print('名称: ${t['name']}, 年龄: ${t['age']}');} else {print('请求失败: ${data['msg']}');}} catch (e) {print('错误异常: $e');}});test('测试dio网络请求json和dart对象互转', () async {Dio dio = Dio();try {Response response = await dio.get('http://localhost:8080/api/users');/*** 响应数据: {t: {name: 测试对象, age: 666}, msg: success, code: 0}*/print('响应数据: ${response.data}');// 使用模型类解析数据var apiResponse = ApiResponse.fromJson(response.data);print(apiResponse);// 如果需要进一步处理数据if (apiResponse.code == 0) {print('名称: ${apiResponse.t.name}, 年龄: ${apiResponse.t.age}');} else {print('请求失败: ${apiResponse.msg}');}} catch (e) {print('错误异常: $e');}});
}
class ApiResponse {final int code;final String msg;final User t;ApiResponse({required this.code, required this.msg, required this.t});factory ApiResponse.fromJson(Map<String, dynamic> json) {return ApiResponse(code: json['code'],msg: json['msg'],t: User.fromJson(json['t']),);}
}class User {final String name;final int age;User({required this.name, required this.age});factory User.fromJson(Map<String, dynamic> json) {return User(name: json['name'],age: json['age'],);}
}
(2) 发起 POST 请求
Future<void> postData() async {Dio dio = Dio();try {Response response = await dio.post('https://jsonplaceholder.typicode.com/posts',data: {'title': 'Flutter Dio','body': 'This is a Dio post request example','userId': 1,},);print('Response data: ${response.data}');} catch (e) {print('Error occurred: $e');}
}

在 POST 请求中,数据可以通过 data 参数发送,并且支持自动将 Dart 的 Map 对象转为 JSON。

3. 使用拦截器

Dio 提供了拦截器来在请求发出前或响应返回时执行自定义逻辑,这对于处理 token、全局错误处理等非常有用。

添加请求拦截器和响应拦截器
Dio dio = Dio();dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {print('Request: ${options.method} ${options.path}');return handler.next(options); // 继续执行请求},onResponse: (response, handler) {print('Response: ${response.statusCode}');return handler.next(response); // 继续执行响应},onError: (DioError e, handler) {print('Error: ${e.message}');return handler.next(e); // 继续处理错误},
));

通过拦截器,您可以在网络请求的各个阶段执行自定义逻辑,例如在每个请求前自动添加身份验证 token,或者在响应中统一处理错误。

4. 全局配置

Dio 可以为所有请求设置全局的配置,例如超时时间、请求头等:

Dio dio = Dio(BaseOptions(baseUrl: 'https://jsonplaceholder.typicode.com',connectTimeout: Duration(seconds: 5),receiveTimeout: Duration(seconds: 5),headers: {'Content-Type': 'application/json; charset=UTF-8',},
));Future<void> fetchData() async {try {Response response = await dio.get('/posts/1');print('Response data: ${response.data}');} catch (e) {print('Error occurred: $e');}
}

在这里,我们通过 BaseOptions 为 Dio 实例设置了基础配置,后续的每个请求都将继承这些配置。

5. 文件上传和下载

(1) 文件上传

Dio 支持表单数据提交,非常适合用于上传文件:

Future<void> uploadFile(String filePath) async {Dio dio = Dio();FormData formData = FormData.fromMap({'file': await MultipartFile.fromFile(filePath, filename: 'upload.png'),});try {Response response = await dio.post('https://example.com/upload',data: formData,);print('File uploaded: ${response.data}');} catch (e) {print('Upload error: $e');}
}

FormData 可以处理多种类型的数据,包括文件上传。MultipartFile.fromFile() 方法会将本地文件转换为上传的表单文件。

(2) 文件下载
Future<void> downloadFile() async {Dio dio = Dio();try {await dio.download('https://example.com/file.zip','/path/to/save/file.zip',onReceiveProgress: (received, total) {if (total != -1) {print('Downloading: ${(received / total * 100).toStringAsFixed(0)}%');}},);} catch (e) {print('Download error: $e');}
}

Dio 提供了 download 方法用于文件下载,并且可以通过 onReceiveProgress 回调函数实时获取下载进度。

6. 取消请求

Dio 提供了取消请求的功能,非常适合处理用户发起多个重复请求或长时间等待的操作。可以通过 CancelToken 来控制请求的取消。

CancelToken cancelToken = CancelToken();Future<void> fetchData() async {Dio dio = Dio();try {Response response = await dio.get('https://jsonplaceholder.typicode.com/posts/1',cancelToken: cancelToken,);print('Response data: ${response.data}');} catch (e) {if (CancelToken.isCancel(e)) {print('Request cancelled');} else {print('Error: $e');}}
}// 在需要的时候取消请求
cancelToken.cancel('Request cancelled by user');

封装

和axios一样可以封装实列使用

import 'package:dio/dio.dart';class DioClient {static DioClient? _instance;late Dio _dio;// 私有构造函数DioClient._internal() {_dio = Dio(BaseOptions(baseUrl: "https://your-api.com", // 设置基础URLconnectTimeout: const Duration(seconds: 10),receiveTimeout: const Duration(seconds: 10),headers: {'Content-Type': 'application/json',},));// 添加拦截器_dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {// 在请求发送前做一些处理,如添加公共tokenoptions.headers['Authorization'] = 'Bearer your_token';print('REQUEST[${options.method}] => PATH: ${options.path}');handler.next(options); // 继续下一个拦截器},onResponse: (response, handler) {// 处理响应print('RESPONSE[${response.statusCode}] => PATH: ${response.requestOptions.path}');handler.next(response);},onError: (DioError e, handler) {// 处理错误print('ERROR[${e.response?.statusCode}] => PATH: ${e.requestOptions.path}');handler.next(e); // 继续下一个拦截器},));// 可选:日志拦截器,用于在开发时打印请求和响应_dio.interceptors.add(LogInterceptor(request: true,requestHeader: true,requestBody: true,responseHeader: true,responseBody: true,error: true,));}// 单例模式static DioClient getInstance() {_instance ??= DioClient._internal();return _instance!;}// GET 请求Future<Response> get(String path, {Map<String, dynamic>? queryParams}) async {try {Response response = await _dio.get(path, queryParameters: queryParams);return response;} catch (e) {return Future.error(_handleError(e));}}// POST 请求Future<Response> post(String path, {Map<String, dynamic>? data}) async {try {Response response = await _dio.post(path, data: data);return response;} catch (e) {return Future.error(_handleError(e));}}// PUT 请求Future<Response> put(String path, {Map<String, dynamic>? data}) async {try {Response response = await _dio.put(path, data: data);return response;} catch (e) {return Future.error(_handleError(e));}}// DELETE 请求Future<Response> delete(String path, {Map<String, dynamic>? data}) async {try {Response response = await _dio.delete(path, data: data);return response;} catch (e) {return Future.error(_handleError(e));}}// Token 自动刷新逻辑(可根据具体情况修改)Future<void> _refreshToken() async {// 刷新 token 的逻辑// 如果 token 刷新成功,更新请求头中的 token_dio.options.headers['Authorization'] = 'Bearer new_token';}// 处理错误String _handleError(dynamic error) {if (error is DioError) {switch (error.type) {case DioErrorType.connectTimeout:return "Connection Timeout!";case DioErrorType.sendTimeout:return "Send Timeout!";case DioErrorType.receiveTimeout:return "Receive Timeout!";case DioErrorType.response:return "Received invalid status code: ${error.response?.statusCode}";case DioErrorType.cancel:return "Request to API server was cancelled";case DioErrorType.other:return "Connection to API server failed due to internet connection";default:return "Unexpected error occured";}} else {return "Unexpected error occured";}}
}

实列化
DioClient dioClient = DioClient.getInstance();
发送请求
var response = await dioClient.get(‘/api/v1/resource’);

总结

相比 http 库,Dio 提供了更丰富的功能,尤其是在处理拦截器、全局配置、文件上传和下载、取消请求等方面。通过使用 Dio,你可以更方便地管理复杂的网络请求逻辑,并保持代码简洁和易维护。

你可以根据项目需求选择适合的网络请求库,但如果你的项目复杂度较高且需要更多的控制,Dio 会是一个非常合适的选择。

样式

flutter的每个控件的样式类都不一样,很容易记混,所以进行总结

在 Flutter 中,控件样式的定义是非常灵活的,有些控件有类似的样式属性,但不同类型的控件又可能有特定的样式定义。为了方便你记忆,我将根据控件的类型对常用的样式属性进行归纳总结。

1. 通用样式属性

以下属性是 Flutter 中大部分控件共享的样式属性,尤其是涉及到 ContainerTextButton 等常见控件:
通用样式属性在 Flutter 中适用于许多控件,尤其是像 ContainerTextButton 等控件,几乎所有的 UI 组件都可以设置一些通用的样式属性。为了帮助你更详细地理解通用样式属性,我将对每个属性进行详细解释,并提供相应的代码示例。

color

color 是设置控件的背景颜色的属性。它常见于 ContainerTextButtonScaffold 等控件。

用法:
Container(color: Colors.blue,  // 设置背景颜色为蓝色child: Text('This is a Container'),
)
注意:
  • 有些控件需要通过 decoration 来设置背景颜色,例如 Container 中,当 decoration 设置时,不能直接使用 color 属性。
  • Text 控件的颜色需要通过 TextStylecolor 属性来设置。
padding

padding 是设置控件内部内容的边距(内边距)。通过 EdgeInsets 来定义四个方向的距离。

用法:
Container(padding: EdgeInsets.all(16.0),  // 设置四周内边距为16像素color: Colors.grey,child: Text('This is a padded Container'),
)
常见的 EdgeInsets 构造函数:
  • EdgeInsets.all(double value):四个方向的边距相同。
  • EdgeInsets.symmetric({double vertical, double horizontal}):设置水平或垂直方向的对称内边距。
  • EdgeInsets.only({double left, double top, double right, double bottom}):分别设置某个方向的边距。
margin

margin 是设置控件外部与其他控件之间的间距(外边距)。与 padding 类似,也使用 EdgeInsets 进行定义。

用法:
Container(margin: EdgeInsets.all(20.0),  // 设置四周外边距为20像素color: Colors.green,child: Text('This Container has a margin'),
)
注意:
  • margin 是容器之外的空间,而 padding 是容器内部的空间。
alignment

alignment 用于控制容器内子控件的对齐方式。常用于 ContainerAlign 等控件。

用法:
Container(alignment: Alignment.center,  // 将子控件居中对齐color: Colors.yellow,child: Text('Centered text'),
)
常见的 Alignment 常量:
  • Alignment.center:子控件居中。
  • Alignment.topLeft:子控件左上角对齐。
  • Alignment.bottomRight:子控件右下角对齐。
细节:

Alignment 是一个 2D 平面的坐标系,中心为 (0,0),向左为负数,向右为正数,向上为负数,向下为正数。你也可以通过 Alignment(x, y) 自定义位置。

. decoration

decoration 属性通过 BoxDecoration 来设置更加丰富的样式,适用于 Container 等控件。它可以设置背景颜色、背景图像、圆角、阴影、边框等。

用法:
Container(decoration: BoxDecoration(color: Colors.red,  // 设置背景颜色borderRadius: BorderRadius.circular(10),  // 设置圆角boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.5),  // 阴影颜色offset: Offset(2, 4),  // 阴影偏移blurRadius: 5,  // 阴影模糊半径),],),child: Text('Decorated Container'),
)
其他属性:
  • border:设置边框样式。
  • gradient:设置渐变背景。
  • image:设置背景图片,使用 DecorationImage
注意:

如果 Container 同时设置了 colordecorationcolor 会被忽略。

widthheight

widthheight 用于设置控件的宽度和高度,通常用于容器控件如 ContainerSizedBox

用法:
Container(width: 200.0,  // 宽度 200 像素height: 100.0, // 高度 100 像素color: Colors.blue,child: Center(child: Text('Fixed size container')),
)

如果标识沾满 ,无限大使用double.infinity, 源码是1.0/0.0

注意:
  • 如果 Container 的子控件有固定大小,那么 widthheight 可能会受到子控件的影响。
constraints

constraints 属性通过 BoxConstraints 设置控件的尺寸约束,如最小宽度、最大高度等。

用法:
Container(constraints: BoxConstraints(minWidth: 100,  // 最小宽度maxWidth: 200,  // 最大宽度minHeight: 50,  // 最小高度maxHeight: 150, // 最大高度),color: Colors.orange,child: Text('Constrained Container'),
)
常用的 BoxConstraints
  • BoxConstraints.tight(Size size):强制控件固定尺寸。
  • BoxConstraints.loose(Size size):允许控件小于指定尺寸。
  • BoxConstraints.expand():扩展控件以占据所有可用空间。
transform

transform 用于在控件绘制时进行几何变换,包括旋转、缩放、平移等。它接收一个 Matrix4 对象来定义变换方式。

用法:
Container(color: Colors.purple,transform: Matrix4.rotationZ(0.1),  // 绕 Z 轴旋转child: Text('Rotated Container'),
)
常见变换类型:
  • Matrix4.translationValues(double x, double y, double z):平移。
  • Matrix4.rotationZ(double radians):绕 Z 轴旋转。
  • Matrix4.diagonal3Values(double x, double y, double z):缩放。
注意:

transform 影响控件的渲染位置,但不会改变它实际的布局空间。

child

child 是几乎所有容器类控件中都有的属性,表示容器内部的子控件。大多数情况下,容器类控件只能包含一个子控件,如果需要包含多个子控件,可以使用布局控件如 ColumnRow 等。

用法:
Container(color: Colors.teal,child: Text('This is a child widget'),
)
decorationforegroundDecoration
  • decoration:用于设置控件背景的装饰样式,如背景颜色、边框、阴影等。
  • foregroundDecoration:和 decoration 类似,但应用在内容的前景(覆盖在 child 之上)。
用法:
Container(decoration: BoxDecoration(color: Colors.yellow,border: Border.all(color: Colors.red, width: 2),),foregroundDecoration: BoxDecoration(color: Colors.black.withOpacity(0.5), // 在前景添加半透明黑色覆盖层),child: Text('Container with foreground decoration'),
)

2. 文本样式 (TextStyle)

文本控件 (Text) 的样式属性,定义了字体、大小、颜色等。

  • fontSize:字体大小。

    fontSize: 16.0
    
  • fontWeight:字体粗细,可使用 FontWeight.boldFontWeight.w400

    fontWeight: FontWeight.bold
    
  • color:文本颜色。

    color: Colors.black
    
  • fontFamily:指定字体族。

    fontFamily: 'Roboto'
    
  • letterSpacing:字母间距。

    letterSpacing: 2.0
    
  • decoration:文本装饰,如下划线、删除线等。

    decoration: TextDecoration.underline
    
  • height:行高,通常是字体大小的倍数。

    height: 1.5
    

3. 按钮样式

Flutter 的按钮控件(如 ElevatedButtonTextButtonOutlinedButton)有统一的样式系统,通过 ButtonStyle 来定义。常用的按钮样式属性有:

  • backgroundColor:按钮背景颜色。

    backgroundColor: MaterialStateProperty.all(Colors.blue)
    
  • foregroundColor:按钮上的文本或图标的颜色。

    foregroundColor: MaterialStateProperty.all(Colors.white)
    
  • shape:按钮的形状,如圆角按钮。

    shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(18.0),),
    )
    
  • side:边框样式,适用于 OutlinedButton

    side: MaterialStateProperty.all(BorderSide(color: Colors.blue, width: 2.0),
    )
    
  • padding:按钮内的填充空间。

    padding: MaterialStateProperty.all(EdgeInsets.all(16.0))
    
  • elevation:按钮的阴影效果,适用于 ElevatedButton

    elevation: MaterialStateProperty.all(5.0)
    

4. 容器样式 (Container)

Container 是一个灵活的控件,几乎可以包含所有样式属性。除了上面提到的通用样式,Container 还支持:

  • widthheight:容器的宽度和高度。

    width: 100,
    height: 50,
    
  • constraints:设置容器的尺寸约束。

    constraints: BoxConstraints(minWidth: 100,minHeight: 50,maxWidth: 200,maxHeight: 100,
    )
    
  • transform:用于在绘制时应用旋转、缩放、平移等变换。

    transform: Matrix4.rotationZ(0.1),
    
  • decoration:用于设置容器的背景颜色、渐变、阴影、边框等样式。

    decoration: BoxDecoration(color: Colors.blue,borderRadius: BorderRadius.circular(10),boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.5),spreadRadius: 5,blurRadius: 7,offset: Offset(0, 3),),],
    )
    

5. 图片样式 (Image)

图片控件(Image)也有一些特定的样式属性:

  • fit:图片的适应模式,用于控制图片如何填充容器,比如 BoxFit.cover

    fit: BoxFit.cover
    
  • widthheight:图片的宽度和高度。

    width: 100,
    height: 100,
    
  • alignment:图片的对齐方式。

    alignment: Alignment.center
    
  • colorcolorBlendMode:应用颜色和混合模式到图片上。

    color: Colors.red,
    colorBlendMode: BlendMode.colorBurn,
    

6. 列表样式

ListViewGridView 中,每个项的样式往往与容器类似,可以通过 paddingmargindecoration 来控制样式。此外,列表特有的样式包括:

  • scrollDirection:滚动方向,水平或垂直。

    scrollDirection: Axis.horizontal
    
  • shrinkWrap:是否根据内容收缩,适用于在嵌套列表中防止无限滚动。

    shrinkWrap: true,
    
  • physics:控制滚动行为,如 BouncingScrollPhysics(滚动回弹效果)或 NeverScrollableScrollPhysics(禁止滚动)。

    physics: BouncingScrollPhysics()
    

7. 布局样式

布局控件(如 RowColumnStack 等)有一些特定的样式属性:

  • mainAxisAlignment:主轴对齐方式,如 MainAxisAlignment.center

    mainAxisAlignment: MainAxisAlignment.center,
    
  • crossAxisAlignment:交叉轴对齐方式,如 CrossAxisAlignment.start

    crossAxisAlignment: CrossAxisAlignment.start,
    
  • spacing:在 Wrap 布局中,用于控制子控件之间的间距。

    spacing: 10.0,
    
  • overflow:在 Stack 中控制子控件溢出时的处理方式,如 Overflow.visible

    overflow: Overflow.visible,
    

总结

  • 通用样式:颜色、对齐方式、边距、内边距等可广泛应用于大多数控件。
  • 文本样式:通过 TextStyle 定制字体、大小、颜色、间距等。
  • 按钮样式:按钮具有 ButtonStyle 来控制背景、边框、阴影等。
  • 容器样式Container 拥有灵活的尺寸、装饰、变换等属性。
  • 图片样式:控制图片的适应模式、尺寸、颜色滤镜等。
  • 列表和布局样式:控制滚动方向、对齐方式、间距等布局特性。

由于控件特别多 篇幅原因根本写不完,下面给一个大概目录介绍,实际用法可以使用gpt 进行了解(gpt 都比文档解释明白)

超详细的 Flutter 控件大全

目录

  1. 基础控件
    • Text
    • RichText
    • Image
    • Icon
    • Placeholder
  2. 布局控件
    • Container
    • Padding
    • Center
    • Align
    • SizedBox
    • Expanded
    • Flexible
    • Row
    • Column
    • Stack
    • Wrap
    • Flow
    • Table
    • GridView
    • ListView
  3. 输入控件
    • TextField
    • Checkbox
    • Radio
    • Switch
    • Slider
    • Form
    • DropdownButton
  4. 按钮控件
    • ElevatedButton
    • TextButton
    • OutlinedButton
    • IconButton
    • FloatingActionButton
    • PopupMenuButton
  5. 导航控件
    • AppBar
    • BottomNavigationBar
    • Drawer
    • TabBar
    • TabBarView
    • Navigator
    • PageView
  6. 动画与过渡控件
    • AnimatedContainer
    • AnimatedOpacity
    • Hero
    • Transform
    • AnimationController
    • FadeTransition
    • ScaleTransition
    • SizeTransition
    • PositionedTransition
    • SlideTransition
  7. 样式与主题控件
    • Theme
    • MediaQuery
    • DefaultTextStyle
    • IconTheme
    • Builder
  8. 异步与状态管理控件
    • StatefulWidget
    • StatelessWidget
    • FutureBuilder
    • StreamBuilder
  9. 滚动控件
    • SingleChildScrollView
    • Scrollbar
    • CustomScrollView
    • NotificationListener
  10. 绘制与效果控件
    • Opacity
    • ClipRect
    • ClipRRect
    • ClipOval
    • ClipPath
    • CustomPaint
  11. 交互模型
    • GestureDetector
    • Dismissible
    • Draggable
    • LongPressDraggable
    • DragTarget
  12. Material 组件
    • Scaffold
    • MaterialApp
    • Material
    • Card
    • Chip
    • SnackBar
    • Dialog
    • AlertDialog
    • SimpleDialog
    • BottomSheet
    • ExpansionPanel
  13. Cupertino(iOS 风格)控件
    • CupertinoApp
    • CupertinoButton
    • CupertinoNavigationBar
    • CupertinoTabScaffold
    • CupertinoAlertDialog

基础控件

Text

描述:用于显示一行简单格式的文本。

用法

Text('Hello, Flutter!',style: TextStyle(fontSize: 24,color: Colors.blue,fontWeight: FontWeight.bold,fontStyle: FontStyle.italic,letterSpacing: 2.0,wordSpacing: 5.0,decoration: TextDecoration.underline,decorationColor: Colors.red,decorationStyle: TextDecorationStyle.dashed,),textAlign: TextAlign.center,overflow: TextOverflow.ellipsis,maxLines: 2,
)

主要属性

  • data:要显示的文本。
  • style:文本样式,使用 TextStyle
  • textAlign:文本对齐方式,如 TextAlign.center
  • overflow:文本溢出处理方式,如 TextOverflow.ellipsis(省略号)。
  • maxLines:最大显示行数。
  • softWrap:是否自动换行。

RichText

描述:显示多种样式的富文本,可以对文本的不同部分应用不同的样式。

用法

RichText(text: TextSpan(text: 'Hello ',style: TextStyle(fontSize: 18, color: Colors.black),children: <TextSpan>[TextSpan(text: 'Flutter',style: TextStyle(fontWeight: FontWeight.bold, color: Colors.blue),),TextSpan(text: '!'),],),
)

主要属性

  • text:要显示的文本,使用 TextSpan 组合。
  • textAlign:文本对齐方式。
  • textDirection:文本方向。
  • softWrap:是否自动换行。
  • overflow:文本溢出处理方式。

Image

描述:用于显示图片,可以从多种来源加载图片。

用法

Image.network('https://example.com/image.png',width: 100,height: 100,fit: BoxFit.cover,color: Colors.red,colorBlendMode: BlendMode.colorBurn,
)

主要属性

  • image:要显示的图片,使用 ImageProvider
  • widthheight:图片的宽高。
  • fit:图片的适应方式,如 BoxFit.cover
  • alignment:图片的对齐方式。
  • repeat:图片的重复方式。
  • colorcolorBlendMode:颜色和混合模式。

示例

Image.asset('assets/images/flutter_logo.png',width: 200,height: 200,
)

Icon

描述:用于显示图标,图标来自于字体库,如 Material Icons。

用法

Icon(Icons.favorite,color: Colors.pink,size: 24.0,semanticLabel: 'Favorite',
)

主要属性

  • icon:要显示的图标,使用 IconData
  • size:图标大小。
  • color:图标颜色。
  • semanticLabel:语义标签。

Placeholder

描述:一个占位控件,用于在布局时占据空间,表示将来会添加其他控件。

用法

Placeholder(color: Colors.grey,strokeWidth: 2.0,fallbackWidth: 100.0,fallbackHeight: 100.0,
)

主要属性

  • color:占位符的颜色。
  • strokeWidth:线条宽度。
  • fallbackWidthfallbackHeight:当约束无效时的默认宽高。

布局控件

Container

描述:一个方便的容器控件,结合了绘制、定位和尺寸调整的常见操作。

用法

Container(width: 200,height: 200,padding: EdgeInsets.all(16.0),margin: EdgeInsets.symmetric(horizontal: 20.0),alignment: Alignment.center,decoration: BoxDecoration(color: Colors.blue,borderRadius: BorderRadius.circular(10.0),border: Border.all(color: Colors.black, width: 2.0),boxShadow: [BoxShadow(color: Colors.grey.withOpacity(0.5),offset: Offset(0, 3),blurRadius: 7,spreadRadius: 5,),],),child: Text('Container 示例', style: TextStyle(color: Colors.white)),
)

主要属性

  • alignment:子控件的对齐方式。
  • padding:内边距。
  • color:背景颜色。
  • decoration:背景装饰,如颜色、渐变、边框等。
  • widthheight:容器的宽高。
  • constraints:添加额外的约束条件。
  • margin:外边距。
  • transform:在绘制时应用的变换。

Padding

描述:一个小部件,用于在其子部件周围插入给定的填充。

用法

Padding(padding: EdgeInsets.fromLTRB(10, 20, 10, 20),child: Text('Padding 示例'),
)

主要属性

  • padding:填充的值,使用 EdgeInsets
  • child:子控件。

Center

描述:将其子控件居中显示。

用法

Center(child: Text('居中文本'),
)

主要属性

  • widthFactorheightFactor:可选参数,用于控制 Center 的尺寸。
  • child:子控件。

Align

描述:根据 Alignment 对齐其子控件,并可根据子控件的大小调整自身大小。

用法

Align(alignment: Alignment.bottomRight,child: Text('右下角对齐'),
)

主要属性

  • alignment:对齐方式,使用 Alignment
  • widthFactorheightFactor:可选参数,用于控制 Align 的尺寸。
  • child:子控件。

SizedBox

描述:具有特定尺寸的盒子,可用于给子控件指定固定的宽高。

用法

SizedBox(width: 100,height: 100,child: ElevatedButton(onPressed: () {},child: Text('固定尺寸按钮'),),
)

主要属性

  • widthheight:宽度和高度。
  • child:子控件。

Expanded

描述:用于扩展 RowColumnFlex 中的子控件,以填充可用空间。

用法

Row(children: <Widget>[Expanded(flex: 1,child: Container(color: Colors.red),),Expanded(flex: 2,child: Container(color: Colors.green),),],
)

主要属性

  • flex:占用空间的比例。
  • child:子控件。

Flexible

描述:一个控件,可以控制 RowColumnFlex 子控件的弹性行为。

用法

Row(children: <Widget>[Flexible(flex: 1,fit: FlexFit.tight,child: Container(color: Colors.blue),),Flexible(flex: 2,fit: FlexFit.loose,child: Container(color: Colors.orange),),],
)

主要属性

  • flex:占用空间的比例。
  • fit:弹性系数,FlexFit.tightFlexFit.loose
  • child:子控件。

Row

描述:沿水平方向排列子控件的布局。

用法

Row(mainAxisAlignment: MainAxisAlignment.spaceAround,crossAxisAlignment: CrossAxisAlignment.center,children: <Widget>[Icon(Icons.home),Icon(Icons.star),Icon(Icons.person),],
)

主要属性

  • children:子控件列表。
  • mainAxisAlignment:主轴(水平)方向的对齐方式。
  • crossAxisAlignment:交叉轴(垂直)方向的对齐方式。
  • mainAxisSize:主轴尺寸,MainAxisSize.maxMainAxisSize.min

Column

描述:沿垂直方向排列子控件的布局。

用法

Column(mainAxisAlignment: MainAxisAlignment.spaceEvenly,crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[Text('第一行'),Text('第二行'),Text('第三行'),],
)

主要属性

  • Row 类似,只是方向为垂直方向。

Stack

描述:可以将子控件堆叠在一起,后添加的控件会覆盖在之前的控件之上。

用法

Stack(alignment: Alignment.center,children: <Widget>[Container(width: 200, height: 200, color: Colors.red),Container(width: 150, height: 150, color: Colors.green),Positioned(bottom: 10,right: 10,child: Text('定位文本'),),],
)

主要属性

  • alignment:未定位子控件的对齐方式。
  • fit:未定位子控件如何适应 Stack 的大小。
  • overflow:溢出处理方式(已废弃,使用 clipBehavior)。

Wrap

描述:当空间不足时,自动换行排列子控件,类似于网页的自动换行布局。

用法

Wrap(spacing: 8.0,runSpacing: 4.0,alignment: WrapAlignment.center,children: <Widget>[Chip(label: Text('标签1')),Chip(label: Text('标签2')),Chip(label: Text('标签3')),Chip(label: Text('标签4')),Chip(label: Text('标签5')),],
)

主要属性

  • direction:布局方向,水平或垂直。
  • alignment:主轴对齐方式。
  • spacing:主轴方向子控件之间的间距。
  • runSpacing:交叉轴方向子控件之间的间距。
  • children:子控件列表。

Flow

描述:一个高效的控件,可以自定义子控件的位置,适用于需要高度自定义布局的场景。

用法

Flow(delegate: MyFlowDelegate(),children: <Widget>[Container(width: 80, height: 80, color: Colors.red),Container(width: 80, height: 80, color: Colors.green),Container(width: 80, height: 80, color: Colors.blue),],
)

主要属性

  • delegate:控制子控件布局的委托类,需要继承 FlowDelegate
  • children:子控件列表。

Table

描述:创建一个表格布局,按行和列排列子控件。

用法

Table(border: TableBorder.all(color: Colors.black),children: [TableRow(children: [Text('单元格1'),Text('单元格2'),Text('单元格3'),]),TableRow(children: [Text('单元格4'),Text('单元格5'),Text('单元格6'),]),],
)

主要属性

  • childrenTableRow 的列表,每个 TableRow 包含一行的子控件。
  • border:表格边框。
  • defaultColumnWidth:默认列宽。

GridView

描述:可滚动的网格列表,用于以网格形式显示数据。

用法

GridView.count(crossAxisCount: 2,crossAxisSpacing: 10.0,mainAxisSpacing: 10.0,children: <Widget>[Container(color: Colors.red),Container(color: Colors.green),Container(color: Colors.blue),Container(color: Colors.yellow),],
)

主要属性

  • crossAxisCount:列数。
  • mainAxisSpacing:主轴(垂直)方向间距。
  • crossAxisSpacing:交叉轴(水平)方向间距。
  • childAspectRatio:子控件的宽高比。
  • children:子控件列表。

ListView

描述:可滚动的列表,用于按顺序显示子控件。

用法

ListView.builder(itemCount: 100,itemBuilder: (context, index) {return ListTile(leading: Icon(Icons.person),title: Text('用户 $index'),subtitle: Text('用户详情'),trailing: Icon(Icons.arrow_forward),);},
)

主要属性

  • children:子控件列表。
  • itemCount:列表项数量(用于 builder 模式)。
  • itemBuilder:列表项构建器函数。

输入控件

TextField

描述:用于文本输入的控件,支持单行和多行输入。

用法

TextField(decoration: InputDecoration(labelText: '用户名',hintText: '请输入用户名',prefixIcon: Icon(Icons.person),),onChanged: (value) {print('输入的内容:$value');},
)

主要属性

  • decoration:输入框装饰,使用 InputDecoration
  • onChanged:内容改变时的回调。
  • controller:控制器,用于获取和设置文本。
  • keyboardType:键盘类型,如 TextInputType.emailAddress
  • obscureText:是否隐藏输入的内容(如密码)。
  • maxLength:最大输入长度。

Checkbox

描述:复选框,可用于选择或取消选择某个选项。

用法

Checkbox(value: _isChecked,onChanged: (bool? newValue) {setState(() {_isChecked = newValue!;});},
)

主要属性

  • value:当前选中状态。
  • onChanged:状态改变时的回调。
  • activeColor:选中时的颜色。

Radio

描述:单选按钮,用于从多个选项中选择一个。

用法

Radio<int>(value: 1,groupValue: _selectedValue,onChanged: (int? newValue) {setState(() {_selectedValue = newValue!;});},
)

主要属性

  • value:当前单选按钮的值。
  • groupValue:当前组中被选中的值。
  • onChanged:选中状态改变时的回调。

Switch

描述:开关控件,用于在开和关之间切换。

用法

Switch(value: _isSwitched,onChanged: (bool newValue) {setState(() {_isSwitched = newValue;});},activeColor: Colors.green,
)

主要属性

  • value:当前状态。
  • onChanged:状态改变时的回调。
  • activeColor:打开时的颜色。

Slider

描述:滑块控件,用于在给定范围内选择一个值。

用法

Slider(value: _sliderValue,min: 0.0,max: 100.0,divisions: 10,label: '${_sliderValue.round()}',onChanged: (double newValue) {setState(() {_sliderValue = newValue;});},
)

主要属性

  • value:当前值。
  • minmax:最小值和最大值。
  • divisions:将滑块分成的等份数。
  • label:显示在滑块上的标签。
  • onChanged:值改变时的回调。

Form

描述:表单,用于对多个输入控件进行统一管理和验证。

用法

final _formKey = GlobalKey<FormState>();Form(key: _formKey,child: Column(children: <Widget>[TextFormField(decoration: InputDecoration(labelText: '邮箱'),validator: (value) {if (value == null || value.isEmpty) {return '请输入邮箱';}return null;},),ElevatedButton(onPressed: () {if (_formKey.currentState!.validate()) {// 表单验证通过}},child: Text('提交'),),],),
)

主要属性

  • key:用于标识表单的全局键。
  • child:表单的子控件。
  • autovalidateMode:自动验证模式。

DropdownButton

描述:下拉按钮,可以从多个选项中选择一个。

用法

String _selectedItem = '选项1';DropdownButton<String>(value: _selectedItem,items: <String>['选项1', '选项2', '选项3'].map<DropdownMenuItem<String>>((String value) {return DropdownMenuItem<String>(value: value,child: Text(value),);}).toList(),onChanged: (String? newValue) {setState(() {_selectedItem = newValue!;});},
)

主要属性

  • value:当前选中的值。
  • items:可供选择的菜单项列表。
  • onChanged:选项改变时的回调。

按钮控件 (Button Widgets)

ElevatedButton

  • 概述: ElevatedButton 是一个带有凸起效果的按钮,用户点击时会有立体感。

  • 常见属性:

    • onPressed: 按钮点击事件的回调函数,若为 null 则按钮不可用。
    • child: 按钮中的内容,通常为 TextIcon
    • style: 自定义按钮的样式,如背景颜色、阴影、边框等。

    示例:

    ElevatedButton(onPressed: () {},child: Text('Elevated Button'),
    )
    

TextButton

  • 概述: TextButton 是一个没有边框和背景的文本按钮,适合用于轻量级的按钮需求。

  • 常见属性:

    • onPressed: 点击时触发的回调。
    • child: 按钮的内容,通常为文本。
    • style: 可定制字体颜色、内边距等。

    示例:

    TextButton(onPressed: () {},child: Text('Text Button'),
    )
    

OutlinedButton

  • 概述: OutlinedButton 是一个带边框但没有背景的按钮,适合用于较轻的交互需求。

  • 常见属性:

    • onPressed: 点击事件的回调。
    • child: 按钮内容。
    • style: 自定义边框颜色、形状等。

    示例:

    OutlinedButton(onPressed: () {},child: Text('Outlined Button'),
    )
    

IconButton

  • 概述: IconButton 是一个点击响应的图标按钮,可以用来触发特定的功能,如导航、删除等。

  • 常见属性:

    • icon: 显示的图标。
    • onPressed: 点击时触发的回调。
    • tooltip: 长按按钮时显示的提示文字。

    示例:

    IconButton(icon: Icon(Icons.add),onPressed: () {},
    )
    

FloatingActionButton

  • 概述: FloatingActionButton 是一个悬浮的圆形按钮,通常用于页面的主要交互操作。

  • 常见属性:

    • onPressed: 按钮点击的回调函数。
    • child: 按钮中的图标或文本。
    • backgroundColor: 背景颜色。

    示例:

    FloatingActionButton(onPressed: () {},child: Icon(Icons.add),
    )
    

PopupMenuButton

  • 概述: PopupMenuButton 是一个点击后弹出菜单项的按钮,适合用于选项选择或菜单操作。

  • 常见属性:

    • onSelected: 选择某个菜单项后的回调。
    • itemBuilder: 构建弹出的菜单项列表。

    示例:

    PopupMenuButton<String>(onSelected: (value) {// Handle selection},itemBuilder: (BuildContext context) {return ['Option 1', 'Option 2'].map((String choice) {return PopupMenuItem<String>(value: choice,child: Text(choice),);}).toList();},
    )
    

导航控件 (Navigation Widgets)

AppBar

  • 概述: AppBar 是一个放置在 Scaffold 顶部的导航栏控件,通常包含标题、导航图标、操作按钮等。

  • 常见属性:

    • title: 导航栏的标题。
    • actions: 导航栏右侧的操作按钮,如搜索、分享等。
    • leading: 导航栏左侧的控件,通常为返回按钮或菜单按钮。

    示例:

    AppBar(title: Text('App Bar'),actions: [IconButton(icon: Icon(Icons.search),onPressed: () {},),],
    )
    

BottomNavigationBar

  • 概述: BottomNavigationBar 是页面底部的导航栏,通常用于在多个页面之间切换。

  • 常见属性:

    • items: 导航栏中的菜单项,通常为 BottomNavigationBarItem 的列表。
    • currentIndex: 当前选中的菜单项索引。
    • onTap: 点击某个菜单项时触发的回调。

    示例:

    BottomNavigationBar(currentIndex: 0,onTap: (index) {// Handle tab change},items: [BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),],
    )
    

Drawer

  • 概述: Drawer 是一个从屏幕边缘滑出的侧边栏,通常用于显示导航选项或设置菜单。

  • 常见属性:

    • child: 侧边栏中的内容,通常为导航列表。

    示例:

    Drawer(child: ListView(children: [DrawerHeader(child: Text('Header')),ListTile(title: Text('Item 1'),onTap: () {},),],),
    )
    

TabBar

  • 概述: TabBar 是用于页面标签切换的控件,通常与 TabBarView 一起使用。

  • 常见属性:

    • tabs: Tab 标签项的列表。
    • controller: 控制 Tab 页的切换。

    示例:

    TabBar(tabs: [Tab(text: 'Tab 1'),Tab(text: 'Tab 2'),],
    )
    

TabBarView

  • 概述: TabBarView 是与 TabBar 配合使用的内容视图,当标签切换时显示不同的内容。

  • 常见属性:

    • children: 每个 Tab 对应的内容视图。
    • controller: 控制切换的控制器。

    示例:

    TabBarView(children: [Center(child: Text('Tab 1 Content')),Center(child: Text('Tab 2 Content')),],
    )
    

Navigator

  • 概述: Navigator 是 Flutter 中管理路由的控件,提供页面间导航的能力。

  • 常见方法:

    • push: 推入一个新页面。
    • pop: 返回上一个页面。

    示例:

    Navigator.push(context,MaterialPageRoute(builder: (context) => NewPage()),
    );
    

PageView

  • 概述: PageView 是一个可以水平或垂直滑动的多页面视图控件,常用于图片轮播或页面翻阅。

  • 常见属性:

    • children: 子页面列表。
    • controller: 控制滑动的控制器。

    示例:

    PageView(children: [Container(color: Colors.red),Container(color: Colors.blue),],
    )
    

动画与过渡控件 (Animation and Transition Widgets)

AnimatedContainer

  • 概述: AnimatedContainer 是一个带有动画效果的容器,属性的变化会触发过渡动画。

  • 常见属性:

    • duration: 动画持续时间。
    • curve: 动画曲线。

    示例:

    AnimatedContainer(duration: Duration(seconds: 1),color: Colors.blue,height: 100.0,width: 100.0,
    )
    

AnimatedOpacity

  • 概述: AnimatedOpacity 用于对不透明度的变化进行动画处理,适合用于渐隐渐现效果。

  • 常见属性:

    • opacity: 不透明度值。
    • duration: 动画持续时间。

    示例:

    AnimatedOpacity(opacity: 0.5,duration: Duration(seconds: 2),child: Container(color: Colors.red),
    )
    

Hero

  • 概述: Hero 用于两个页面之间的元素过渡动画,创建视觉连贯的动画效果。

  • 常见属性:

    • tag: 唯一标识符,用于在两个页面间匹配相同的控件。

    示例:

    Hero(tag: 'heroTag',child: Image.asset('path_to_image'),
    )
    

Transform

  • 概述: Transform 控件用于应用几何变换,如平移、旋转、缩放等。

  • 常见属性:

    • transform: 变换矩阵,如 Matrix4 用于平移、旋转等。

    示例:

Transform.rotate(
angle: 0.5,
child: Container(color: Colors.blue),
)


### **AnimationController**- **概述**: AnimationController 是动画的核心控制器,用于控制动画的进度、启动、停止等。- **常见属性与方法**:- `vsync`: 提高动画性能。
- `duration`: 动画的持续时间。
- `forward`, `reverse`, `stop`: 启动、反转、停止动画。**示例**:```dart
AnimationController(vsync: this,duration: Duration(seconds: 2),
)

FadeTransition

  • 概述: FadeTransition 用于实现渐隐渐现的动画效果。

  • 常见属性:

    • opacity: 动画的不透明度控制,通常使用 Animation。

    示例:

    FadeTransition(opacity: animation,child: Text('Fade Transition'),
    )
    

ScaleTransition

  • 概述: ScaleTransition 用于实现缩放动画。

  • 常见属性:

    • scale: 动画的缩放值,通常使用 Animation。

    示例:

    ScaleTransition(scale: animation,child: Icon(Icons.star),
    )
    

SizeTransition

  • 概述: SizeTransition 根据动画的值对子控件进行尺寸缩放,适用于线性变化。

  • 常见属性:

    • sizeFactor: 尺寸因子,决定动画的变化。

    示例:

    SizeTransition(sizeFactor: animation,child: Container(color: Colors.blue),
    )
    

PositionedTransition

  • 概述: PositionedTransition 是基于 Positioned 控件实现的动画,用于动态改变子控件的 topleft 等定位属性。

  • 常见属性:

    • rect: 定位属性的动画值。

    示例:

    PositionedTransition(rect: animation,child: Text('Positioned Transition'),
    )
    

SlideTransition

  • 概述: SlideTransition 实现平移动画,通常用于滑动视图的过渡效果。

  • 常见属性:

    • position: 动画控制的滑动位置,通常为 Animation。

    示例:

    SlideTransition(position: animation,child: Text('Slide Transition'),
    )
    

1. 样式与主题控件

Theme
  • 概述: Theme 控件用于设置应用的全局样式和主题。

  • 常见属性:

    • data: 定义 ThemeData 对象,包括颜色、字体等。
    • child: 需要应用主题的子控件。

    示例:

    Theme(data: ThemeData(primarySwatch: Colors.blue),child: MyApp(),
    )
    
MediaQuery
  • 概述: MediaQuery 控件用于获取设备的屏幕尺寸、方向和其他媒体信息。

  • 常见属性:

    • data: 提供 MediaQueryData 对象,包括屏幕宽度、高度、设备像素比等。
    • child: 需要响应媒体查询的子控件。

    示例:

    MediaQuery.of(context).size.width;
    
DefaultTextStyle
  • 概述: DefaultTextStyle 设置子控件的默认文本样式。

  • 常见属性:

    • style: TextStyle 对象,指定文本颜色、字体等。
    • child: 应用样式的子控件。

    示例:

    DefaultTextStyle(style: TextStyle(fontSize: 20, color: Colors.red),child: Text('Styled Text'),
    )
    
IconTheme
  • 概述: IconTheme 用于设置图标的默认样式。

  • 常见属性:

    • data: IconThemeData 对象,定义图标的大小、颜色等。
    • child: 应用图标样式的子控件。

    示例:

    IconTheme(data: IconThemeData(color: Colors.green),child: Icon(Icons.star),
    )
    
Builder
  • 概述: Builder 用于在其子控件中构建上下文环境,以便访问 BuildContext

  • 常见属性:

    • builder: 返回需要的 Widget 的构建器函数。

    示例:

    Builder(builder: (context) {return Text('Width: ${MediaQuery.of(context).size.width}');},
    )
    

2. 异步与状态管理控件

StatefulWidget
  • 概述: StatefulWidget 是一个状态变化的控件,每次状态变化都会重新构建。

  • 常见属性:

    • createState: 创建控件的状态对象。

    示例:

    class MyStatefulWidget extends StatefulWidget {_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
    }class _MyStatefulWidgetState extends State<MyStatefulWidget> {Widget build(BuildContext context) {return Container();}
    }
    
StatelessWidget
  • 概述: StatelessWidget 是一个无状态控件,构建时不依赖状态。

  • 常见属性:

    • build: 构建控件的方法。

    示例:

    class MyStatelessWidget extends StatelessWidget {Widget build(BuildContext context) {return Text('I am stateless');}
    }
    
FutureBuilder
  • 概述: FutureBuilder 根据异步 Future 的状态动态构建 UI。

  • 常见属性:

    • future: 需要等待的异步操作。
    • builder: 返回根据 AsyncSnapshot 构建的 Widget

    示例:

    FutureBuilder<String>(future: fetchData(),builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.done) {return Text(snapshot.data ?? 'Error');} else {return CircularProgressIndicator();}},
    )
    
StreamBuilder
  • 概述: StreamBuilder 根据数据流 Stream 的状态动态构建 UI。

  • 常见属性:

    • stream: 需要监听的数据流。
    • builder: 返回根据 AsyncSnapshot 构建的 Widget

    示例:

    StreamBuilder<int>(stream: myStream,builder: (context, snapshot) {return Text('Stream Value: ${snapshot.data}');},
    )
    

滚动控件

SingleChildScrollView
  • 概述: SingleChildScrollView 允许一个子控件在可滚动的视图中显示。

  • 常见属性:

    • child: 需要滚动显示的子控件。
    • scrollDirection: 滚动方向,默认为垂直方向。

    示例:

    SingleChildScrollView(child: Column(children: List.generate(100, (index) => Text('Item $index')),),
    )
    
Scrollbar
  • 概述: Scrollbar 控件用于显示滚动条。

  • 常见属性:

    • child: 可滚动的子控件。

    示例:

    Scrollbar(child: ListView.builder(itemCount: 100,itemBuilder: (context, index) => ListTile(title: Text('Item $index')),),
    )
    
CustomScrollView
  • 概述: CustomScrollView 是一个支持自定义滚动效果的控件。

  • 常见属性:

    • slivers: 需要滚动的子控件,通常是 Sliver 类型。

    示例:

    CustomScrollView(slivers: [SliverList(delegate: SliverChildBuilderDelegate((context, index) => ListTile(title: Text('Item $index')),childCount: 100,),),],
    )
    
NotificationListener
  • 概述: NotificationListener 用于监听子控件中的滚动事件。

  • 常见属性:

    • onNotification: 处理通知事件的回调。

    示例:

    NotificationListener<ScrollNotification>(onNotification: (notification) {print(notification.metrics.pixels);return true;},child: ListView.builder(itemCount: 100,itemBuilder: (context, index) => ListTile(title: Text('Item $index')),),
    )
    

绘制与效果控件

Opacity
  • 概述: Opacity 控件用于设置子控件的不透明度。

  • 常见属性:

    • opacity: 控件的透明度,范围为 0.0 - 1.0。

    示例:

    Opacity(opacity: 0.5,child: Text('Semi-transparent text'),
    )
    
ClipRect
  • 概述: ClipRect 用于裁剪矩形区域中的子控件。

  • 常见属性:

    • child: 需要裁剪的子控件。

    示例:

    ClipRect(child: Align(alignment: Alignment.topLeft,widthFactor: 0.5,heightFactor: 0.5,child: Container(color: Colors.red),),
    )
    
ClipRRect
  • 概述: ClipRRect 用于裁剪圆角矩形区域中的子控件。

  • 常见属性:

    • borderRadius: 圆角半径。
    • child: 需要裁剪的子控件。

    示例:

    ClipRRect(borderRadius: BorderRadius.circular(16.0),child: Container(color: Colors.blue, width: 100, height: 100),
    )
    
ClipOval
  • 概述: ClipOval 用于裁剪椭圆形区域中的子控件。

  • 常见属性:

    • child: 需要裁剪的子控件。

    示例:

    ClipOval(child: Image.network('https://via.placeholder.com/150'),
    )
    
ClipPath
  • 概述: ClipPath 使用自定义路径裁剪子控件。

  • 常见属性:

    • clipper: 自定义路径裁剪器。

    示例:

    ClipPath(clipper: MyCustomClipper(),child: Container(color: Colors.green),
    )
    
CustomPaint
  • 概述: CustomPaint 用于自定义绘制内容。
  • 常见属性:
    • painter: 自定义绘制

器。

示例:

CustomPaint(
painter: MyPainter(),
child: Container(),
)

1. 交互模型

GestureDetector
  • 概述: GestureDetector 是一个无形的控件,能够检测用户的手势(如点击、拖动、滑动等)。

  • 常见属性:

    • onTap: 点击时调用的回调。
    • onDoubleTap: 双击时调用的回调。
    • onLongPress: 长按时调用的回调。
    • onPanUpdate: 拖动时调用的回调。

    示例:

    GestureDetector(onTap: () {print('Tapped!');},onLongPress: () {print('Long pressed!');},child: Container(color: Colors.blue,width: 100,height: 100,child: Center(child: Text('Tap Me')),),
    )
    
Dismissible
  • 概述: Dismissible 控件用于实现滑动删除的功能,适合用于列表项。

  • 常见属性:

    • key: 唯一标识符,通常是 Key 类型。
    • background: 当控件被滑动时显示的背景。
    • child: 需要滑动的子控件。
    • onDismissed: 控件被滑动并删除时的回调。

    示例:

    Dismissible(key: Key('item'),background: Container(color: Colors.red),child: ListTile(title: Text('Swipe to delete')),onDismissed: (direction) {print('Item dismissed');},
    )
    
Draggable
  • 概述: Draggable 控件用于创建可拖动的控件。

  • 常见属性:

    • child: 拖动时显示的子控件。
    • feedback: 拖动时的反馈控件。
    • childWhenDragging: 拖动时原控件显示的内容。

    示例:

    Draggable(data: 'data',child: Container(color: Colors.blue, width: 100, height: 100),feedback: Material(child: Container(color: Colors.red, width: 100, height: 100),),childWhenDragging: Container(color: Colors.grey, width: 100, height: 100),
    )
    
LongPressDraggable
  • 概述: LongPressDraggable 是一种专门用于长按拖动的控件。

  • 常见属性:

    • Draggable 类似,增加了对长按的支持。

    示例:

    LongPressDraggable(data: 'data',child: Container(color: Colors.blue, width: 100, height: 100),feedback: Material(child: Container(color: Colors.red, width: 100, height: 100),),
    )
    
DragTarget
  • 概述: DragTarget 用于接收拖动控件的数据。

  • 常见属性:

    • builder: 构建拖放目标的函数,接收当前拖动状态。
    • onAccept: 当接受到拖动数据时调用的回调。

    示例:

    DragTarget<String>(builder: (context, candidateData, rejectedData) {return Container(color: Colors.green, width: 100, height: 100);},onAccept: (data) {print('Accepted: $data');},
    )
    

2. Material 组件

Scaffold
  • 概述: Scaffold 是一个 Material 设计的基本布局结构,包含应用程序的主要视觉界面元素。

  • 常见属性:

    • appBar: 顶部的应用栏。
    • body: 主要的内容区域。
    • floatingActionButton: 浮动操作按钮。
    • bottomNavigationBar: 底部导航栏。

    示例:

    Scaffold(appBar: AppBar(title: Text('Scaffold Example')),body: Center(child: Text('Hello World')),floatingActionButton: FloatingActionButton(onPressed: () {}),
    )
    
MaterialApp
  • 概述: MaterialApp 是一个封装了多个 Material 设计相关的配置的控件,通常作为应用程序的根控件。

  • 常见属性:

    • home: 应用的主界面。
    • theme: 应用的主题设置。

    示例:

    MaterialApp(home: Scaffold(appBar: AppBar(title: Text('MaterialApp Example')),body: Center(child: Text('Hello World')),),
    )
    
Material
  • 概述: Material 是一个简单的控件,用于将子控件渲染为 Material 设计风格。

  • 常见属性:

    • child: 需要应用 Material 风格的子控件。

    示例:

    Material(child: Container(color: Colors.red),
    )
    
Card
  • 概述: Card 是一个 Material 风格的容器,通常用于显示内容。

  • 常见属性:

    • child: 显示在卡片上的内容。
    • elevation: 卡片的阴影深度。

    示例:

    Card(elevation: 4,child: Padding(padding: const EdgeInsets.all(16.0),child: Text('This is a Card'),),
    )
    
Chip
  • 概述: Chip 是一个 Material 风格的小块,通常用于展示信息或选项。

  • 常见属性:

    • label: 显示的文本。
    • avatar: 显示的头像。

    示例:

    Chip(label: Text('Chip Label'),avatar: CircleAvatar(child: Text('A')),
    )
    
SnackBar
  • 概述: SnackBar 是一个短暂显示的消息提示框,通常用于显示反馈信息。

  • 常见属性:

    • content: 显示的内容。
    • action: 额外的操作按钮。

    示例:

    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('This is a SnackBar'),action: SnackBarAction(label: 'Undo', onPressed: () {}),),
    )
    
Dialog
  • 概述: Dialog 是一个弹出窗口,通常用于显示信息或请求用户操作。

  • 常见属性:

    • child: 显示在对话框中的内容。

    示例:

    showDialog(context: context,builder: (context) => AlertDialog(title: Text('Dialog Title'),content: Text('This is a dialog'),actions: [TextButton(onPressed: () => Navigator.of(context).pop(), child: Text('OK'))],),
    );
    
AlertDialog
  • 概述: AlertDialog 是一种特殊类型的对话框,用于提示用户重要信息或请求确认。

  • 常见属性:

    • title: 对话框的标题。
    • content: 对话框的内容。

    示例:

    showDialog(context: context,builder: (context) => AlertDialog(title: Text('Alert Title'),content: Text('This is an alert dialog.'),actions: [TextButton(onPressed: () => Navigator.of(context).pop(),child: Text('Cancel'),),TextButton(onPressed: () => Navigator.of(context).pop(),child: Text('OK'),),],),
    );
    
SimpleDialog
  • 概述: SimpleDialog 是一个简单的对话框,通常用于提供多个选项供用户选择。

  • 常见属性:

    • title: 对话框的标题。
    • children: 显示在对话框中的子控件。

    示例:

    showDialog(context: context,builder: (context) => SimpleDialog(title: Text('Choose an option'),children: [SimpleDialogOption(child: Text('Option 1'), onPressed: () {}),SimpleDialogOption(child: Text('Option 2'), onPressed: () {}),],),
    );
    
BottomSheet
  • 概述: BottomSheet 是从屏幕底部滑出的面板,可以用于显示额外内容。

  • 常见属性:

    • builder: 返回底部面板的构建器函数。

    示例:

    showModalBottomSheet(context: context,builder: (context) => Container(height:
    

200,
child: Center(child: Text(‘This is a BottomSheet’)),
),
);

#### **ExpansionPanel**
- **概述**: `ExpansionPanel` 是一种可展开的面板,适合用于显示可折叠的信息。
- **常见属性**:
- `headerBuilder`: 用于构建面板头部的函数。
- `body`: 显示在面板展开时的内容。**示例**:
```dart
ExpansionPanelList(expandedHeaderAlignment: ExpansionPanelHeaderAlignment.center,elevation: 1,expandedPanel: true,children: [ExpansionPanel(headerBuilder: (context, isExpanded) => ListTile(title: Text('Panel Header')),body: ListTile(title: Text('This is the body')),isExpanded: true,),],
)

3. Cupertino(iOS 风格)控件

CupertinoApp
  • 概述: CupertinoApp 是一个应用程序的根控件,具有 iOS 风格的外观和行为。

  • 常见属性:

    • home: 应用的主界面。

    示例:

    CupertinoApp(home: CupertinoPageScaffold(navigationBar: CupertinoNavigationBar(middle: Text('Cupertino App'),),child: Center(child: Text('Hello World')),),
    );
    
CupertinoButton
  • 概述: CupertinoButton 是一个 iOS 风格的按钮。

  • 常见属性:

    • onPressed: 按钮被点击时的回调。
    • child: 按钮内部显示的内容。

    示例:

    CupertinoButton(onPressed: () {print('Button pressed');},child: Text('Click Me'),
    )
    
CupertinoNavigationBar
  • 概述: CupertinoNavigationBar 是一个 iOS 风格的导航栏,通常放在页面顶部。

  • 常见属性:

    • middle: 中间显示的标题。
    • leading: 导航栏左侧的控件。

    示例:

    CupertinoNavigationBar(middle: Text('Navigation Bar'),leading: CupertinoButton(padding: EdgeInsets.zero,child: Icon(CupertinoIcons.back),onPressed: () {},),
    )
    
CupertinoTabScaffold
  • 概述: CupertinoTabScaffold 是一个 iOS 风格的标签式页面结构。

  • 常见属性:

    • tabBar: 显示在底部的标签栏。
    • tabBuilder: 用于构建每个标签对应的页面。

    示例:

    CupertinoTabScaffold(tabBar: CupertinoTabBar(items: [BottomNavigationBarItem(icon: Icon(CupertinoIcons.home), label: 'Home'),BottomNavigationBarItem(icon: Icon(CupertinoIcons.settings), label: 'Settings'),],),tabBuilder: (context, index) {return Center(child: Text('Tab $index'));},
    )
    
CupertinoAlertDialog
  • 概述: CupertinoAlertDialog 是一种 iOS 风格的警告对话框。

  • 常见属性:

    • title: 对话框的标题。
    • content: 对话框的内容。
    • actions: 显示在对话框底部的操作按钮。

    示例:

    showCupertinoDialog(context: context,builder: (context) => CupertinoAlertDialog(title: Text('Alert'),content: Text('This is an alert dialog'),actions: [CupertinoDialogAction(onPressed: () => Navigator.of(context).pop(),child: Text('OK'),),],),
    );
    

这份详细的控件描述涵盖了 Flutter 中的一些主要控件及其用法,帮助你更好地理解和使用 Flutter 进行应用开发!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com