Flutter基础知识
创始人
2024-01-31 13:24:52
0

const 常量构造函数,如果控件是,则前面加;如果常量构造函数包含有非常量构造函数,则不加,内部是的控件单独加

1.Flutter学习网址

Flutter 中文官网 https://flutter.cn/
Flutter 官网:https://flutter.dev/
Flutter Packages官网:https://pub.dev/

2.环境搭建,真机调试

第8步提前操作

1.总步骤

Flutter Android 环境搭建

  • 电脑上面安装JDK
  • 电脑上面下载安装AS
  • 电脑上面下载配置 Flutter SDK
  • 电脑上配置Flutter国内镜像
  • 运行 flutter doctor 命令检测环境是否配置成功,更具提示安装对应软件
  • AS 安装Flutter 插件
  • 创建运行Flutter项目

2.AS 安装插件:Flutter 和Dart

3.Flutter sdk

Flutter sdk(使用最新版本) 下载路径 https://docs.flutter.dev/development/tools/sdk/releases?tab=windows#windows

4.Flutter 国内镜像

Flutter 国内镜像地址 https://docs.flutter.dev/community/china

export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
git clone -b dev https://github.com/flutter/flutter.git
export PATH="$PWD/flutter/bin:$PATH"
cd ./flutter
flutter doctor

在这里插入图片描述
在这里插入图片描述

5.flutter doctor

在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/8586d46cea2a4c1084bab28a31dfb243.png在这里插入图片描述flutter doctor --android-licenses 一路点y

(非必须)Visual Studio 如果需要开发桌面应用 https://visualstudio.microsoft.com/downloads/
C++ CMake tools for Windows 必须下载 1.5G
在这里插入图片描述#### 6.AS 新建flutter项目 (项目目录都是小写)
在这里插入图片描述
在这里插入图片描述

7.AS 打开创建好的android 项目

8.vs下载即操作

vs下载路径:https://code.visualstudio.com/
插件:fluter dart Awesome FlutterSnippets(flutter提示工具)
不同的插件,快捷方式不一样

在这里插入图片描述
在这里插入图片描述

9.快捷键操作项目

vs 打开flutter文件夹
flutter run
flutter run -d all
ctrl+s 保存
常用快捷键(鼠标点到控制台)
r键:点击后热加载,也算是重新加载
R键:热重启项目
P键:显示网络,这个可以很好的掌握布局情况,工作中很有用
o键:切换Android和ios的预览模式
q键 :退出调试模式 ctrl+c

3.Flutter 目录结构介绍 入口 自定义Widget Center组件 Text组件 MaterailAp组件 Scaffpld组件礼包

lib 项目目录
pubspec.yaml 配置文件 项目依赖 项目版本号

analysis_options.yaml 分析dart语法文件,老项目升级成新项目有警告信息的话可以删掉此文件,可以全部删掉,有利于语法规范
在这里插入图片描述

import 'package:flutter/material.dart';void main() {runApp(MaterialApp(home: Scaffold(appBar: AppBar(title: const Text("你好Flutter")),body: HomeWidge(),),));
}class HomeWidge extends StatelessWidget {@overrideWidget build(BuildContext context) {return const Center(child: Text("我是一个文本",textDirection: TextDirection.ltr,style: TextStyle(fontSize: 25.0, color: Colors.red)));}
}

4.Container组件 Text组件

const(常量构造函数) 规范 ,也可以不加

