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.pngflutter 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.count GridView.extent
crossAxisCount 一行的Widget数量 maxCrossAxisExtent 横轴子元素的最大长度
gridDelegate SliverGridDelegateWithFixedCrossAxisCount SliverGridDelegateWithMaxCrossAxisExtent
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<Widget> _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<HomePage> {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<HomePage> {final List<String> _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<MyHomePage> createState() => _MyHomePageState();
}//有状态组件
class _MyHomePageState extends State<MyHomePage> {int _currentIndex = 0;final List<Widget> _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<MyHomePage> createState() => _MyHomePageState();
}//有状态组件
class _MyHomePageState extends State<MyHomePage> {int _currentIndex = 0;final List<Widget> _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: <Widget>[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: <Widget>[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: <Widget>[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: <Widget>[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 State<HomePage>with 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<HomePage> createState() => _HomePageState();
}class _HomePageState extends State<HomePage>with 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<HomePage> createState() => _HomePageState();
}class _HomePageState extends State<HomePage>with 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<KeepAliveWrapper> createState() => _KeepAliveWrapperState();
}class _KeepAliveWrapperState extends State<KeepAliveWrapper>with 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<HomePage> createState() => _HomePageState();
}class _HomePageState extends State<HomePage>with 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<SearchPage> createState() => _SearchPageState();
}class _SearchPageState extends State<SearchPage> {@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<SearchPage> createState() => _SearchPageState();
}class _SearchPageState extends State<SearchPage> {@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<String, Function> 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: <Widget>[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: <Widget>[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: <Widget>[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: <Widget>[Padding(padding: const EdgeInsets.all(10),child: Stack(children: <Widget>[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<MyPageView> createState() => _MyPageViewState();
}class _MyPageViewState extends State<MyPageView> {@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<MyPage> createState() => _MyPageState();
}class _MyPageState extends State<MyPage> {@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<MyPageView> createState() => _MyPageViewState();
}class _MyPageViewState extends State<MyPageView> {final List<Widget> _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<MyPage> createState() => _MyPageState();
}class _MyPageState extends State<MyPage> {@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<MyPageView> createState() => _MyPageViewState();
}class _MyPageViewState extends State<MyPageView> {List<Widget> 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<MyPage> createState() => _MyPageState();
}class _MyPageState extends State<MyPage> {@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<Widget> pageList;const Swiper({super.key,this.width = double.infinity,this.height = 200,required this.pageList});@overrideState<Swiper> createState() => _SwiperState();
}class _SwiperState extends State<Swiper> {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<PicturePage> createState() => _PicturePageState();
}class _PicturePageState extends State<PicturePage> {@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动画

Flutter基础知识相关推荐

  1. Flutter基础知识链接汇总(持续更新中)

    1.传送门:https://blog.csdn.net/tgbus18990140382/article/details/81181879 Flutter切换tab后保留tab状态 Automatic ...

  2. Flutter基础入门

    文章目录 一.Flutter基础知识 1.Flutter简介和发展历史 2.Flutter安装和配置 3.Dart语言基础知识 Dart语言特性 Dart基本语法 空安全 Null safety Da ...

  3. Flutter的基础知识之Dart语法

    Flutter的基础知识之Dart语法 关于TextStyle的设置 import 'package:flutter/material.dart'; void main() => runApp( ...

  4. Android基础知识梳理

    文章目录 系统架构 应用层 应用框架层 系统运行库层 硬件抽象层(HAL) Linux内核层 补充 通信方式 Binder IPC原理 Binder原理 Socket handler 主线程中 子线程 ...

  5. Flutter 基础目录结构介绍、入口自定义widget、等相关组件使用

    提示:此文章为前端学习flutter过程,如有歧义期望各位大大的宝贵意见 学习Dart 基础知识 移步这里 安装flutter环境相关 移步这里 flutter基础组件使用相关 移步这里 文章目录 一 ...

  6. Android Systrace 基础知识(9)-MainThread 和 RenderThread 解读

    本文是 Systrace 系列文章的第九篇,主要是是介绍 Android App 中的 MainThread 和 RenderThread,也就是大家熟悉的「主线程」和「渲染线程」.文章会从 Syst ...

  7. 嵌入式Linux的OTA更新,基础知识和实现

    嵌入式Linux的OTA更新,基础知识和实现 OTA updates for Embedded Linux, Fundamentals and implementation 更新的需要 一旦嵌入式Li ...

  8. 计算机基础知识第十讲,计算机文化基础(第十讲)学习笔记

    计算机文化基础(第十讲)学习笔记 采样和量化PictureElement Pixel(像素)(链接: 采样的实质就是要用多少点(这个点我们叫像素)来描述一张图像,比如,一幅420x570的图像,就表示 ...

  9. 嵌入式linux编程,嵌入式Linux学习笔记 - 嵌入式Linux基础知识和开发环境的构建_Linux编程_Linux公社-Linux系统门户网站...

    注:所有内容基于友善之臂Mini2440开发板 一.嵌入式Linux开发环境的构建 嵌入式开发一般分为三个步骤: 1.编译bootloader,烧到开发板 2.编译嵌入式Linux内核,烧到开发板 3 ...

最新文章

  1. 会计的思考(6):阳光是最好的杀虫剂—会计反映
  2. php树莓派养鱼,树莓派学习11: 将树莓派变成一个Web服务器
  3. 索引中丢失 IN 或 OUT 参数
  4. 如何用html构建ios应用,使用HTML5构建iOS原生APP
  5. YBTOJ洛谷P4074:糖果公园(树上莫队)
  6. mockito接口没法赋值_Mockito:无法实例化@InjectMocks字段:类型是接口
  7. block的使用(六)
  8. 最最基础的Android倒计时应用
  9. python 迭代多个对象
  10. 使用 Metasploit 利用 MySQL 默认空密码或弱密码漏洞 (CVE-2002-1809, CNNVD-200212-263, CVE-1999-0502)
  11. 脚本和网络课层的联系
  12. 木马万能查杀清除方法,木马专杀
  13. 香港站群多段服务器VPS大带宽服务器日本站群多段服务器
  14. zlib简单使用说明(转)
  15. SiteFactory支持ppt一键上传
  16. 基于STM32F103系列单片机四路定时器电机编码器模式配置过程附源码
  17. 微信小程序scroll-view实现滚动卡片
  18. 在Mysql中无符号是什么意思博客_mysql中的unsigned是什么意思???
  19. 腾讯游戏业务竟然是这样利用低代码平台的 | ArchSummit
  20. IBM 中国研究院面试经历

热门文章

  1. 彼得·德鲁克的一句话
  2. android textview layoutparams,Android动态设置布局的LayoutParams属性总遇到造型异常
  3. go调优工具gops使用
  4. 计算机专业怎么考护士证,护士资格证人机考试怎么考
  5. CoolShell-第2题
  6. 尼采关于人生和生活的语录
  7. sql查询指定日期到现在时间的日期列表
  8. Centos移动/home目录空间到/根目录下
  9. open-mmlab mmtracking中的DeepSort代码阅读
  10. Winograd快速卷积相关研究综述