import 'package:flutter/material.dart';void main() {runApp(MaterialApp(home: Scaffold(appBar: AppBar(title: const Text("你好Flutter")),body: Column(children: [MyApp(), MyButton(), MyText()],),),));
}class HomeWidge extends StatelessWidget {@overrideWidget build(BuildContext context) {return const Center(child: Text("我是一个文本",textDirection: TextDirection.ltr,style: TextStyle(fontSize: 25.0, color: Colors.red)));}
}class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Center(child: Container(margin: const EdgeInsets.fromLTRB(0, 60, 0, 0),alignment: Alignment.center,height: 200,width: 200,// transform: Matrix4.skewY(0.2),decoration: BoxDecoration(color: Colors.yellow,gradient: const LinearGradient(colors: [Colors.red, Colors.orange]),boxShadow: const [BoxShadow(color: Colors.blue,offset: Offset(2.0, 2.0),blurRadius: 10.0,)],border: Border.all(color: Colors.red, width: 2),borderRadius: BorderRadius.circular(8)),child: const Text("你好Flutter",style: TextStyle(fontSize: 20),),),);}
}class MyButton extends StatelessWidget {const MyButton({super.key});@overrideWidget build(BuildContext context) {return Container(alignment: Alignment.center,width: 200,height: 40,decoration: BoxDecoration(color: Colors.blue,borderRadius: BorderRadius.circular(10),),margin: const EdgeInsets.fromLTRB(0, 40, 0, 0),child: const Text("按钮",style: TextStyle(color: Colors.white,fontSize: 20,)),);}
}class MyText extends StatelessWidget {const MyText({super.key});@overrideWidget build(BuildContext context) {return Container(alignment: Alignment.center,width: 200,height: 200,decoration: const BoxDecoration(color: Colors.yellow,),child: const Text("如果是负值,会让单词变得更紧凑如果是负值,会让单词变得更紧凑",textAlign: TextAlign.left,maxLines: 2,overflow: TextOverflow.ellipsis,style: TextStyle(fontSize: 20.0,fontWeight: FontWeight.bold,color: Colors.red,fontStyle: FontStyle.italic),),);}
}

5.图片Image组件 本地图片 远程图片 图片剪切 圆形图片

上下间距
SizedBox( height: 20)

import 'package:flutter/material.dart';class MyApp2 extends StatelessWidget {const MyApp2({super.key});@overrideWidget build(BuildContext context) {return Center(child: Container(width: 150,height: 150,alignment: Alignment.center,decoration: BoxDecoration(color: Colors.yellow,borderRadius: BorderRadius.circular(10),image: const DecorationImage(fit: BoxFit.cover,image: NetworkImage("https://www.itying.com/themes/itying/images/ionic4.png"))),// child: Image.network(//   "https://www.itying.com/themes/itying/images/ionic4.png",//   fit: BoxFit.cover,// ),),);}
}//实现圆形图片
class Circular extends StatelessWidget {const Circular({super.key});@overrideWidget build(BuildContext context) {return Center(child: ClipOval(child: Image.network("https://www.itying.com/themes/itying/images/ionic4.png",width: 150.0,height: 150.0,fit: BoxFit.cover,),),);}
}class LocationImg extends StatelessWidget {const LocationImg({super.key});@overrideWidget build(BuildContext context) {return Center(child: ClipOval(child: Image.asset("images/a.jpg",width: 150.0,height: 150.0,fit: BoxFit.cover,),),);}
}

6.ICON图标组件 自带图标 和自定义图标

用处不大

7.列表(ListView GridView)组件

2.GridView创建网格列表主要有下面三种方式

  • 1、可以通过GridView.count 实现网格布局
  • 2、可以通过GridView.extent 实现网格布局
  • 3、通过GridView.builder实现动态网格布局
GridView.countGridView.extent
crossAxisCount 一行的Widget数量maxCrossAxisExtent 横轴子元素的最大长度
gridDelegateSliverGridDelegateWithFixedCrossAxisCountSliverGridDelegateWithMaxCrossAxisExtent
import 'package:flutter/material.dart';
import 'package:flutter01/res/listData.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(theme: ThemeData(primarySwatch: Colors.yellow),home: Scaffold(appBar: AppBar(title: Text("Fluter app")),body: MyHomePage(),),);}
}class MyHomePage extends StatelessWidget {const MyHomePage({super.key});Widget _initGridViewData(context, index) {return Container(decoration: BoxDecoration(border: Border.all(color: Colors.black26)),child: Column(children: [Image.network(listData[index]["imageUrl"]),const SizedBox(height: 10),Text(listData[index]["title"],style: const TextStyle(fontSize: 18),)],),);}@overrideWidget build(BuildContext context) {return GridView.builder(padding: const EdgeInsets.all(10),itemCount: listData.length,gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisSpacing: 10,mainAxisSpacing: 10,crossAxisCount: 2,childAspectRatio: 1),itemBuilder: _initGridViewData);}
}
List listData = [{"title": "Candy shop","author": "Mohamed Chain","imageUrl": "https://www.itying.com/images/flutter/1.png",},
];

8.Flutter页面布局 Padding Row Column flex Expanded

this.icon 是 this.icon=icon; 的简写
required this.color 中 required 表明是必传参数
this.color = Colors.red 这个写,写可以不传

class IconContainer extends StatelessWidget {Color color;double size;IconData icon;IconContainer(this.icon,{Key? key, this.color = Colors.red, this.size = 32.0}): super(key: key);IconContainer1({Key? key, this.color = Colors.red, this.size = 32.0}): super(key: key) {
this.icon=icon;}@overrideWidget build(BuildContext context) {return Container(height: 100,width: 100,color: this.color,child: Icon(icon, color: color, size: size),);}
}

double.infinity 和double.maxFinite可以让当前元素的width或者height达到父元素的尺寸
底层代码,只能用在Container容器里

width: double.infinity,
height: double.infinity,

flex Expanded 弹性布局
在这里插入图片描述
在这里插入图片描述

9.Flutter页面布局 Stack层叠组件,Stack与Align 、Stack与Positioned实现定位布局

1.最常用 Stack与Positioned

FlutterMediaQuery获取屏幕宽度和高度
final size = MediaQuery.of(context).size;
size.width,
在这里插入图片描述
alignment: Alignment(-1, 1),
算法实现
(Alignment.xchildWidth/2+childWidth/2, Alignment.ychildHeight/2+childHeight/2)
在这里插入图片描述

2.具体实例:相对与容器定位

在这里插入图片描述

import 'package:flutter/material.dart';
import 'package:flutter01/res/listData.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(theme: ThemeData(primarySwatch: Colors.yellow),home: Scaffold(appBar: AppBar(title: Text("Fluter app")),body: MyHomePage(),),);}
}class MyHomePage extends StatelessWidget {const MyHomePage({super.key});@overrideWidget build(BuildContext context) {final size = MediaQuery.of(context).size;return Column(children: [SizedBox(width: double.infinity,height: 40,child: Stack(children: const [Align(alignment: Alignment.topLeft,child: Text("收藏"),),Align(alignment: Alignment.topRight,child: Text("购买"),),],),),SizedBox(width: double.infinity,height: 40,child: Stack(children: const [Positioned(left: 10, child: Text("收藏")),Positioned(right: 10, child: Text("购买")),],),)],);}
}

9.Flutter页面布局 AspectRatio、 Card、 CircleAvatar 组件

1.child的宽高比 AspectRatio

用在控制图片的宽高比
在这里插入图片描述

 AspectRatio(aspectRatio: 3 / 1,child: Container(color: Colors.red,),)

2 .卡片布局Card

在这里插入图片描述

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(theme: ThemeData(primarySwatch: Colors.blue),home: Scaffold(appBar: AppBar(title: Text("Fluter app")),body: MyHomePage(),),);}
}class MyHomePage extends StatelessWidget {const MyHomePage({super.key});@overrideWidget build(BuildContext context) {final size = MediaQuery.of(context).size;return ListView(children: [Card(margin: EdgeInsets.all(10),elevation: 10,shape:RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),child: Column(children: const [ListTile(title: Text("张三",style: TextStyle(fontSize: 28),),subtitle: Text("高级软甲女工程师"),),Divider(),ListTile(title: Text("电话:1443234564",),subtitle: Text("地址:xxxxx"),)],),),Card(margin: EdgeInsets.all(10),child: Column(children: const [ListTile(title: Text("李四",style: TextStyle(fontSize: 28),),subtitle: Text("高级软甲男工程师"),),Divider(),ListTile(title: Text("电话:1443234564",),subtitle: Text("地址:xxxxx"),)],),)],);}
}

3 .卡片图文列表

在这里插入图片描述

ListView(children: [Card(margin: const EdgeInsets.all(10),elevation: 20,shape:RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),child: Column(children: [AspectRatio(aspectRatio: 16 / 9,child: Image.network("https://www.itying.com/images/flutter/1.png",fit: BoxFit.cover,),),ListTile(leading: ClipOval(child: Image.network("https://www.itying.com/images/flutter/2.png",fit: BoxFit.cover,height: 40,width: 40,)),title: const Text("XXXXXXX"),subtitle: const Text("aaaaaaaaa"),)],),)],)

4 .实现一个圆形图片 CircleAvatar

 CircleAvatar(backgroundImage: NetworkImage("https://www.itying.com/images/flutter/3.png"),)
ClipOval(child: Image.network("https://www.itying.com/images/flutter/2.png",fit: BoxFit.cover,height: 40,width: 40,))

5 .动态卡片图文列表

在这里插入图片描述

import 'package:flutter/material.dart';
import './res/listData.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(theme: ThemeData(primarySwatch: Colors.blue),home: Scaffold(appBar: AppBar(title: Text("Fluter app")),body: MyHomePage(),),);}
}class MyHomePage extends StatelessWidget {const MyHomePage({super.key});List _initCardDate() {var tempList = listData.map((value) {return Card(margin: const EdgeInsets.all(10),elevation: 20,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),child: Column(children: [AspectRatio(aspectRatio: 16 / 9,child: Image.network(value["imageUrl"],fit: BoxFit.cover,),),ListTile(leading: CircleAvatar(backgroundImage: NetworkImage(value["imageUrl"]),),title: Text(value["title"]),subtitle: Text(value["author"]),)],),);});return tempList.toList();}@overrideWidget build(BuildContext context) {final size = MediaQuery.of(context).size;return ListView(children: _initCardDate(),);}
}

10.Flutter按钮组件 Elevatedbutton、TextButton、OutlineButton、IconButton

19

在这里插入图片描述

import 'package:flutter/material.dart';
import './res/listData.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(theme: ThemeData(primarySwatch: Colors.blue),home: Scaffold(appBar: AppBar(title: Text("Fluter app")),body: MyHomePage(),),);}
}class MyHomePage extends StatelessWidget {const MyHomePage({super.key});@overrideWidget build(BuildContext context) {final size = MediaQuery.of(context).size;return ListView(children: [Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [ElevatedButton(onPressed: () {print("ElevatedButton");},child: const Text("普通按钮")),TextButton(onPressed: () {}, child: const Text("文本按钮")),OutlinedButton(onPressed: () {}, child: const Text("带边框的按钮")),IconButton(onPressed: () {}, icon: const Icon(Icons.thumb_up))],),const SizedBox(height: 20,),Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [ElevatedButton.icon(onPressed: () {},icon: const Icon(Icons.thumb_up),label: const Text("点赞")),TextButton.icon(onPressed: () {},icon: const Icon(Icons.thumb_up),label: const Text("点赞")),OutlinedButton.icon(onPressed: () {},icon: const Icon(Icons.thumb_up),label: const Text("点赞")),],),const SizedBox(height: 20,),Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [ElevatedButton(style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.red),foregroundColor: MaterialStateProperty.all(Colors.black)),onPressed: () {},child: const Text("普通按钮")),],),Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [Container(width: 140,height: 60,child: ElevatedButton(style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.red),foregroundColor: MaterialStateProperty.all(Colors.white)),onPressed: () {},child: const Text("大按钮")),),SizedBox(width: 140,height: 40,child: ElevatedButton(onPressed: () {}, child: const Text("大按钮")),)],),const SizedBox(height: 20,),Row(children: [Expanded(flex: 1,child: Container(margin: const EdgeInsets.all(20),height: 44,child: ElevatedButton(style: ButtonStyle(backgroundColor:MaterialStateProperty.all(Colors.redAccent),foregroundColor:MaterialStateProperty.all(Colors.white)),onPressed: () {},child: const Text("登录")),),)],),const SizedBox(height: 20,),Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [ElevatedButton(style: ButtonStyle(shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)))),onPressed: () {},child: const Text("圆角按钮")),Container(height: 60,width: 60,child: ElevatedButton(style: ButtonStyle(shape: MaterialStateProperty.all(const CircleBorder(side: BorderSide(width: 2, color: Colors.yellow)))),onPressed: () {},child: const Text("圆形")),)],),SizedBox(height: 20,),Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [OutlinedButton(onPressed: () {},child: const Text("带边框的按钮"),style: ButtonStyle(side: MaterialStateProperty.all(BorderSide(width: 1, color: Colors.red))),)],)],);}
}

11.使用Wrap组件实现电商APP搜索页面布局

21
ListView 不能嵌套ListView
在这里插入图片描述

import 'package:flutter/material.dart';
import './res/listData.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(theme: ThemeData(primarySwatch: Colors.blue),home: Scaffold(appBar: AppBar(title: Text("Fluter app")),body: MyHomePage(),),);}
}class MyHomePage extends StatelessWidget {const MyHomePage({super.key});@overrideWidget build(BuildContext context) {final size = MediaQuery.of(context).size;return ListView(padding: const EdgeInsets.all(10),children: [Row(children: [Text('热搜', style: Theme.of(context).textTheme.titleLarge)],),const Divider(),Wrap(spacing: 10,runSpacing: 10,children: [Button("女装", onPressed: () {}),Button("女装", onPressed: () {}),Button("女装", onPressed: () {}),Button("女装", onPressed: () {}),Button("女装", onPressed: () {}),Button("女装", onPressed: () {}),Button("女装", onPressed: () {}),Button("女装", onPressed: () {}),],),const SizedBox(height: 10,),Row(children: [Text('历史记录', style: Theme.of(context).textTheme.titleLarge)],),const Divider(),Column(children: const [ListTile(title: Text("女装"),),Divider(),ListTile(title: Text("笔记本"),),Divider(),ListTile(title: Text("手电筒"),),Divider(),],),const SizedBox(height: 40,),Padding(padding: const EdgeInsets.all(40),child: OutlinedButton.icon(style: ButtonStyle(foregroundColor: MaterialStateProperty.all(Colors.black45)),onPressed: () {},icon: const Icon(Icons.delete),label: const Text("清空历史记录",)),)],);}
}//自定义按钮组件
class Button extends StatelessWidget {String text; //按钮的文字void Function()? onPressed; //方法Button(this.text, {super.key, required this.onPressed});@overrideWidget build(BuildContext context) {return ElevatedButton(style: ButtonStyle(backgroundColor:MaterialStateProperty.all(Color.fromARGB(31, 248, 247, 247)),foregroundColor: MaterialStateProperty.all(Colors.black45)),onPressed: onPressed,child: Text(text));}
}

12.StatefulWidget有状态组件

setState(() {
});

通俗的讲:如果我们想改变页面中的数据的话这个时候就需要用到StatefulWidget
21

里面是const 就无法在外面加const

1.计数界面

在这里插入图片描述

//有状态组件
class _HomePageState extends State {int _countNum = 0;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Fluter app")),floatingActionButton: FloatingActionButton(onPressed: () {setState(() {_countNum++;});},child: const Icon(Icons.add),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text("$_countNum",style: Theme.of(context).textTheme.headline1,),const SizedBox(height: 100,),ElevatedButton(onPressed: () {setState(() {_countNum++;});print(_countNum);},child: const Text("增加"))],),),);}
}

2.添加列表界面

在这里插入图片描述

//有状态组件
class _HomePageState extends State {final List _list = [];@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Fluter app")),floatingActionButton: FloatingActionButton(onPressed: () {setState(() {_list.add("我是一个新增列表");});},child: const Icon(Icons.add),),body: ListView(children: _list.map((value) {return ListTile(title: Text(value));}).toList(),),);}
}

13.Scaffold BottomNavigatioinBar自定义底部导航栏

在这里插入图片描述

import 'package:flutter/material.dart';
import './tabs/home.dart';
import './tabs/category.dart';
import './tabs/setting.dart';
import './tabs/user.dart';class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState createState() => _MyHomePageState();
}//有状态组件
class _MyHomePageState extends State {int _currentIndex = 0;final List _pages = [HomePage(),Category(),SettingPage(),UserPage()];@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Fluter app")),bottomNavigationBar: BottomNavigationBar(fixedColor: Colors.red, //选中的颜色iconSize: 25, //底部菜单大小currentIndex: _currentIndex, //第几个菜单选项type: BottomNavigationBarType.fixed, //如果底部有四个以上的菜单的时候,就需要配置这个参数onTap: (index) {//点击选项触发的方法setState(() {_currentIndex = index;});},items: const [BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),BottomNavigationBarItem(icon: Icon(Icons.settings), label: "设置"),BottomNavigationBarItem(icon: Icon(Icons.person), label: "个人")],),body: _pages[_currentIndex],);}
}

14.FloatingActionButton实现类似闲鱼APP底部导航凸起按钮

在这里插入图片描述

import 'package:flutter/material.dart';
import './tabs/home.dart';
import './tabs/category.dart';
import './tabs/setting.dart';
import './tabs/user.dart';
import './tabs/message.dart';class MyHomePage extends StatefulWidget {const MyHomePage({super.key});@overrideState createState() => _MyHomePageState();
}//有状态组件
class _MyHomePageState extends State {int _currentIndex = 0;final List _pages = [HomePage(),Category(),MessagePage(),SettingPage(),UserPage()];@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("Fluter app")),bottomNavigationBar: BottomNavigationBar(fixedColor: Colors.red, //选中的颜色iconSize: 25, //底部菜单大小currentIndex: _currentIndex, //第几个菜单选项type: BottomNavigationBarType.fixed, //如果底部有四个以上的菜单的时候,就需要配置这个参数onTap: (index) {//点击选项触发的方法setState(() {_currentIndex = index;});},items: const [BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),BottomNavigationBarItem(icon: Icon(Icons.message), label: "消息"),BottomNavigationBarItem(icon: Icon(Icons.settings), label: "设置"),BottomNavigationBarItem(icon: Icon(Icons.person), label: "个人")],),floatingActionButton: Container(height: 60,width: 60,padding: const EdgeInsets.all(4),margin: const EdgeInsets.only(top: 4),decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(30)),child: FloatingActionButton(backgroundColor: _currentIndex == 2 ? Colors.red : Colors.blue,onPressed: () {setState(() {_currentIndex = 2;});},child: const Icon(Icons.add),),),floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,body: _pages[_currentIndex],);}
}

15.Drawer侧边栏,不同设备调试Flutter程序

在Scaffold组件里面传入drawer参数可以定义左侧边栏,传入endDrawer可以定义右侧边栏。侧边栏默认是隐藏的,我们可以通过手指滑动显示侧边栏,也可以通过点击按钮显示侧边栏。

1.Flutter DrawerHeader

在这里插入图片描述

在上一个代码中增加以下代码

 drawer: Drawer(child: Column(children: [DrawerHeader(decoration: const BoxDecoration(color: Colors.yellow,image: DecorationImage(image: NetworkImage("https://www.itying.com/images/flutter/2.png"),fit: BoxFit.cover)),child: ListView(children: [Text('我是一个头部')],),),const ListTile(title: Text("个人中心"),leading: CircleAvatar(child: Icon(Icons.people)),),const Divider(),const ListTile(title: Text("系统设置"),leading: CircleAvatar(child: Icon(Icons.settings)),)],)),

2.Flutter UserAccountsDrawerHeader

在这里插入图片描述

 drawer: Drawer(child: Column(children: [UserAccountsDrawerHeader(accountName: const Text("大地老师"),accountEmail: const Text("dadi@itying.com"),currentAccountPicture: const CircleAvatar(backgroundImage:NetworkImage("https://www.itying.com/images/flutter/3.png"),),decoration: const BoxDecoration(color: Colors.yellow,image: DecorationImage(image: NetworkImage("https://www.itying.com/images/flutter/2.png"),fit: BoxFit.cover)),otherAccountsPictures: [Image.network("https://www.itying.com/images/flutter/4.png"),Image.network("https://www.itying.com/images/flutter/5.png"),Image.network("https://www.itying.com/images/flutter/6.png")],),const ListTile(title: Text("个人中心"),leading: CircleAvatar(child: Icon(Icons.people)),),const Divider(),const ListTile(title: Text("系统设置"),leading: CircleAvatar(child: Icon(Icons.settings)),)],)),

15.Flutter AppBar TabBar TabBarView 实现类似头条顶部滑动导航

1.AppBar自定义顶部按钮图标、颜色

在这里插入图片描述

appBar: AppBar(backgroundColor: Colors.red, //导航栏背景颜色leading: IconButton(//左侧按钮图标icon: const Icon(Icons.menu),onPressed: () {print('menu Pressed');}),title: const Text('FlutterDemo'),actions: [//右侧按钮图标IconButton(icon: const Icon(Icons.search),onPressed: () {print('Search Pressed');}),IconButton(icon: const Icon(Icons.more_horiz),onPressed: () {print('more_horiz Pressed');})],),

2.去掉debug样式

class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(debugShowCheckedModeBanner: false,//去掉debug样式theme: ThemeData(primarySwatch: Colors.blue),home: HomePage(),);}
}

3.Flutter AppBar结合TabBar实现顶部Tab切换

在这里插入图片描述

1.关键代码
class _HomePageState extends Statewith SingleTickerProviderStateMixin {late TabController _tabController;//生命周期函数:当前组件初始化的时候就会触发@overridevoid initState() {super.initState();_tabController = TabController(length: 3, vsync: this);_tabController.addListener(() {if (_tabController.animation!.value == _tabController.index) {print(_tabController.index); //获取点击或滑动页面的索引值}});}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(bottom: TabBar(isScrollable: true,indicatorColor: Colors.white,indicatorWeight: 2,indicatorPadding: EdgeInsets.all(5),indicatorSize: TabBarIndicatorSize.label,// indicator: BoxDecoration(//     color: Colors.blue, borderRadius: BorderRadius.circular(10)),controller: _tabController,tabs: const [Tab(child: Text("热门")),Tab(child: Text("推荐")),Tab(child: Text("视频"))],),),body: TabBarView(controller: _tabController,children: const [Text("热门"), Text("推荐"), Text("视频")],),);}
}
2.完整代码
import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(debugShowCheckedModeBanner: false,theme: ThemeData(primarySwatch: Colors.blue),home: HomePage(),);}
}class HomePage extends StatefulWidget {const HomePage({super.key});@overrideState createState() => _HomePageState();
}class _HomePageState extends Statewith SingleTickerProviderStateMixin {late TabController _tabController;//生命周期函数:当前组件初始化的时候就会触发@overridevoid initState() {super.initState();_tabController = TabController(length: 3, vsync: this);_tabController.addListener(() {if (_tabController.animation!.value == _tabController.index) {print(_tabController.index); //获取点击或滑动页面的索引值}});}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(backgroundColor: Colors.red, //导航栏背景颜色leading: IconButton(//左侧按钮图标icon: const Icon(Icons.menu),onPressed: () {print('menu Pressed');}),title: const Text('FlutterDemo'),actions: [//右侧按钮图标IconButton(icon: const Icon(Icons.search),onPressed: () {print('Search Pressed');}),IconButton(icon: const Icon(Icons.more_horiz),onPressed: () {print('more_horiz Pressed');})],bottom: TabBar(isScrollable: true,indicatorColor: Colors.white,indicatorWeight: 2,indicatorPadding: EdgeInsets.all(5),indicatorSize: TabBarIndicatorSize.label,// indicator: BoxDecoration(//     color: Colors.blue, borderRadius: BorderRadius.circular(10)),controller: _tabController,tabs: const [Tab(child: Text("热门")),Tab(child: Text("推荐")),Tab(child: Text("视频"))],),),body: TabBarView(controller: _tabController,children: const [Text("热门"), Text("推荐"), Text("视频")],),);}
}

4.BottomNavigationBar 的页面中使用Tabbar

HomePage 中写的代码

import 'package:flutter/material.dart';class HomePage extends StatefulWidget {const HomePage({super.key});@overrideState createState() => _HomePageState();
}class _HomePageState extends Statewith SingleTickerProviderStateMixin {late TabController _tabController;//生命周期函数:当前组件初始化的时候就会触发@overridevoid initState() {super.initState();_tabController = TabController(length: 3, vsync: this);_tabController.addListener(() {if (_tabController.animation!.value == _tabController.index) {print(_tabController.index); //获取点击或滑动页面的索引值}});}@overrideWidget build(BuildContext context) {return Scaffold(appBar: PreferredSize(preferredSize: Size.fromHeight(40),child: Container(height: 40,child: AppBar(elevation: 0.5,backgroundColor: Colors.white,centerTitle: true,title: TabBar(labelStyle: TextStyle(fontSize: 14),isScrollable: true,indicatorColor: Colors.red,labelColor: Colors.red,unselectedLabelColor: Colors.black,indicatorWeight: 2,indicatorPadding: EdgeInsets.all(5),indicatorSize: TabBarIndicatorSize.label,// indicator: BoxDecoration(//     color: Colors.blue, borderRadius: BorderRadius.circular(10)),controller: _tabController,tabs: const [Tab(child: Text("热门")),Tab(child: Text("推荐")),Tab(child: Text("视频"))],),),),),body: TabBarView(controller: _tabController,children: const [Text("热门"), Text("推荐"), Text("视频")],),);}
}
1.PreferredSize可以改变appBar的高度
Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(50),
child: AppBar(
....
)
),
body: Test(),
)
2. 自定义KeepAliveWrapper 缓存页面

解决: 跳转其它页面返回后,自动回到了顶部
引入之后,包括在需要缓冲的外层

KeepAliveWrapper

import 'package:flutter/material.dart';class KeepAliveWrapper extends StatefulWidget {const KeepAliveWrapper({Key? key, @required this.child, this.keepAlive = true}): super(key: key);final Widget? child;final bool keepAlive;@overrideState createState() => _KeepAliveWrapperState();
}class _KeepAliveWrapperState extends Statewith AutomaticKeepAliveClientMixin {@overrideWidget build(BuildContext context) {return widget.child!;}@overridebool get wantKeepAlive => widget.keepAlive;@overridevoid didUpdateWidget(covariant KeepAliveWrapper oldWidget) {if (oldWidget.keepAlive != widget.keepAlive) {
// keepAlive 状态需要更新,实现在 AutomaticKeepAliveClientMixin 中updateKeepAlive();}super.didUpdateWidget(oldWidget);}
}
3.监听TabController改变事件(两种方式)
  //生命周期函数:当前组件初始化的时候就会触发@overridevoid initState() {super.initState();_tabController = TabController(length: 3, vsync: this);_tabController.addListener(() {//不判断回获取两次if (_tabController.animation!.value == _tabController.index) {print(_tabController.index); //获取点击或滑动页面的索引值}});}
TabBar(//只能监听点击事件,不能监听滑动onTap:(value) {},)

完整代码

import 'package:flutter/material.dart';
import '../tools/KeepAliveWrapper.dart';class HomePage extends StatefulWidget {const HomePage({super.key});@overrideState createState() => _HomePageState();
}class _HomePageState extends Statewith SingleTickerProviderStateMixin {late TabController _tabController;//生命周期函数:当前组件初始化的时候就会触发@overridevoid initState() {super.initState();_tabController = TabController(length: 3, vsync: this);_tabController.addListener(() {//不判断回获取两次if (_tabController.animation!.value == _tabController.index) {print(_tabController.index); //获取点击或滑动页面的索引值}});}//组件销毁的时候触发@overridevoid dispose() {// TODO: implement disposesuper.dispose();_tabController.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: PreferredSize(preferredSize: Size.fromHeight(40),child: Container(height: 40,child: AppBar(elevation: 0.5,backgroundColor: Colors.white,centerTitle: true,title: TabBar(//只能监听点击事件,不能监听滑动onTap: (value) {},labelStyle: TextStyle(fontSize: 14),isScrollable: true,indicatorColor: Colors.red,labelColor: Colors.red,unselectedLabelColor: Colors.black,indicatorWeight: 2,indicatorPadding: EdgeInsets.all(5),indicatorSize: TabBarIndicatorSize.label,// indicator: BoxDecoration(//     color: Colors.blue, borderRadius: BorderRadius.circular(10)),controller: _tabController,tabs: const [Tab(child: Text("热门")),Tab(child: Text("推荐")),Tab(child: Text("视频"))],),),),),body: TabBarView(controller: _tabController,children: const [KeepAliveWrapper(child: Text(("热门")),),KeepAliveWrapper(child: Text(("推荐")),),KeepAliveWrapper(child: Text(("视频")),),],),);}
}

16.Flutter 路由

1.普通路由使用

import '../SearchPage.dart';Center(
child: ElevatedButton(onPressed: (){
Navigator.of(context).push(
MaterialPageRoute(builder: (context){
return const SearchPage();
})
);
}, child: const Text("跳转到搜索页面")),
)

2.传值路由使用

Navigator.of(context).push(MaterialPageRoute(builder: (context) {return const SearchPage(title: "搜索页面",);}));
import 'package:flutter/material.dart';class SearchPage extends StatefulWidget {final String title;const SearchPage({super.key, this.title = "默认Search Page"});@overrideState createState() => _SearchPageState();
}class _SearchPageState extends State {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(widget.title),//获取SearchPage定义的title),body: Center(child: Text("搜索页面"),),);}
}

3.返回到上一页

  Navigator.pop(context);
  Navigator.of(context).pop();

17.Flutter 统一管理路由:命名路由

1.跳转

  Navigator.pushNamed(context, "/search");

main.dart

import 'package:flutter/material.dart';
import './pages/tabs.dart';
import './pages/search.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(debugShowCheckedModeBanner: false,theme: ThemeData(primarySwatch: Colors.blue),//home: const MyHomePage(),initialRoute: "/",routes: {'/': (contxt) => const MyHomePage(),'/search': (contxt) => const SearchPage(),},);}
}

2.跳转传值(和上面写法不一样)

  Navigator.pushNamed(context, '/search', arguments: {"title": "搜索页面",});

main.dart

import 'package:flutter/material.dart';
import './pages/tabs.dart';
import './pages/search.dart';void main() {runApp(MyApp());
}class MyApp extends StatelessWidget {//1、定义Map类型的routesMap routes = {'/': (contxt) => const MyHomePage(),'/search': (context, {arguments}) => SearchPage(arguments: arguments),};MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(debugShowCheckedModeBanner: false,theme: ThemeData(primarySwatch: Colors.blue),//home: const MyHomePage(),initialRoute: "/",//2、调用onGenerateRoute处理onGenerateRoute: (RouteSettings settings) {// 统一处理final String? name = settings.name;final Function? pageContentBuilder = routes[name];if (pageContentBuilder != null) {if (settings.arguments != null) {final Route route = MaterialPageRoute(builder: (context) =>pageContentBuilder(context, arguments: settings.arguments));return route;} else {final Route route = MaterialPageRoute(builder: (context) => pageContentBuilder(context));return route;}}return null;},);}
}

search.dart

import 'package:flutter/material.dart';class SearchPage extends StatefulWidget {final String title;final Map arguments;const SearchPage({super.key, this.title = "默认Search Page", required this.arguments});@overrideState createState() => _SearchPageState();
}class _SearchPageState extends State {@overridevoid initState() {print(widget.arguments);}@overrideWidget build(BuildContext context) {return Scaffold(floatingActionButton: FloatingActionButton(onPressed: () {Navigator.pop(context);},child: Icon(Icons.back_hand),),appBar: AppBar(title: Text(widget.title), //获取SearchPage定义的title),body: Center(child: Text("搜索页面"),),);}
}

3.Flutter 中的命名路由单独抽离到一个文件

新建routers/routers.dart 配置路由

import 'package:flutter/material.dart';
import '../tabs.dart';
import '../search.dart';final Map routes = {'/': (contxt) => const MyHomePage(),'/search': (context, {arguments}) => SearchPage(arguments: arguments),
};
var onGenerateRoute = (RouteSettings settings) {
// 统一处理final String? name = settings.name;final Function? pageContentBuilder = routes[name];if (pageContentBuilder != null) {if (settings.arguments != null) {final Route route = MaterialPageRoute(builder: (context) =>pageContentBuilder(context, arguments: settings.arguments));return route;} else {final Route route =MaterialPageRoute(builder: (context) => pageContentBuilder(context));return route;}}return null;
};

main.dart

class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(debugShowCheckedModeBanner: false,theme: ThemeData(primarySwatch: Colors.blue),//home: const MyHomePage(),initialRoute: "/",//2、调用onGenerateRoute处理onGenerateRoute: onGenerateRoute);}
}

18.Flutter 中替换路由、 返回到根路由

1.相当于要跳转的目标替换了本页面

Navigator.of(context).pushReplacementNamed('/registerSecond');

2.返回到根路由

Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (BuildContext context) {
return const Tabs();
}), (route) => false);

3.Flutter Android 和Ios使用同样风格的路由跳转

import ‘package:flutter/cupertino.dart’;
MaterialPageRoute改为CupertinoPageRoute
flutter run

19.Dialog

1.普通dialog async await

在这里插入图片描述

void _alertDialog() async {var result = await showDialog(context: context,builder: (context) {return AlertDialog(title: const Text("提示信息!"),content: const Text("您确定要删除吗?"),actions: [TextButton(child: const Text("取消"),onPressed: () {print("取消");Navigator.pop(context, 'Cancle');},),TextButton(child: const Text("确定"),onPressed: () {print("确定");Navigator.of(context).pop("Ok");// Navigator.pop(context, "Ok");},)],);});print(result);}

2.simpleDialog

在这里插入图片描述

 void _simpleDialog() async {var result = await showDialog(barrierDismissible: true, //表示点击灰色背景的时候是否消失弹出框context: context,builder: (context) {return SimpleDialog(title: const Text("请选择内容"),children: [SimpleDialogOption(child: const Text("Option A"),onPressed: () {print("Option A");Navigator.pop(context, "A");},),const Divider(),SimpleDialogOption(child: const Text("Option B"),onPressed: () {print("Option B");Navigator.pop(context, "B");},),const Divider(),SimpleDialogOption(child: const Text("Option C"),onPressed: () {print("Option C");Navigator.pop(context, "C");},),],);});print(result);}

3.showModalBottomSheet

_modelBottomSheet() async {var result = await showModalBottomSheet(context: context,builder: (context) {return SizedBox(height: 220,child: Column(children: [ListTile(title: const Text("分享 A"),onTap: () {Navigator.pop(context, "分享 A");},),const Divider(),ListTile(title: const Text("分享 B"),onTap: () {Navigator.pop(context, "分享 B");},),const Divider(),ListTile(title: const Text("分享 C"),onTap: () {Navigator.pop(context, "分享 C");},)],),);});print(result);}

4.toast 重启

https://pub.dev/packages/fluttertoast

在这里插入图片描述

20.自定义Dialog

import 'dart:async';
import 'package:flutter/material.dart';// ignore: must_be_immutable
class MyDialog extends Dialog {String title;String content;Function()? onClosed;MyDialog({Key? key,required this.title,required this.onClosed,this.content = ""}): super(key: key);@overrideWidget build(BuildContext context) {return Material(type: MaterialType.transparency,child: Center(child: Container(height: 300,width: 300,color: Colors.white,child: Column(children: [Padding(padding: const EdgeInsets.all(10),child: Stack(children: [Align(alignment: Alignment.center,child: Text(title),),Align(alignment: Alignment.centerRight,child: InkWell(onTap: onClosed,child: const Icon(Icons.close),),)],),),const Divider(),Container(padding: const EdgeInsets.all(10),width: double.infinity,child: Text(content, textAlign: TextAlign.left),)],),)),);}
}
void _myDialog() async {await showDialog(barrierDismissible: true, //表示点击灰色背景的时候是否消失弹出框context: context,builder: (context) {return MyDialog(title: '标题',onClosed: () {print("关闭");Navigator.of(context).pop();},content: "我是一个内容");});}

21.PageView

1.PageView

PageView(// scrollDirection: Axis.vertical, // 滑动方向为垂直方向children: [Center(child: Text("1",style: Theme.of(context).textTheme.headline1,),),Center(child: Text("2",style: Theme.of(context).textTheme.headline1,),),Center(child: Text("3",style: Theme.of(context).textTheme.headline1,),),Center(child: Text("4",style: Theme.of(context).textTheme.headline1,),),Center(child: Text("5",style: Theme.of(context).textTheme.headline1,),),Center(child: Text("6",style: Theme.of(context).textTheme.headline1,),)],)

2.PageView.builder

import 'package:flutter/material.dart';class MyPageView extends StatefulWidget {const MyPageView({super.key});@overrideState createState() => _MyPageViewState();
}class _MyPageViewState extends State {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("pageview演示"),),body: PageView.builder(scrollDirection: Axis.vertical, // 滑动方向为垂直方向itemBuilder: (BuildContext context, int index) {return MyPage(text: "$index");},itemCount: 10,));}
}class MyPage extends StatefulWidget {final String text;const MyPage({super.key, required this.text});@overrideState createState() => _MyPageState();
}class _MyPageState extends State {@overrideWidget build(BuildContext context) {return Center(child: Text(widget.text, style: Theme.of(context).textTheme.headline1),);}
}

3.PageView 上拉无限加载

import 'package:flutter/material.dart';class MyPageView extends StatefulWidget {const MyPageView({super.key});@overrideState createState() => _MyPageViewState();
}class _MyPageViewState extends State {final List _list = [];@overridevoid initState() {super.initState();for (var i = 0; i < 10; i++) {_list.add(MyPage(text: "$i"));}}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("pageview演示"),),body: PageView(scrollDirection: Axis.vertical, // 滑动方向为垂直方向onPageChanged: (index) {print(index);print(_list.length);if (index + 2 == _list.length) {setState(() {for (var i = 0; i < 10; i++) {_list.add(MyPage(text: "$i"));}});}},children: _list,));}
}class MyPage extends StatefulWidget {final String text;const MyPage({super.key, required this.text});@overrideState createState() => _MyPageState();
}class _MyPageState extends State {@overrideWidget build(BuildContext context) {return Center(child: Text(widget.text, style: Theme.of(context).textTheme.headline1),);}
}

4.PageView 实现一个无限轮播的轮播图

List.generate(widget.pageList.length, (i) { })
设置 left: 0, right: 0,就会占满一行
Flutter定时器
在这里插入图片描述

const timeout = Duration(seconds: 3);
var t=Timer.periodic(timeout, (timer) {
print('afterTimer='+DateTime.now().toString()););
// timer.cancel(); // 取消定时器
});
t.cancel(); // 取消定时器
import 'package:flutter/material.dart';
import './swiper.dart';class MyPageView extends StatefulWidget {const MyPageView({super.key});@overrideState createState() => _MyPageViewState();
}class _MyPageViewState extends State {List pageList = [];@overridevoid initState() {List listData = [{"imageUrl": 'https://www.itying.com/images/flutter/1.png',},{"imageUrl": 'https://www.itying.com/images/flutter/2.png',},{"imageUrl": 'https://www.itying.com/images/flutter/3.png',}];for (int i = 0; i < listData.length; ++i) {pageList.add(PicturePage(url: listData[i]["imageUrl"],));}}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("pageview演示"),),body: SizedBox(height: 200,child: PageView(//scrollDirection: Axis.vertical, // 滑动方向为垂直方向children: [Swiper(pageList: pageList)],),));}
}class MyPage extends StatefulWidget {final String text;const MyPage({super.key, required this.text});@overrideState createState() => _MyPageState();
}class _MyPageState extends State {@overrideWidget build(BuildContext context) {return Center(child: Text(widget.text, style: Theme.of(context).textTheme.headline1),);}
}
import 'package:flutter/material.dart';
import 'dart:async';class Swiper extends StatefulWidget {final double width;final double height;final List pageList;const Swiper({super.key,this.width = double.infinity,this.height = 200,required this.pageList});@overrideState createState() => _SwiperState();
}class _SwiperState extends State {late PageController _pageController;int _currentPageIndex = 0;late Timer timer;@overridevoid initState() {super.initState();_pageController = PageController(initialPage: 0);const timeout = Duration(seconds: 3);timer = Timer.periodic(timeout, (timer) {//跳转_pageController.animateToPage((_currentPageIndex + 1) % (widget.pageList.length),curve: Curves.linear,duration: const Duration(milliseconds: 200));// timer.cancel(); // 取消定时器});}@overridevoid dispose() {super.dispose();timer.cancel();_pageController.dispose();}@overrideWidget build(BuildContext context) {return Stack(children: [SizedBox(width: double.infinity,height: 200,child: PageView.builder(controller: _pageController,onPageChanged: (int index) {setState(() {_currentPageIndex = index % (widget.pageList.length);});},itemCount: 10000,itemBuilder: (context, index) {return widget.pageList[index % (widget.pageList.length)];}),),Positioned(bottom: 10,left: 0,right: 0,child: Row(mainAxisAlignment: MainAxisAlignment.center,children: List.generate(widget.pageList.length, (i) {return Container(margin: const EdgeInsets.fromLTRB(2, 0, 2, 0),width: 10,height: 10,decoration: BoxDecoration(shape: BoxShape.circle,color: _currentPageIndex == i ? Colors.blue : Colors.grey),);}).toList(),),),],);}
}class PicturePage extends StatefulWidget {final String url;final double width;final double height;const PicturePage({super.key,required this.url,this.width = double.infinity,this.height = 200});@overrideState createState() => _PicturePageState();
}class _PicturePageState extends State {@overrideWidget build(BuildContext context) {print(widget.url);return SizedBox(width: widget.width,height: widget.height,child: Image.network(widget.url, fit: BoxFit.cover),);}
}

5. AutomaticKeepAliveClientMixin 缓存PageView页面

6.自定义KeepAliveWrapper 缓存页面

KeepAliveWrapper(
child: Text((“热门”)),
),

22.Flutter Key详解

23.AnimatedList 实现动态列表

24.Flutter动画

相关内容

热门资讯

视频丨日本民众集会反对政府推进...   14日,部分日本民众在首相官邸前举行集会,要求日本首相高市早苗立即撤回错误言论,强烈抗议日本政府...
【中国那些事儿】外资持续加码彰...   中国日报网1月15日电 新年伊始,外资企业纷纷加码中国市场,多家企业宣布增加投资或启动新设施规划...
新华社评论员:切实把党中央重大...   新华社北京1月14日电 题:切实把党中央重大决策部署贯彻落实好——二论学习贯彻习近平总书记在二十...
“十五五”开好局起好步丨冰面上...   今年是“十五五”开局之年,我国将出台智能网联新能源汽车产业发展规划,以此推动新能源汽车产业高质量...
“十五五”电网投资4万亿元,创...   国家电网公司全面贯彻习近平新时代中国特色社会主义思想,深入贯彻党的二十大和二十届历次全会精神,坚...
著名电影表演艺术家陶玉玲逝世 ...   总台记者获悉,著名电影表演艺术家陶玉玲于今天(1月15日)下午在北京去世,享年92岁。其代表作有...
人民论坛网评 | 县域经济向“...   中央经济工作会议提出,统筹推进以县城为重要载体的城镇化建设和乡村全面振兴,推动县域经济高质量发展...
保险不只是合同,更是承诺 人们对保险的误解,往往从“花钱买纸”开始。很多人以为,交保费就是为了换一份合同,要是没出险,这笔钱就...
央广财评|韧性十足!中国外贸规...   海关总署披露的数据显示,2025年我国外贸进出口达45.47万亿元,增长3.8%,外贸规模创历史...
为反腐败安上科技“透视镜”——...   电视专题片《一步不停歇半步不退让》今天播出第四集《科技赋能反腐》。从追踪跨境腐败,到破解虚拟货币...