Flutter 是一个跨平台的 UI 工具集,它的设计初衷,就是允许在各种操作系统上复用同样的代码,例如 iOS 和 Android,同时让应用程序可以直接与底层平台服务进行交互。如此设计是为了让开发者能够在不同的平台上,都能交付拥有原生体验的高性能应用,尽可能地共享复用代码的同时,包容不同平台的差异。
1.Dart
1.基础
1.1入口方法
main.dart
1.1注释
//
/**/
///
1.3定义变量
var strs= “dart”;
print(strs);
1.4声明变量
字符串
String str=”dart”;
数字类型
int num = 10;
1.5修饰符
var
final 只能赋值一次不能修改
const 一开始就赋值 常量不可变
1.6声明字符串
print(“$str1$str2”)
print(str1+str2) //字符串的连接
1.7List的声明
var list
var list = ["test",20,true];
//设置存放指定类型
var list =<String>["test","test1"];
list.length; //===>获取长度
list.add("add"); //===>添加元素
创建一个固定长度的数组
第一个参数为长度,第二个参数为填充的内容,无法增加数据,无法修改长度
void main() {
var list=List.filled(2,"1");
print(list);
}
1.8Map
第一种方式
var persion={
"name":"Dart",
"age":"8"
};
print(persion); //输出 {name: Dart, age: 8}
print(persion['name']); //输出 Dart
print(persion['age']); //输出 8
第二种方式
var persion1=new Map();
persion1["name"]="张三";
persion1["age"]="9";
print(persion1); //输出 {name: 张三, age: 9}
print(persion1['name']); //输出 张三
print(persion1['age']); //输出 9
1.9is判断类型
var str = '111';
if (str is String) {
print("str is String type");
} else if (str is int) {
print("str is int type");
} else {
print("str is other type");
}
1.10.运算符
+-*/ %取余 ~/取整
> < <= >= == !=
&&并且 || 或者 !取反
+=,-=,*=,/=,%=,~/=
判断为空之后赋值(??=)
int b;
b??=6; //当 b在这之前没有被赋值,则在这行代码中会被赋值
//解释:当a为null时,赋值??符号后的10给a,然后将a赋值给b.
// 当a不为null时,直接将a赋值给b
var a;
var b = a ?? 10;
print(b); // 输出10
1.11.类型转换
//将字符串转换为整型
String str='111';
var myNum=int.parse(str); //输出 111
其他类型转boolean
var mynum="";
if (mynum.isEmpty){
print("空");
}else{
print("非空");
}
// ===>空
a++
a—
自增自减运算
1.12.循环
for (int i=0;i<50;i++) while() do()while() 与java类似
void main(){
List list = [{
"title":"新闻1",
},{
"title":"新闻2",
},{
"title":"新闻3",
},{
"title":"新闻4",
}];
//for in 循环
for (var ele in list) {
print(ele["title"]);
}
}
11.13.List
常用属性
length 长度
reversed 翻转
isEmpty 是否为空
isNotEmpty 是否不为空
//增加 add
list.add("test");
//List<T>.filled(number,ele) 填充元素
List newlist = List<String>.filled(2, "1");
//全部加入,拼接数组 addAll
list.addAll(list1);
//翻转列表
List newlist = list.reversed.toList();
//indexOf()查找元素,找不到返回-1
List list = ["1","2","3"];
print(list.indexOf("1"));
//remove()移除
list.remove("1");
//fillRange(1,2,'aaa'); 从1开始到索引2,填充为'aaa'
list.fillRange(1,2,'aaa');
//insert() 在索引值插入插入
list.insert(1,"4");
//insertAll 插入全部数组
list.insertAll(1,["5","6"]);
//join拼接数组
var desc = list.join('-');
//split
var list = desc.split('-');
11.14.Set
去除数组重复的内容
Set是没有顺序且不能重复的集合,所以不能通过所有去获取值
keys 获取所有的key值
values 获取所有的value值
isEmpty 判断是否为空
isNotEmpty 判读是否不为空
11.15.遍历
1.forEach
list.forEach((value){
print(value);
});
2.map
var newlist = list.map((value){
return value + "6";
});
print(newlist.toList());
3.any
var res = list.any((value){
return value>5;
});
print(res);
//有一个满足返回true
4.every
var res = list.every((value){
return value>5;
});
print(res);
//全部满足返回true
Map person = {
"name":"tom",
"age":19
};
person.forEach((key,value){
print(key.toString()+"-"+value.toString());
});
2.函数
1.定义
可以在main函数内或者main函数外
void printinfo(){
print("test");
}
printinfo();
2.可选参数
此时的gender 和 age为可选参数
String test(String name,[String gender,int age]){
if (age != null){
return "name:${name},gender:${gender}";
}
return "name:${name},gender:${gender},age:${age}";
}
3.默认参数
String test(String name,[String gender="man",int age]){
if (age != null){
return "name:${name},gender:${gender}";
}
return "name:${name},gender:${gender},age:${age}";
}
4.命名参数
String test(String name,{String gender="man",int age}){
if (age != null){
return "name:${name},gender:${gender}";
}
return "name:${name},gender:${gender},age:${age}";
}
//调用的参数和形参名相同
5.将函数当做参数传递
fn1(fn2){
fn2();
}
fn2(){
print("object");
}
fn1(fn2);
6.使用匿名函数传递参数
var fn = ()=>{
print("mytest");
};
fn3(fn){
fn();
}
fn3(fn);
7.箭头函数
list.forEach((item)=>print(item.toString()));
8.自执行方法
((value){
print(value);
})(2);
9.必包
void test1(){
var a = 0;
print(a);
a++;
}
test1();
3.类
1.定义
class Person{
String name = "zs";
String email = "123@git.com";
String address = "America";
void getinfo(){
print("${name}${email}${address}");
}
}
var p1 = new Person();
print(p1.name);
p1.getinfo();
2.构造函数
Person(String name,String email,String address){
this.name = name;
this.email = email;
this.address = address;
}
3.简写的构造函数
Person(this.name,this.email,this.address);
4.命名构造函数
Person.now(){
print("命名构造函数");
}
var p = new Person.now();
5.私有成员属性,加下划线
class Person{
//私有属性
String _name = "zs";
String _email = "123@git.com";
String _address = "America";
Person();
//私有方法
String _getname(){
return this._name;
}
void getinfo(){
print("${this._name}${this._email}${this._address}");
}
}
6.get set
class Rect{
num height;
num width;
Rect(this.height,this.width);
get area{
return height*width;
}
set areaheight(value){
this.height = value;
}
}
7.在实例化之前进行赋值操作
Rect():height=2,width=10{
}
8.静态属性和静态方法static
在属性和方法前加上static
非静态方法可以调用静态成员和非静态成员
静态方法无法访问非静态的属性和方法
9.对象操作符
?条件运算符
as 类型转换
is类型判断 Person is Object ====>true
..联级操作
var p;
//不为空才调用
p?.getinfo();
var s;
s="";
s=new Person();
(s as Person).getinfo();
//..联级操作 赋值之后进行调用方法操作
Person p = new Person();
p..name = "city"
..email = "123@m.com"
..getinfo();
4.继承
1.定义继承
class Animal{
}
class Cat extends Animal{
}
2.实例化子类给父类传参
class Animal{
String name;
String kind;
Animal(this.name,this.kind);
getinfo(){
print("${name}-${kind}");
}
}
class Cat extends Animal{
Cat(String name,String kind):super(name,kind);
}
在覆写父类的方法时可以加上@override也可以不写
super.父类方法名 调用父类的方法
2.抽象类
抽象并且定义标准
父类定义一个方法不去实现,子类有不同的实现 —》 多态
abstract class Wolf{
void run();
}
class Dog extends Wolf{
void run(){
print("run");
}
}
3.一个类实现多个接口
abstract class A{
void run();
}
abstract class B{
void walk();
}
class C implements A,B{
void run() {
// TODO: implement run
}
void walk() {
// TODO: implement walk
}
}
4.mixins
mixin A{
void run(){
print("A");
}
}
mixin B{
void walk(){
print("B");
}
}
class C with A,B{
}
1.作为mixins的类只能继承自Object,不能继承其他类
2.作为mixins的类不能有构造函数
3.一个类可以mixins多个mixins的类
4.minxins不是继承,也不是接口,而是一种特性
C c = new C()
print(C is A)
print(c is B)
print(c is C)
- true true true
5.泛型
1.泛型方法
print(getData<num>(12));
}
T getData<T>(T value){
return value;
}
2.泛型类
class MyList<T>{
List list = <T>[];
void add(value){
list.add(value);
}
}
3.泛型接口
文件缓存,内存缓存
1.getBykey 和 setBykey
abstract class Cache<T>{
getByKey(String key);
setByKey(String key,T value);
}
class FileCache<T> implements Cache{
getByKey(String key) {
return null;
}
setByKey(String key, value) {
print(key +"="+ value);
}
}
class MemoeryCache<T> implements Cache{
getByKey(String key) {
return null;
}
setByKey(String key, value) {
print(key +"="+ value);
}
}
3.内置库dart:io
可以使用async 和 await
async让方法变成异步
await等待异步方法的完成
4.第三方库
pub get
The official repository for Dart and Flutter packages. (pub.dev)
import '' show get; //从一个模块仅导入get方法
import '' hiden get; //不需要get方法
import '' deferred; //懒加载,用到才导入
6. 2.13新特性
1.可空类型
int a=12; //声明a为不可空类型
a = null;
//此时会报错,因为dart有Null safety
int? a=12; //声明a为可空类型
a=null;
String test(url){
if (url !=null){
return 'test';
}
return null;
}
//报错,返回值可能为null
String? test(url){
if (url !=null){
return 'test';
}
return null;
}
//声明返回值为可空
2.类型断言
void test(String? url){
//如果不为空会打印出长度,为空会抛出异常
print(url!.length);
}
void test(String? url){
//如果不为空会打印出长度,为空会抛出异常
try{
print(url!.length);
}catch(error){
print("url为空");
}
}
3.late关键字
late关键字用来延迟初始化
class person{
late String name;
late String age;
void setname(String name,String age){
this.name = name;
this.age = age;
}
}
4.require 用来标记为必填参数
void PrintTest({required String name,required String age}){
}
7.性能优化
1.常量
const PI = 3.14 –>定义常量
- const final
- const 声明的常量是在编译时确定的
- final 声明的常量允许声明后再赋值,赋值后不可改变s
2.identical
var a = new Object();
var b = new Object();
print(identical(a, b)); //查看两个对象是否共用同一个内存空间
// ---->false
const 在多个地方定义相同的对象时,内存只保留了一个对象
const a = Object();
const b = Object();
print(identical(a, b)); //查看两个对象是否共用同一个内存空间
// ---->true
3.常量构造函数
常量构造函数以const开头
const 构造函数必须用于成员变量都是final的类
如果实例化不加const,即使调用的是常量构造函数 ,实例化的成员也不是常量实例对象
class person{
final String name;
final String age;
const person({required this.name,required this.age});
}
const a = const person(name:"test",age:"12");
const b = const person(name:"test",age:"12");
print(identical(a, b)); //查看两个对象是否共用同一个内存空间
//---->true
2.Flutter基础
配置JDK,下载Android studio
1.配置Flutter
1.下载SDK
https://docs.flutter.dev/get-started/install/windows/mobile
2.配置镜像
PUB_HOSTED_URL:https://pub.flutter-io.cn
FLUTTER_STORAGE_BASE_URL:https://storage.flutter-io.cn
3.配置环境变量
sdk的bin目录
4.报错说需要同意证书
安装安卓命令行工具 cmdline-tools
flutter doctor –android-licenses
2.flutter项目文件
创建flutter项目
flutter create rctool
lib –> 所有的代码将会写在lib目录下
pubspec.yaml —>配置文件
3.入口main.dart
void main(){
runApp(const Center(
child: Text("哈哈哈",textDirection: TextDirection.ltr,style: TextStyle(
color: Color.fromRGBO(35, 67, 188, 1), //字体颜色
fontSize: 40 //字体大小
),),
));
}
3.Flutter组件
MaterialApp和Scaffold两个组件装饰APP
1.MaterialApp
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("hello flutter")),
body: const Center(
child: Text("哈哈哈",textDirection: TextDirection.ltr,style: TextStyle(
color: Color.fromRGBO(35, 67, 188, 1), //字体颜色
fontSize: 40 //字体大小
))
))
));
}
statelessWidget 无状态组件,状态不可变的Widget
statefulWidget 状态组件,状态可能在生命周期发生改变
class myApp extends StatelessWidget{
const myApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return const Center(
child: Text("哈哈哈",textDirection: TextDirection.ltr,style: TextStyle(
color: Color.fromRGBO(35, 67, 188, 1), //字体颜色
fontSize: 40 //字体大小
))
);
}
}
2.Container容器组件
alignment(这个属性是针对容器中的child的对其方式)
topCenter:顶部居中对齐
topLeft:顶部左对齐
topRight:顶部右对齐
center:水平垂直居中对齐
centerLeft:垂直居中水平居左对齐
centerRight:垂直居中水平居右对齐
bottomCenter底部居中对齐
bottomLeft:底部居左对齐
bottomRight:底部居右对齐
decoration(容器的修饰器,用于背景或者border)
如果在decoration中用了color,就把容器中设置的color去掉,不要重复设置color,设置的边框样式是让四条边框的宽度为8px,颜色为黑 色
margin(margin属性是表示Container与外部其他组件的距离)
padding(指Container边缘与Child之间的距离)
padding: EdgeInsets.all(20.0),
transform(可以根据自己的需要调整旋转的角度)
transform: Matrix4.rotationZ(0.2)
width宽度
height高度
class myApp extends StatelessWidget{
const myApp({super.key});
Widget build(BuildContext context) {
return Center(
child: Container(
alignment: Alignment.center, //对齐位置
width: 100,
height: 100,
//margin: EdgeInsetsGeometry.lerp(),
decoration: BoxDecoration(
color: Colors.red, //背景颜色
border: Border.all( //边框
color: Colors.blue,
width: 2
),
borderRadius: BorderRadius.circular(50), //圆角
boxShadow: const [ //配置阴影效果
BoxShadow(color:Colors.black,
blurRadius: 10.0
)
],
gradient: const LinearGradient(colors: [Colors.amberAccent,Colors.red])
),
child: const Text("data",style: TextStyle(color: Colors.amberAccent),),
)
);
}
}
margin
margin: const EdgeInsets.fromLTRB(left, top, right, bottom)
transform 移动
transform: Matrix4.translationValues(x, y, z), //位移
transform: Matrix4.rotationX(radians), //旋转 radians为角度
transform: Matrix4.skewX(alpha), //缩放
3.Text组件
style | 文字样式(颜色、粗细) |
---|---|
textAlign | 文字对齐样式 |
overflow | 文字字数超出后样式 |
textScaleFactor | 文字大小 |
maxLines | 最大行数 |
4.Image组件
1.加载远程图片
Image.network("")
child: Image.asset("assert/a8f6066ff11c400a10419beba3dd2a61.jpg",
fit: BoxFit.fill,
),
fit 可以控制图片的填充形式,宽度填满等
实现圆角图片
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(150),
image: const DecorationImage(
image: NetworkImage("https://pss.bdstatic.com/static/superman/img/logo/bd_logo1-66368c33f8.png"),
fit:BoxFit.cover
),
),
ClipOval实现圆角图片
return ClipOval(
child: Image.network("https://pss.bdstatic.com/static/superman/img/logo/bd_logo1-66368c33f8.png",
width: 150,
height: 150,
fit: BoxFit.cover,
),
);
2.加载本地图片
pubspec.yaml
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
assets:
- images/a.jpg
- images/2.0x/a.jpg
- images/3.0x/a.jpg
5.Icon图标
Icon(Icons.home,size: 40,color: Colors.blue,)
1.pubspec.yaml
fonts:
- family: richuicon //自定义字体名
fonts:
- asset: fonts/iconfont.ttf
2.自定义图标
class richuicon{
static const IconData check = IconData(
0xe645, //unicode编码
fontFamily: "richuicon", //自定义的fontFamily
matchTextDirection: true
);
static const IconData close = IconData(
0xe646, //unicode编码
fontFamily: "richuicon", //自定义的fontFamily
matchTextDirection: true
);
}
3.使用
Icon(richuicon.check,size: 40,color: Colors.amberAccent,)
6.ListView
1.静态
可滑动
ListView(
children: const <Widget>[myApp(),myButton(),myImage(),Icon(Icons.home,size: 40,color: Colors.blue,),
Icon(richuicon.check,size: 40,color: Colors.amberAccent,)
],
)
scrollDirection Axis.horizationtal水平列表 Axis.vertical垂直列表
2.动态展示数据
class mylist extends StatelessWidget {
List<Widget> initdata(){
List<Widget> list = [];
for (var i=0;i<10;i++){
list.add( ListTile(
title: Text("data$i"),
));
}
return list;
}
const mylist({super.key});
Widget build(BuildContext context) {
return ListView(
children: initdata(),
);
}
}
使用ListViewBuilder
class myview extends StatelessWidget {
List<String> list = [];
myview({super.key}){
for (var i=0;i<10;i++){
list.add("data$i");
}
}
Widget build(BuildContext context) {
return ListView.builder(
itemCount: list.length,
itemBuilder:(context,index){
return ListTile(
title: Text("data:${list[index]}"),
);
},
);
}
}
7.网格组件Gridview
基本用法
class mygrid extends StatelessWidget{
const mygrid({super.key});
Widget build(BuildContext context) {
return GridView.count(crossAxisCount: 3, //一行有多少Widget
children: const [
Icon(Icons.bike_scooter),
Icon(Icons.bike_scooter),
Icon(Icons.bike_scooter),
Icon(Icons.bike_scooter),
Icon(Icons.bike_scooter),
Icon(Icons.bike_scooter),
Icon(Icons.bike_scooter),
Icon(Icons.bike_scooter),
Icon(Icons.bike_scooter),
Icon(Icons.bike_scooter),
Icon(Icons.bike_scooter)
],
);
}
}
1、GridView.count(@required int crossAxisCount)
GridView.count的使用,需要传的是int类型的参数,也就是创建固定数量的item,crossAxisCount表示横轴item的个数(系统默认是横轴);
2、GridView.extent(@required double maxCrossAxisExtent)
GridView.extent的使用,需要传的是double类型的参数,也就是创建横轴上最大可容纳的item,maxCrossAxisExtent表示横轴item的最大宽度;
3、GridView.builder(@required this.gridDelegate,@required IndexedWidgetBuilder itemBuilder)
适用于widget数量多的时候,通过GridView.builder的使用,动态的创建widget,itemBuilder表示子widget构造器;
4、GridView.custom(@required this.gridDelegate,@required this.childrenDelegate)
GridView.custom的使用,通过两个代理方法gridDelegate和childrenDelegate来创建Gridview,其中gridDelegate是进行布局的代理,控制每列或每行的子widget的数量,以及上下左右间距和宽高比例;childrenDelegate的代理方法有两种实现方式,在使用的时候需要注意二者的区别。
属性 | 说明 |
---|---|
scrollDirection | 滚动方向 |
reverse | 组件反向排序 |
controller | 滚动控制(滚动监听) |
primary | 如果内容不足,则用户无法滚动 而如果[primary]为true,它们总是可以尝试滚动。 |
physics | 滑动类型设置 AlwaysScrollableScrollPhysics 总是可以滑动 NeverScrollableScrollPhysics 禁止滚动 BouncingScrollPhysics 内容超过一屏 上拉有回弹效果 ClampingScrollPhysics 包裹内容 不会有回弹 |
shrinkWrap | 默认false 内容适配 |
padding | 内边距 |
crossAxisCount | 列 数量 |
mainAxisSpacing | 垂直子 Widget 之间间距 |
crossAxisSpacing | 水平子 Widget 之间间距 |
childAspectRatio | 子 Widget 宽高比例 |
addAutomaticKeepAlives | 默认true |
addRepaintBoundaries | 默认true |
addSemanticIndexes | 默认true |
cacheExtent | 设置预加载的区域 |
children | 子元素 |
semanticChildCount | 将提供语义信息的子代数量 |
dragStartBehavior | |
GridView.builder独有属性 | |
gridDelegate | 一个控制 GridView 中子项布局的委托。 |
itemBuilder | 遍历数返回Widget |
itemCount | 子控件数量 |
GridView.builder
lass mybuild extends StatelessWidget{
Widget initGridData(context,index){
return Container(
decoration: const BoxDecoration(
color: Colors.blueAccent
),
child: Column(
children: [
Image.asset("images/a.jpg"),
const Text("hahaha")
],
),
);
}
Widget build(BuildContext context) {
return GridView.builder(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 0),
itemCount: 10,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
childAspectRatio: 1.2
), itemBuilder: initGridData);
}
}
8.Padding组件
padding padding值,EdgeInsets设置填充的值
child 子组件
4.线性布局
1.Row组件
宽度自适应
void main(){
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("hello flutter")),
body: const SizedBox(
height: 400,
width: 400,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, //控制主轴的方向
crossAxisAlignment: CrossAxisAlignment.center, //控制侧轴对其
children:[ IconContainer(),IconContainer(),IconContainer()],
),
)
)
)
);
}
class IconContainer extends StatelessWidget{
const IconContainer({super.key});
Widget build(BuildContext context) {
return Container(
height: 100,
width: 100,
alignment: Alignment.center,
decoration:const BoxDecoration(
color:Colors.red
),
child:const Icon(Icons.add,color: Colors.blueAccent,size: 32,),
);
}
}
2.Column布局
高度自适应
void main(){
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("hello flutter")),
body: const SizedBox(
height: 400,
width: 400,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, //控制主轴的方向
crossAxisAlignment: CrossAxisAlignment.center, //控制侧轴对其
children:[ IconContainer(),IconContainer(),IconContainer()],
),
)
)
)
);
}
class IconContainer extends StatelessWidget{
const IconContainer({super.key});
Widget build(BuildContext context) {
return Container(
height: 100,
width: 100,
alignment: Alignment.center,
decoration:const BoxDecoration(
color:Colors.red
),
child:const Icon(Icons.add,color: Colors.blueAccent,size: 32,),
);
}
}
3.弹性布局
Expanded
flex 设置占的份数
void main(){
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("hello flutter")),
body: const Flex(
direction: Axis.horizontal,
children: [
Expanded(
flex:1,
child: IconContainer()
),
Expanded(
flex:2,
child: IconContainer()
),
],
)
)
)
);
}
4.Stack层叠组件
以堆的方式放入children子组件,所有的组件都堆在一起
void main(){
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("hello flutter")),
body: Stack(
children: [
Container(
height: 400,
width: 500,
color: Colors.red,
),
const Text("data",textAlign: TextAlign.center,)
],
)
)
)
);
}
Positioned
- top
- bottom
- left
- right
- height
- width (宽度和高度必须为固定值,不能为double.infinity)
定位类型css的position
5.Align
可以控制子组件的位置
void main(){
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("hello flutter")),
body: const Align(
alignment: Alignment.center,
child: Text("data"),
)
)
)
);
}
6.AspectRatio
aspectRatio 宽高比
class myaspect extends StatelessWidget{
const myaspect({super.key});
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 3/1,
child: Container(
color: Colors.red,
),
);
}
}
7.Card
class mycard extends StatelessWidget{
const mycard({super.key});
Widget build(BuildContext context) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
),
elevation: 10, //设置阴影深度
margin:const EdgeInsets.fromLTRB(0, 10, 0, 0) ,
child: const Column(
children: [Text("data")],
)
);
}
}
8.CircleAvatar
通过CircleAvatar 实现圆形图片
class mycard extends StatelessWidget{
const mycard({super.key});
Widget build(BuildContext context) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)
),
elevation: 10, //设置音乐深度
margin:const EdgeInsets.fromLTRB(0, 10, 0, 0) ,
child: const Column(
children: [Text("data"),
CircleAvatar(
radius: 10,
backgroundImage: AssetImage("images/a.jpg"),
)
],
)
);
}
}
9.ElevatedButton,TextBtton,IconButton
class myButton extends StatelessWidget{
const myButton({super.key});
Widget build(BuildContext context) {
/* return SizedBox(
child: ElevatedButton(onPressed: (){}, child: const Text("click")),//普通按钮
);*/
/* return SizedBox(
child: TextButton(onPressed: (){}, child: const Text("click")),//文本按钮
); */
/* return SizedBox(
child: OutlinedButton(onPressed: (){}, child: const Text("click")),//文本按钮
);*/
/* return SizedBox(
child: IconButton(onPressed: (){}, icon:const Icon(Icons.access_alarm)),//边框按钮
);*/
return SizedBox(
child: ElevatedButton.icon(onPressed: (){}, icon:const Icon(Icons.access_alarm),label: const Text("提醒",style: TextStyle(color: Colors.red,))),//图标加文字
);
}
}
ButtonStyle
class myButton1 extends StatelessWidget{
const myButton1({super.key});
Widget build(BuildContext context) {
return SizedBox(
child: SizedBox(
child: ElevatedButton.icon(
style: ButtonStyle( //设置按钮样式
backgroundColor: WidgetStateProperty.all(Colors.amberAccent),
foregroundColor: const WidgetStatePropertyAll(Colors.blueAccent)
),
onPressed: (){},
icon:const Icon(Icons.access_alarm),
label: const Text("提醒",style: TextStyle(color: Colors.red,fontSize: 10))),//图标加文字,
),
);
}
}
10.Wrap组件
当x轴无法显示时可以显示到y轴
void main(){
runApp(MaterialApp(
home: Scaffold(
body: ListView(
padding: const EdgeInsets.all(10),
children:[ Layout("热搜"),Wrap(
spacing: 10, //间距
alignment: WrapAlignment.spaceAround,
runSpacing: 10, //间距
children: [ElevatedButton(onPressed:(){}, child: const Text("1") ),
ElevatedButton(onPressed:(){}, child: const Text("2") ),
ElevatedButton(onPressed:(){}, child: const Text("3") ),
ElevatedButton(onPressed:(){}, child: const Text("4") ),
ElevatedButton(onPressed:(){}, child: const Text("5") ),
ElevatedButton(onPressed:(){}, child: const Text("6") ),
ElevatedButton(onPressed:(){}, child: const Text("7") ),
ElevatedButton(onPressed:(){}, child: const Text("8") ),
ElevatedButton(onPressed:(){}, child: const Text("9") ),
],
),const SizedBox(height: 10,),
Layout("历史记录"),
const Divider(),
const Column(
children: [ListTile(title: Text("5"),
),Divider(),
ListTile(title: Text("6")),
Divider()
],
)
],
)
)
)
);
}
class Layout extends StatelessWidget{
var text;
Layout(this.text,{super.key});
Widget build(BuildContext context) {
return Row(
children: [
Text(text,style: Theme.of(context).textTheme.titleLarge,)
],
);
}
}
5.StatefulWidget有状态组件
实现点击按钮++
class HomeState extends StatefulWidget{
const HomeState({super.key});
State<HomeState> createState()=> _HomeState();
}
class _HomeState extends State<HomeState>{
int _num = 0;
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("$_num"),
const SizedBox(height: 10,),
ElevatedButton(onPressed: (){
setState(() {
_num++;
});
}, child:const Text("++"))
],
),
);
}
}
添加一个浮动按钮
void main(){
runApp(
MaterialApp(
title: "richu",
home: Scaffold(
body:HomeState(),
floatingActionButton: FloatingActionButton(onPressed: (){
},child: Text("click me"),),
),
)
);
}
实现动态列表
void main(){
runApp(
const MaterialApp(
title: "richu",
home: HomeState()
));
}
class HomeState extends StatefulWidget{
const HomeState({super.key});
State<HomeState> createState()=> _HomeState();
}
class _HomeState extends State<HomeState>{
final List<String> _list = [];
int num = 1;
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(onPressed: (){
setState(() {
_list.add("data$num");
num++;
});
},child: const Text("+"),),
appBar: AppBar(title:const Text("richu")),
body: ListView(
children:_list.map((v){
return ListTile(
title: Text(v),
);
}).toList()
),
);
}
}
1.BottomNavigationBar
自定义底部导航栏
items 配置底部菜单项
Ontab 点击事件
curretIndex 索引
Iconsize 底部图标的大小
fixedColor 选中的颜色
type:BottomNavigationBarType.fixed 如果菜单超过三个则需要加上这个
void main(){
runApp(
const MaterialApp(
title: "richu",
home: HomeState()
));
}
class HomeState extends StatefulWidget{
const HomeState({super.key});
State<HomeState> createState()=> _HomeState();
}
class _HomeState extends State<HomeState>{
int currentId = 0;
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(onTap: (index){
setState(() {
currentId = index;
});
},currentIndex: currentId,items: const[
BottomNavigationBarItem(icon: Icon(Icons.home),label: "首页"),
BottomNavigationBarItem(icon: Icon(Icons.settings),label: "设置"),
BottomNavigationBarItem(icon: Icon(Icons.supervised_user_circle),label: "用户")]),
appBar: AppBar(title:const Text("richu")),
body: const Text("data")
);
}
}
2.实现页面切换
import 'package:flutter/material.dart';
import './tabs/user.dart';
import './tabs/home.dart';
import './tabs/setting.dart';
void main(){
runApp(
const MaterialApp(
title: "richu",
home: HomeState()
));
}
class HomeState extends StatefulWidget{
const HomeState({super.key});
State<HomeState> createState()=> _HomeState();
}
class _HomeState extends State<HomeState>{
int currentId = 0;
final List<Widget> _list = const [
MyHomePage(),
SettingPage(),
UserPage(),
];
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(onTap: (index){
setState(() {
currentId = index;
});
},currentIndex: currentId,items: const[
BottomNavigationBarItem(icon: Icon(Icons.home),label: "首页"),
BottomNavigationBarItem(icon: Icon(Icons.settings),label: "设置"),
BottomNavigationBarItem(icon: Icon(Icons.supervised_user_circle),label: "用户")]),
appBar: AppBar(title:const Icon(Icons.arrow_back)),
body: _list[currentId]
);
}
}
3.FloatingActionButton实现底部突起按钮
shape:const CircleBorder()
void main(){
runApp(
const MaterialApp(
title: "richu",
home: HomeState()
));
}
class HomeState extends StatefulWidget{
const HomeState({super.key});
State<HomeState> createState()=> _HomeState();
}
class _HomeState extends State<HomeState>{
int currentId = 0;
final List<Widget> _list = const [
MyHomePage(),
SettingPage(),
UserPage(),
];
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(onTap: (index){
setState(() {
currentId = index;
});
},currentIndex: currentId,fixedColor: Colors.blue,type: BottomNavigationBarType.fixed,items: const[
BottomNavigationBarItem(icon: Icon(Icons.home),label: "首页"),
BottomNavigationBarItem(icon: Icon(Icons.settings),label: "设置"),
BottomNavigationBarItem(icon: Icon(Icons.supervised_user_circle),label: "用户"),
//BottomNavigationBarItem(icon: Icon(Icons.supervised_user_circle),label: "用户")
]),
appBar: AppBar(title:const Icon(Icons.arrow_back)),
floatingActionButton: Container(
height: 60,
width: 60,
decoration:BoxDecoration(
color: Colors.black12,
borderRadius: BorderRadius.circular(30)
),
child: FloatingActionButton(shape:const CircleBorder(),onPressed: (){
setState(() {
currentId = 1;
});
},child: const Icon(Icons.add),),),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
body: _list[currentId]
);
}
}
4.Drawer侧边栏
void main(){
runApp(
const MaterialApp(
title: "richu",
home: HomeState()
));
}
class HomeState extends StatefulWidget{
const HomeState({super.key});
State<HomeState> createState()=> _HomeState();
}
class _HomeState extends State<HomeState>{
int currentId = 0;
final List<Widget> _list = const [
MyHomePage(),
SettingPage(),
UserPage(),
];
Widget build(BuildContext context) {
return Scaffold(
drawer: const Drawer(
child: Column(
children: [
DrawerHeader(child: ListTile(leading: Icon(Icons.home),title: Text("信息"),
)),
Divider(),
ListTile(
leading: CircleAvatar(child:Icon(Icons.supervised_user_circle)),
title: Text("用户中心"),
),Divider(),
ListTile(
leading: CircleAvatar(child:Icon(Icons.delete)),
title: Text("删除"),
),Divider()
],
),
),
bottomNavigationBar: BottomNavigationBar(onTap: (index){
setState(() {
currentId = index;
});
},currentIndex: currentId,fixedColor: Colors.blue,type: BottomNavigationBarType.fixed,items: const[
BottomNavigationBarItem(icon: Icon(Icons.home),label: "首页"),
BottomNavigationBarItem(icon: Icon(Icons.settings),label: "设置"),
BottomNavigationBarItem(icon: Icon(Icons.supervised_user_circle),label: "用户"),
]),
appBar: AppBar(title:const Icon(Icons.arrow_back)),
body: _list[currentId]
);
}
}
5.UserAccountDrawHeader
class _HomeState extends State<HomeState>{
int currentId = 0;
final List<Widget> _list = const [
MyHomePage(),
SettingPage(),
UserPage(),
];
Widget build(BuildContext context) {
return Scaffold(
drawer: const Drawer(
child: Column(
children: [
/*DrawerHeader(child: ListTile(leading: Icon(Icons.home),title: Text("信息"),
)),*/
UserAccountsDrawerHeader(accountName: Text("日初"), accountEmail: Text("xxx@163.com"),currentAccountPicture:CircleAvatar(backgroundImage: AssetImage("images/a.jpg"))),
Divider(),
ListTile(
leading: CircleAvatar(child:Icon(Icons.supervised_user_circle)),
title: Text("用户中心"),
),Divider(),
ListTile(
leading: CircleAvatar(child:Icon(Icons.delete)),
title: Text("删除"),
),Divider()
],
),
),
bottomNavigationBar: BottomNavigationBar(onTap: (index){
setState(() {
currentId = index;
});
},currentIndex: currentId,fixedColor: Colors.blue,type: BottomNavigationBarType.fixed,items: const[
BottomNavigationBarItem(icon: Icon(Icons.home),label: "首页"),
BottomNavigationBarItem(icon: Icon(Icons.settings),label: "设置"),
BottomNavigationBarItem(icon: Icon(Icons.supervised_user_circle),label: "用户"),
]),
appBar: AppBar(title:const Icon(Icons.arrow_back)),
body: _list[currentId]
);
}
}
6.Bar
1.AppBar
debugShowCheckedModeBanner: false 关闭debug图标
void main(){
runApp(
const MaterialApp(
debugShowCheckedModeBanner: false,
title: "richu",
home: HomeState()
));
}
class HomeState extends StatefulWidget{
const HomeState({super.key});
State<HomeState> createState()=> _HomeState();
}
class _HomeState extends State<HomeState>{
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(onPressed: (){}, icon: const Icon(Icons.menu)), //左侧的按钮图标,
actions: [
IconButton(onPressed: (){}, icon: const Icon(Icons.add)) //右侧图标
],
),
body:const Text("data")
);
}
}
2.TabBar
tabbar和tabbarView都要配置Controller
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin{
late TabController _tabController;
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(onPressed: (){}, icon: const Icon(Icons.menu)), //左侧的按钮图标,
actions: [
IconButton(onPressed: (){}, icon: const Icon(Icons.add)) //右侧图标
],
bottom: TabBar(controller:_tabController ,tabs:const [
Tab(child: Text("推荐")),Tab(child: Text("热门")),Tab(child: Text("视频"),)
]),
),
body:TabBarView(controller: _tabController ,children:const [ListTile(
title: Text("我的推荐"),
),
ListTile(
title: Text("我的热门"),
),
ListTile(
title: Text("我的视频"),
)
])
);
}
}
3.AppBar属性
字段 | 属性 | 描述 |
---|---|---|
key | Key | 当组件在组件树中移动时使用Key可以保持组件之前状态 |
leading | Widget | 通常情况下返回一个返回键(IconButton) |
leadingWidth | double | 左侧leading的宽度,默认56 |
automaticallyImplyLeading | bool | 和leading配合使用,如果为true并且leading为空的情况下,会自动配置返回键 |
title | Widget | 导航栏的标题 |
centerTitle | bool | 标题是否居中,不同操作系统默认显示位置不一样 |
actions | List | 一个Widget列表 |
bottom | PreferredSizeWidget | 出现在导航栏底部的控件 |
elevation | double | 控制导航栏下方阴影的大小 |
shadowColor | Color | 控制导航栏下方阴影的颜色 |
shape | ShapeBorder | 导航栏的形状以及阴影 |
backgroundColor | Color | 导航栏的背景颜色 |
foregroundColor(只有当14属性设置为flase的时候,该属性才会生效) ) | Color | 导航栏中文本和图标的颜色 |
backwardsCompatibility | bool | 与foregroundColor配合使用 |
iconTheme | IconThemeData | 导航栏图标的颜色、透明度、大小的配置 |
actionsIconTheme | IconThemeData | 导航栏右侧图标的颜色、透明度、大小的配置 |
textTheme | TextTheme | 导航栏文本的排版样式 |
primary | bool | 导航栏是否显示在屏幕顶部 |
excludeHeaderSemantics | bool | 标题是否应该用 [Semantics] 包裹,默认false |
titleSpacing | double | title内容的间距 |
toolbarOpacity | double | 导航栏的透明度 |
toolbarHeight | double | 导航栏的高度,默认kToolbarHeight |
toolbarTextStyle | TextStyle | 导航栏图标的颜色 |
titleTextStyle | TextStyle | 导航栏标题的默认颜色 |
flexibleSpace | Widget | 堆叠在工具栏和选项卡栏的后面 |
systemOverlayStyle | SystemUiOverlayStyle | 叠加层的样式 |
brightness | Brightness | 导航栏的亮度,改属性已废弃,用systemOverlayStyle代替 |
bottomOpacity | double | 导航栏底部的透明度 |
3.PreferredSize配置appBar的高度
appBar: PreferredSize(preferredSize: const Size.fromHeight(50), child: TabBar(
controller:_tabController ,
indicatorColor: Colors.red,
labelColor: Colors.black87,
tabs:const [
Tab(child: Text("推荐")),Tab(child: Text("热门")),Tab(child: Text("视频"),)
]),),
4.自定义缓存组件
class KeepAliveWrapper extends StatefulWidget{
final Widget? child;
final bool keepAlive;
const KeepAliveWrapper({Key? key,required this.child,this.keepAlive=true}):super(key: key);
State<KeepAliveWrapper> createState() => _KeepAliveWrapper();
}
class _KeepAliveWrapper extends State<KeepAliveWrapper> with AutomaticKeepAliveClientMixin{
Widget build(BuildContext context) {
return widget.child!;
}
bool get wantKeepAlive => widget.keepAlive;
}
实现页面的缓存
import 'package:flutter/material.dart';
class KeepAliveWrapper extends StatefulWidget{
final Widget? child;
final bool keepAlive;
const KeepAliveWrapper({Key? key,required this.child,this.keepAlive=true}):super(key: key);
State<KeepAliveWrapper> createState() => _KeepAliveWrapper();
}
class _KeepAliveWrapper extends State<KeepAliveWrapper> with AutomaticKeepAliveClientMixin{
Widget build(BuildContext context) {
return widget.child!;
}
bool get wantKeepAlive => widget.keepAlive;
}
void main(){
runApp(
const MaterialApp(
debugShowCheckedModeBanner: false,
title: "richu",
home: HomeState()
));
}
class HomeState extends StatefulWidget{
const HomeState({super.key});
State<HomeState> createState()=> _HomeState();
}
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin{
late TabController _tabController;
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(preferredSize: const Size.fromHeight(50), child: TabBar(
controller:_tabController ,
indicatorColor: Colors.red,
labelColor: Colors.black87,
tabs:const [
Tab(child: Text("推荐")),Tab(child: Text("热门")),Tab(child: Text("视频"),)
]),),
backgroundColor: Colors.white,
body:TabBarView(controller: _tabController ,children:[KeepAliveWrapper(child: ListView(children: const [ListTile(
title: Text("我的推荐"),
)],),),
const ListTile(
title: Text("我的热门"),
),
const ListTile(
title: Text("我的视频"),
)
])
);
}
}
5.tabController实现事件监听
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin{
late TabController _tabController;
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
_tabController.addListener((){
print(_tabController.index); //触发两次
});
}
解决触发两次的问题
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin{
late TabController _tabController;
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
_tabController.addListener((){
if (_tabController.index == _tabController.animation!.value){
print(_tabController.index); //触发一次
}
});
}
7.路由
1.Navigator.of(context).push()
可以通过Navigator.push()跳转到另一个页面
Navigator.pop()返回
class UserPage extends StatefulWidget{
const UserPage({super.key});
State<UserPage> createState() => _UserPage();
}
class _UserPage extends State<UserPage>{
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
ElevatedButton(onPressed: (){
Navigator.of(context).push(
MaterialPageRoute(builder: (BuildContext builde){
return const MyHomePage();
})
);
}, child: const Text("搜索"))
],
)
);
}
}
2.基本路由
可以使用widget.属性获取父类的属性
class SettingPage extends StatefulWidget{
final String title;
const SettingPage({super.key,this.title = ""});
State<SettingPage> createState() => _SettingPage();
}
class _SettingPage extends State<SettingPage>{
Widget build(BuildContext context) {
return Center(
child: Text(widget.title),
);
}
}
此时传递参数,在构造函数传递title即可
ElevatedButton(onPressed: (){
Navigator.of(context).push(
MaterialPageRoute(builder: (BuildContext builde){
return const SettingPage(title: "我是设置");
})
);
}, child: const Text("设置"))],
3.命名路由
ElevatedButton(onPressed: (){
Navigator.pushNamed(context, "/setting");
}, child: const Text("设置"))
],
4.命名路由传值
1.配置Map routes
Map routes = {
"/" : (context) => const MyHomePage(),
"/news" : (context) => const NewsPage(),
"/setting" : (context,arguments) => SettingPage(arguments: arguments),
};
2.配置onGenerateRoute
//固定写法
onGenerateRoute: (RouteSettings settings){
final String? name = settings.name;
final Function? builder = routes[name];
if (builder != null){
if (settings.arguments != null){
final Route route = MaterialPageRoute(
builder: (context) => builder(context,arguments:settings.arguments)
);
return route;
}else{
final Route route = MaterialPageRoute(
builder: (context) => builder(context)
);
return route;
}
}
3.传递参数arguments
ElevatedButton(onPressed: (){
Navigator.pushNamed(context, "/news",arguments: {
"title":"我是新闻",
"aid":20
});
}, child: const Text("新闻"))
4.flutter返回上一级路由
Navigator.of(context).pop();
5.替换路由
return ListView(
children: [Text(widget.arguments["title"]),ElevatedButton(onPressed: (){
Navigator.of(context).pushReplacementNamed("/");
}, child: const Text("注册"))],
);
6.返回根目录
Navigator.of(context).pushAndRemoveUntil(newRoute, predicate);
7.使用IOS风格的路由跳转
import 'package:flutter/cupertino.dart';
onGenerateRoute: (RouteSettings settings){
final String? name = settings.name;
final Function? builder = routes[name];
if (builder != null){
if (settings.arguments != null){
final Route route = CupertinoPageRoute(
builder: (context) => builder(context,arguments:settings.arguments)
);
return route;
}else{
final Route route = CupertinoPageRoute(
builder: (context) => builder(context)
);
return route;
}
}
return null;
},
8.Dialog
1.AlertDialog
class NewsPage extends StatefulWidget{
final Map arguments;
const NewsPage({super.key,required this.arguments});
State<NewsPage> createState() => _NewsPage();
}
class _NewsPage extends State<NewsPage>{
Widget build(BuildContext context) {
void _alertDialog(){
showDialog(context: context, builder: (context){
return AlertDialog(
title: const Text("提示信息"),
content: const Text("确定?"),
actions: [
TextButton(onPressed: (){
Navigator.of(context).pop("ok");
}, child: const Text("确定")),
TextButton(onPressed: (){
Navigator.of(context).pop("none");
}, child: const Text("取消"))
],
);
});
}
return ListView(
children: [Text(widget.arguments["title"]),ElevatedButton(onPressed: (){
Navigator.of(context).pushReplacementNamed("/");
//Navigator.of(context).pushAndRemoveUntil(newRoute, predicate);
}, child: const Text("注册")),ElevatedButton(onPressed: (){
_alertDialog();
}, child: const Text("取消"))],
);
}
}
2.异步获取消息
Widget build(BuildContext context) {
void _alertDialog() async {
var res = await showDialog(context: context, builder: (context){
return AlertDialog(
title: const Text("提示信息"),
content: const Text("确定?"),
actions: [
TextButton(onPressed: (){
Navigator.of(context).pop("ok");
}, child: const Text("确定")),
TextButton(onPressed: (){
Navigator.of(context).pop("none");
}, child: const Text("取消"))
],
);
});
print(res);
}
3.SimpleDialog
void _simpleDialog()async {
var res = await showDialog(context: context, builder: (context){
return SimpleDialog(
title: const Text("提示信息"),
children: [
SimpleDialogOption(
onPressed: (){
Navigator.pop(context,"1");
},
child: const Text("1"),
),
SimpleDialogOption(
onPressed: (){
Navigator.pop(context,"2");
},
child: const Text("2"),
),
SimpleDialogOption(
onPressed: (){
Navigator.pop(context,"3");
},
child: const Text("3"),
),
],
);
});
print(res);
}
4.showModalBottomSheet
void _modelDialog()async {
var res = await showModalBottomSheet(context: context, builder: (context){
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ListTile(
title: const Text("test1"),
onTap: (){
Navigator.pop(context,"test1");
},
),
ListTile(
title: const Text("test2"),
onTap: (){
Navigator.pop(context,"test2");
},
),
ListTile(
title: const Text("test3"),
onTap: (){
Navigator.pop(context,"test3");
},
)
],
);
});
print(res);
}
5.showToast
添加配置
dependencies:
flutter:
sdk: flutter
fluttertoast: ^8.0.9
Fluttertoast.showToast(
msg: "This is Center Short Toast", //信息
toastLength: Toast.LENGTH_SHORT, //安卓平台生效
gravity: ToastGravity.CENTER, //提示的位置
timeInSecForIosWeb: 1, //提示时间web ios
backgroundColor: Colors.red, //背景颜色
textColor: Colors.white, //文本颜色
fontSize: 16.0 //字体大小
);
6.自定义dialog
自定义dialog,并且点击按钮关闭
class Mydialog extends Dialog{
const Mydialog({super.key});
Widget build(BuildContext context){
return Material(
child: Center(
child: Container(
height: 300,
width: 300,
color: Colors.white,
child: Column(
children: [
const SizedBox(height: 20,),
Stack(
children: [
const Align(alignment: Alignment.centerLeft,child: Text("提示"),),
Align(alignment: Alignment.centerRight,child: InkWell(child:const Icon(Icons.star_border_purple500),onTap: (){
//点击按钮关闭
Navigator.pop(context);
},))
],
),
const Divider(),
const SizedBox(height: 10,),
Container(
padding: const EdgeInsets.all(10),
width: double.infinity, child: const Text("提示信息",style: TextStyle(
fontSize: 40
),),
)
],
),
),
)
);
}
}
传递方法和参数
使用dialog
void _mydialog() {
showDialog(context: context, builder:(context){
return Mydialog(title:"提示",content:"我是提示",onTab: (){
//点击按钮关闭
Navigator.pop(context);
print("关闭");
},);
});
}
class Mydialog extends Dialog{
String title;
String content;
final Function()? onTab;
Mydialog({required this.onTab, required this.title,required this.content,super.key});
Widget build(BuildContext context){
return Material(
type: MaterialType.transparency,
child: Center(
child: Container(
height: 300,
width: 300,
color: Colors.white,
child: Column(
children: [
const SizedBox(height: 20,),
Stack(
children: [
Align(alignment: Alignment.centerLeft,child: Text(title),),
Align(alignment: Alignment.centerRight,child: InkWell(onTap: onTab!(), child:const Icon(Icons.star_border_purple500)))
],
),
const Divider(),
const SizedBox(height: 10,),
Container(
padding: const EdgeInsets.all(10),
width: double.infinity, child: Text(content,style: const TextStyle(
fontSize: 40
),),
)
],
),
),
)
);
}
}
9.PageView
1.PageView
import 'package:flutter/material.dart';
class MyPageView extends StatefulWidget{
const MyPageView({super.key});
State<MyPageView> createState() => _MyPageView();
}
class _MyPageView extends State<MyPageView>{
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
children: [
Center(
child: Text("1",style: Theme.of(context).textTheme.headlineLarge),
),
Center(
child: Text("2",style: Theme.of(context).textTheme.headlineLarge),
),
Center(
child: Text("3",style: Theme.of(context).textTheme.headlineLarge),
),
Center(
child: Text("4",style: Theme.of(context).textTheme.headlineLarge),
),
],
),
);
}
}
2.PageView.Builder
return PageView.builder(
itemCount: 10,
itemBuilder: (context,index){
return Center(
child: Text("data${index+1}",style: Theme.of(context).textTheme.headlineLarge)
);
}
);
allowImplicitScrolling 缓存当前页面的前后两页
onpageChanged(index){ //页面改变时触发
}
3.轮播图
创建定时器
//创建定时器
Timer timer = Timer.periodic(const Duration(seconds: 3),(timer){
print("执行");
});
class MyPageView extends StatefulWidget{
const MyPageView({super.key});
State<MyPageView> createState() => _MyPageView();
}
class _MyPageView extends State<MyPageView>{
var _pageController;
late Timer timer;
var _currentIndex;
void initState() {
super.initState();
//pageController
_pageController =PageController(initialPage: 0);
//创建定时器
timer = Timer.periodic(const Duration(seconds: 3),(timer){
_pageController.animateToPage((_currentIndex+1)%10, uration: const Duration(milliseconds: 400), curve: Curves.linear,);
});
}
Widget build(BuildContext context) {
return PageView.builder(
controller: _pageController,
itemCount: 10,
itemBuilder: (context,index){
return Center(
child: Text("data${index+1}",style: Theme.of(context).textTheme.headlineLarge)
);
}
);
}
void dispose() {
super.dispose();
timer.cancel();
_pageController.dispose();
}
}
4.AutomaticKeepAliveClientMixin
class _MyPageView extends State<MyPageView> with AutomaticKeepAliveClientMixin{
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
10.Flutter Key的作用
1.key的使用
void main(){
runApp(const HomeState());
}
class HomeState extends StatefulWidget{
const HomeState({super.key});
State<HomeState> createState()=>_HomeState();
}
class _HomeState extends State<HomeState>{
List<Widget> list = [
const Boxed(color: Colors.red),
const Boxed(color: Colors.yellow),
const Boxed(color: Colors.blue,)
];
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(child: const Icon(Icons.refresh),onPressed: (){
setState(() {
list.shuffle();
});
}),
appBar: AppBar(
title: const Text("标题"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: list
),
),
)
);
}
}
class Boxed extends StatefulWidget{
final Color color;
const Boxed({super.key,required this.color});
State<Boxed> createState() => _Boxed();
}
class _Boxed extends State<Boxed>{
int _cout = 0;
Widget build(BuildContext context) {
return SizedBox(
height: 100,
width: 100,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(widget.color)
),
onPressed: (){
setState(() {
_cout++;
});
},
child: Text("$_cout",style: Theme.of(context).textTheme.headlineLarge,)),
);
}
}
当点击按钮改变顺序时数字没有跟着一起变
LocalKey局部键
Globalkey全局键
List<Widget> list = [
const Boxed(key: ValueKey("1"),color: Colors.red),
const Boxed(key: ValueKey("2"),color: Colors.yellow),
const Boxed(key: ValueKey("3"),color: Colors.blue,)
];
获取屏幕方向
print(MediaQuery.of(context).orientation);
2.父widget获取子widget的状态和方法
给子widget传递globalkey使用globalkey获取子组件
class HomeState extends StatefulWidget{
const HomeState({Key? key}) : super(key:key);
State<HomeState> createState()=>_HomeState();
}
class _HomeState extends State<HomeState>{
final GlobalKey _globalKey = new GlobalKey();
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
var BoxState = _globalKey.currentState as _Boxed;
print(BoxState._cout);
}),
appBar: AppBar(
title: const Text("标题"),
),
body: Boxed(key: _globalKey,color: Colors.red)
)
);
}
}
11.AnimatedList实现动态列表
class _HomeState extends State<HomeState>{
List<String> list = ["第一","第二"];
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
setState(() {
list.add("value");
});
},child: const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: AnimatedList(initialItemCount: list.length,itemBuilder: ((context,index,animation){
return FadeTransition(opacity: animation,
child: ListTile(title: Text(list[index]),),
);
}))
)
);
}
}
增加数据要使用insertItem
class _HomeState extends State<HomeState>{
final _globalKey = GlobalKey<AnimatedListState>();
List<String> list = ["第一","第二"];
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
setState(() {
list.add("value");
_globalKey.currentState!.insertItem(list.length-1);
});
},child: const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: AnimatedList(
key: _globalKey,
initialItemCount: list.length,itemBuilder: ((context,index,animation){
return FadeTransition(opacity: animation,
child: ListTile(title: Text(list[index]),),
);
}))
)
);
}
}
删除数据使用removeItem
_globalKey.currentState!.removeItem(list.length-1,(context,animation){
return FadeTransition(opacity: animation,child: widget,);
});
12.flutter动画组件
1.隐式动画
在动画组件内,直接配置curve和duration属性
AnimatedContainer
使用AnimatedContainer组件,配置curve曲线过渡和duration过渡时间
class HomeState extends StatefulWidget{
const HomeState({Key? key}) : super(key:key);
State<HomeState> createState()=>_HomeState();
}
class _HomeState extends State<HomeState>{
bool press = false; //设置动画触发的条件
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
setState(() {
press = true; //点击FloatingActionButton进行动画效果
});
}
,child: const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: AnimatedContainer(
curve: Curves.ease, //曲线
duration: const Duration(seconds: 1), //延时
width: press ? 200 : 300,
height: 200,
color:Colors.yellow,
transform: press ? Matrix4.translationValues(0, 0, 0) :
Matrix4.translationValues(100, 100, 0)
),
)
)
);
}
}
AnimatedPadding
通过配置padding值的改变,引起组件的移动动画效果,同样支持curve和duration的配置
class _HomeState extends State<HomeState>{
bool press = false;
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
setState(() {
press = true;
});
}
,child: const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: AnimatedPadding(
padding: EdgeInsets.fromLTRB(10, press ? 10 : 400, 0, 0), //配置边距值
curve: Curves.ease, //曲线
duration: const Duration(seconds: 1), //延时
child: Container(
width: 200,
height: 200,
color:Colors.yellow,
),
),
)
)
);
}
}
AnimatedAlign
通过配置alignment值的改变,引起组件的对齐动画效果,同样支持curve和duration的配置
class _HomeState extends State<HomeState>{
bool press = false;
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
setState(() {
press = true;
});
}
,child: const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: AnimatedAlign(
alignment: press ? Alignment.center : Alignment.topCenter,
curve: Curves.ease, //曲线
duration: const Duration(seconds: 1), //延时
child: Container(
width: 200,
height: 200,
color:Colors.yellow,
),
),
)
)
);
}
}
AnimatedOpacity
通过配置opacity值的改变,引起组件的透明度变化动画效果,同样支持curve和duration的配置
class _HomeState extends State<HomeState>{
bool press = false;
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
setState(() {
press = true;
});
}
,child: const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: AnimatedOpacity(
opacity: press ? 1 : 0.1,
curve: Curves.ease, //曲线
duration: const Duration(seconds: 1), //延时
child: Container(
width: 200,
height: 200,
color:Colors.yellow,
),
),
)
)
);
}
}
AnimatedPositioned
通过配置top,left,right,bottom值的改变,引起组件的距离变化动画效果,同样支持curve和duration的配置
class _HomeState extends State<HomeState>{
bool press = false;
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
setState(() {
press = true;
});
}
,child: const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body:Stack(
children: [
AnimatedPositioned(
top: press ? 0 : 100,
left:press ? 0 : 100,
curve: Curves.ease, //曲线
duration: const Duration(seconds: 1), //延时
child: Container(
width: 200,
height: 200,
color:Colors.yellow,
),
),
],
)
)
);
}
}
2.显示动画
使用显示动画,定义AnimationController,在组件上with SingleTickerProviderStateMixin
RotationTransition
RotationTransition实现旋转动画,turns为AnimationController,可以在initState初始化的时候设置vsync,duration来让程序和手机的刷新频率统一,使用..联级操作调用repeat函数让动画重复运动
class _Boxed extends State<Boxed> with SingleTickerProviderStateMixin{
late AnimationController _controller;
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 1)
)..repeat(); //让程序和手机的刷新频率统一
}
Widget build(BuildContext context) {
return SizedBox(
height: 100,
width: 100,
child: RotationTransition(turns: _controller,
child: const FlutterLogo(size: 60),
)
);
}
}
AnimationController
controller的播放方式
repeat 重复
forward 播放一次
reverse 倒序播放
stop 停止
reset 重置
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin {
late AnimationController _controller;
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 1));//让程序和手机的刷新频率统一
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
_controller.repeat(); //重复播放
},child:const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: Column(
children: [RotationTransition(
turns: _controller,
child: const FlutterLogo(size: 60),
),
ElevatedButton(onPressed: (){
_controller.forward(); //播放一次
}, child:const Icon(Icons.refresh)),
ElevatedButton(onPressed: (){
_controller.reverse(); //倒序播放
}, child:const Icon(Icons.refresh)),
ElevatedButton(onPressed: (){
_controller.stop(); //停止
}, child:const Icon(Icons.refresh)),
ElevatedButton(onPressed: (){
_controller.reset(); //重置
}, child:const Icon(Icons.refresh)),
]
)
)
)
);
}
}
FadeTransition
RotationTransition实现透明度变化动画,opacity为AnimationController,可以在initState初始化的时候设置vsync,duration来让程序和手机的刷新频率统一,同时controller为0-1的值,因此opacity会发生从透明到实体的过程,如果要实现实体逐渐到透明可以使用reverse()倒序播放
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin {
late AnimationController _controller;
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 1));//让程序和手机的刷新频率统一
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
_controller.repeat(); //重复播放
},child:const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: FadeTransition(opacity: _controller,
child: const FlutterLogo(size: 60,),
)
)
)
);
}
}
也可以通过lowerBound和upperBound来配置controller的最低和最高值
ScaleTransition
ScaleTransition实现放大缩小动画,scale为AnimationController,可以在initState初始化的时候设置vsync,duration来让程序和手机的刷新频率统一,同时controller为0-1的值,因此scale会发生从小到大的过程,如果要实现大逐渐到小可以使用reverse()倒序播放
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin {
late AnimationController _controller;
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 1));//让程序和手机的刷新频率统一
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
_controller.repeat(); //重复播放
},child:const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: ScaleTransition(scale: _controller,
child: const FlutterLogo(size: 60,),
)
)
)
);
}
}
_controller.drive(Tween(begin:0.5,end: 1.5)), 即为开始时30 结束后为90 (初始为60)
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin {
late AnimationController _controller;
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 1),
lowerBound: 0.5,
upperBound: 1
);//让程序和手机的刷新频率统一
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
_controller.repeat(); //重复播放
},child:const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: ScaleTransition(scale: _controller.drive(Tween(begin:0.5,end: 1.5)),
child: const FlutterLogo(size: 60,),
)
)
)
);
}
}
SlideTransition
SlideTransition实现位移变化动画,position为AnimationController,可以在initState初始化的时候设置vsync,duration来让程序和手机的刷新频率统一,使用drive函数内部配置Tween()子组件Offset()设置初始位置和结束位置
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin {
late AnimationController _controller;
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 1),
lowerBound: 0.5,
upperBound: 1
);//让程序和手机的刷新频率统一
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton:FloatingActionButton(onPressed: (){
_controller.repeat(); //重复播放
},child:const Icon(Icons.add),) ,
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: SlideTransition(position: _controller.drive(Tween(begin: const Offset(0, 0),end: const Offset(1, 1))),
child: const FlutterLogo(size: 60,),
)
)
)
);
}
配置曲线
chain函数内部使用CurveTween组件,同时可以继续使用链式操作继续配置动画
child: SlideTransition(position: Tween(begin: const Offset(0, 0),end: const Offset(0,2)).chain(CurveTween(curve: Curves.linear)).animate(_controller),
3.交错式动画
通过配置controller.drive()方法来配置交错动画
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin {
late AnimationController _controller;
bool flag = false;
void initState() {
super.initState();
_controller = AnimationController(
vsync: this, duration: const Duration(seconds: 1, milliseconds: 1),
// lowerBound: 0.5,
// upperBound: 1
); //让程序和手机的刷新频率统一
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
flag? _controller.forward() : _controller.reverse();
flag = !flag;
},
child: const Icon(Icons.add),
),
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: Stack(
children: [
//实现交错式动画
ScaleTransition(
scale: _controller.drive(Tween(begin: 0.0, end: 1.0)
.chain(CurveTween(curve: const Interval(0.5, 1)))),
child: const Icon(Icons.search)),
ScaleTransition(
scale: _controller.drive(Tween(begin: 1.0, end: 0.0)
.chain(CurveTween(curve: const Interval(0, 0.5)))),
child: const Icon(Icons.close),
)
],
))));
}
}
交错动画实现方块位移
class _HomeState extends State<HomeState> with SingleTickerProviderStateMixin {
late AnimationController _controller;
bool flag = false;
void initState() {
super.initState();
_controller = AnimationController(
vsync: this, duration: const Duration(seconds: 1, milliseconds: 1),
// lowerBound: 0.5,
// upperBound: 1
); //让程序和手机的刷新频率统一
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
flag? _controller.forward() : _controller.reverse();
flag = !flag;
},
child: const Icon(Icons.add),
),
appBar: AppBar(
title: const Text("测试"),
),
body: Center(
child: Column(
children: [
//实现交错式动画
SlideTransition(position: _controller.drive(Tween(begin: const Offset(0.0, 0.0),end: const Offset(1.5, 0)).chain(CurveTween(curve: Curves.ease)).chain(CurveTween(curve: const Interval(0, 0.2)))),
child: Container(
width: 100,
height: 100,
color: Colors.blue[100],
),
),
SlideTransition(position: _controller.drive(Tween(begin: const Offset(0.0, 0.0),end: const Offset(1.5, 0)).chain(CurveTween(curve: Curves.ease)).chain(CurveTween(curve: const Interval(0.2, 0.4)))),
child: Container(
width: 100,
height: 100,
color: Colors.blue[300],
),
),
SlideTransition(position: _controller.drive(Tween(begin: const Offset(0.0, 0.0),end: const Offset(1.5, 0)).chain(CurveTween(curve: Curves.ease)).chain(CurveTween(curve: const Interval(0.4, 0.6)))),
child: Container(
width: 100,
height: 100,
color: Colors.blue[600],
),
),
SlideTransition(position: _controller.drive(Tween(begin: const Offset(0.0, 0.0),end: const Offset(1.5, 0)).chain(CurveTween(curve: Curves.ease)).chain(CurveTween(curve: const Interval(0.6, 0.8)))),
child: Container(
width: 100,
height: 100,
color: Colors.blue[900],
),
),
],
),
)
));
}
4.Hero动画
在路由组件内配置
class _HomeState extends State<HomeState>{
Map routes = {
"/" : (context) => const MyHomePage(),
"/news" : (context, {arguments}) => NewsPage(arguments: arguments),
"/setting" : (context, {arguments}) => SettingPage(arguments: arguments),
"/page" :(context) => const MyPageView()
};
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
onGenerateRoute: (RouteSettings settings){
final String? name = settings.name;
final Function? builder = routes[name];
if (builder != null){
if (settings.arguments != null){
final Route route = CupertinoPageRoute(
builder: (context) => builder(context,arguments:settings.arguments)
);
return route;
}else{
final Route route = CupertinoPageRoute(
builder: (context) => builder(context)
);
return route;
}
}
return null;
},
title: "richu",
initialRoute: "/",
home: RouteState(),
);
}
}
class RouteState extends StatelessWidget{
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ListView(
children: [
ElevatedButton(onPressed: (){
Navigator.pushNamed(context, "/news",arguments: {
"title":"组件news",
"aid":20
});
}, child: const Hero(tag: "组件news", child:Text("text"))), //通过tag传递参数,类似android的子组件共享参数
],
)
),
);
}
}
在子路由组件中使用hero组件接收参数
class _NewsPage extends State<NewsPage>{
return ListView(
children: [Hero(tag:widget.arguments["title"], child:Text(widget.arguments["title"])),ElevatedButton(onPressed: (){
Navigator.of(context).pushReplacementNamed("/");
//Navigator.of(context).pushAndRemoveUntil(newRoute, predicate);
}, child: const Text("注册")),const SizedBox(height: 20,),ElevatedButton(onPressed: (){
_alertDialog();
}, child: const Text("取消")),const SizedBox(height: 20,),ElevatedButton(onPressed: (){
_simpleDialog();
}, child: const Text("提示信息")),const SizedBox(height: 20,),ElevatedButton(onPressed: (){
_modelDialog();
}, child: const Text("显示")),const SizedBox(height: 20,),ElevatedButton(onPressed: (){
_mydialog();
}, child: const Text("提示"))],
);
}
}
13.Getx
1.基本使用
1.状态管理
GetX 高性能的状态管理,智能的依赖注入和便捷的路由管理
get: ^4.6.1
flutter pub get
Get.defaultDialog(
title: "提示信息",
middleText: "确定删除?",
confirm: ElevatedButton(onPressed: (){
print("ok");
}, child: const Text("确定")),
cancel: ElevatedButton(onPressed: (){
print("test");
}, child: const Text("确定"))
);
返回上一级
Get.back();
2.组件的使用
初始化
class HomeState extends StatelessWidget{
const HomeState({super.key});
Widget build(BuildContext context) {
return GetMaterialApp(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.light,
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text("data"),
),
body: const PageGet(),
),
);
}
}
defaultDialog
return Center(
child: ElevatedButton(
onPressed: () {
Get.defaultDialog(
title: "提示信息",
middleText: "确定删除?",
confirm: ElevatedButton(onPressed: (){
Get.back();
}, child: const Text("确定")),
cancel: ElevatedButton(onPressed: (){
Get.back();
}, child: const Text("取消"))
);
},
child: const Text("Show Dialog"),
),
);
}
Widget build(BuildContext context) {
snackbar 默认在顶部
Get.snackbar("警告", "未知错误");
//配置位置
Get.snackbar("警告", "未知错误",snackPosition: SnackPosition.BOTTOM);
bottomSheet
Get.bottomSheet(Container(
color: Colors.white,
height: 200,
child: Column(
children: [
ElevatedButton(onPressed: (){}, child: const ListTile(
leading: Icon(Icons.sunny),
title: Text("白天模式",style: TextStyle(color: Colors.black),),
),),
ElevatedButton(onPressed: (){}, child:const ListTile(
leading: Icon(Icons.nightlight),
title: Text("黑夜模式" ,style: TextStyle(color: Colors.black),),
))
],
),
));
3.通过getx切换主题
Get.bottomSheet(Container(
color: Colors.white,
height: 200,
child: Column(
children: [
ListTile(
leading: Icon(Icons.sunny),
onTap: (){
Get.changeTheme(ThemeData.light());
Get.back();
},
title: const Text("白天模式",style: TextStyle(color: Colors.black),),
),
ListTile(
leading: Icon(Icons.nightlight),
onTap: (){
Get.changeTheme(ThemeData.dark());
Get.back();
},
title:const Text("黑夜模式" ,style: TextStyle(color: Colors.black),),
)
],
),
));
app
class HomeState extends StatelessWidget{
const HomeState({super.key});
Widget build(BuildContext context) {
return GetMaterialApp(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.light,
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text("data"),
),
body: const PageGet(),
),
);
}
}
4.GetX进行路由切换
配置默认的路由切换动画
initialRoute: "/",
defaultTransition: Transition.rightToLeft,
Get.toNamed(“/login”) 去到指定路由
Get.offAll(const Tabs(index:4)) 去到根路径
Get.off(NextScreen()); 进入下一个页面但是没有返回按钮
Get.back() 返回
5.Getx配置路由
配置路由,参数可在组件内获取
rightToLeft来配置动画效果
class HomeState extends StatelessWidget {
const HomeState({super.key});
Widget build(BuildContext context) {
return GetMaterialApp(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.light,
debugShowCheckedModeBanner: false,
initialRoute: "/",
getPages: [
GetPage(name: "/home", page: () => const MyHomePage()),
GetPage(
name: "/user",
page: () => const UserPage(),
transition: Transition.rightToLeft)
],
home: Scaffold(
appBar: AppBar(
title: const Text("data"),
),
body: const PageGet(),
),
);
}
}
传递参数
Get.toNamed("/news",arguments: {"title":"richu"});
接收参数
Get.arguments["title"], child: Text(Get.arguments["title"]
6.中间件
定义中间件
class ShopMiddleware extends GetMiddleware{
RouteSettings? redirect(String? route){
//return null 默认不做操作
return null;
//路由跳转,并且传递参数,如果没有参数可以传递空map
return const RouteSettings(name: "/",arguments: {});
}
}
配置中间件
GetPage(
name: "/user",
page: () => const UserPage(),
transition: Transition.rightToLeft,
middlewares: [
ShopMiddleware()
]
),
配置多个中间件,并且配置优先级
ShopMiddleware(priority: 2)
class ShopMiddleware extends GetMiddleware{
ShopMiddleware({super.priority});
RouteSettings? redirect(String? route){
//return null;
return const RouteSettings(name: "/",arguments: {});
}
}
2.状态管理
定义一个响应式变量
RxInt _counter = 0.obs;
RxString _name = "".obs;
监听
children: [Obx(()=>Text("$_counter.value"))],
Obx(()=>Text(_name.value))
定义响应式变量的方法
Rx<String> _test1 = Rx<String>("test");
RxString _test2 = RxString("test");
3.响应式状态管理
多个页面共享数据
//定义controller
import 'package:get/get.dart';
class CounterController extends GetxController{
RxInt counter = 0.obs;
inc(){
counter++;
update();
}
dec(){
counter--;
update();
}
}
class _PageGet extends State<PageGet> {
CounterController counterController = Get.put(CounterController());
Widget build(BuildContext context) {
return Column(
children: [
Obx(() => Text("${counterController.counter}")),
ElevatedButton(
onPressed: () {
counterController.inc();
},
child: const Text("++")),
ElevatedButton(
onPressed: () {
Get.toNamed("/news", arguments: {"title": "richu"});
},
child: const Text("to news"))
],
);
}
}
获取
CounterController counterController = Get.find();
ElevatedButton(onPressed: (){
counterController.inc();
}, child:const Text("++")),
Obx(()=>Text("${counterController.counter}"))
2.Binding
import 'package:get/get.dart';
import 'package:richu/controllers/counter.dart';
class AllControllerBinding extends Bindings{
void dependencies() {
Get.lazyPut<CounterController>(()=>CounterController());
}
}
return GetMaterialApp(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.light,
debugShowCheckedModeBanner: false,
initialRoute: "/",
defaultTransition: Transition.rightToLeft,
initialBinding: AllControllerBinding(),
getPages: [
GetPage(
name: "/home",
page: () => const MyHomePage(),
transition: Transition.rightToLeft),
GetPage(
name: "/user",
page: () => const UserPage(),
transition: Transition.rightToLeft,
middlewares: [ShopMiddleware(priority: 2)]),
GetPage(
name: "/news",
page: () => const NewsPage(),
transition: Transition.rightToLeft)
],
home: Scaffold(
appBar: AppBar(
title: const Text("data"),
),
body: const PageGet(),
),
);
配置之后无序put
4.使用GetView
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:get/get.dart';
import 'package:richu/controllers/counter.dart';
class CounterPage extends GetView<CounterController>{
const CounterPage({super.key});
Widget build(BuildContext context) {
Get.put(CounterController());
return Scaffold(
appBar: AppBar(
title: const Text("title"),
),
body: Center(
child: Column(
children: [
Obx(()=>Text("${controller.counter}")),
const SizedBox(height: 20,),
ElevatedButton(onPressed: (){
controller.inc();
}, child: const Text("++"))
],
),
),
);
}
}
在路由注入controller
GetPage(name: "/counter", page: () => const CounterPage(),binding:Counterbinding())
初始化后可以直接使用,无需put
5.controller的生命周期
void onInit() {
print("init");
}
void onReady() {
print("ready");
}
void onClose() {
print("close");
}
6.Flutter实现多语言配置
ElevatedButton(onPressed: () {}, child: const Text("切换到中文")),
const SizedBox(
height: 20,
),
ElevatedButton(onPressed: () {}, child: const Text("切换到英文"))
定义语言
import 'package:get/get.dart';
class Message extends Translations {
Map<String, Map<String, String>> get keys =>{
'zh_CN':{
'hello':"你好"
},
'en-US':{
'hello':"hello richu"
}
};
}
return GetMaterialApp(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.light,
debugShowCheckedModeBanner: false,
initialRoute: "/",
translations: Message(),
locale: const Locale('zh','CN'), //指定默认的语言
fallbackLocale: const Locale('en','US'), //添加一个回调语言选项
defaultTransition: Transition.rightToLeft,
}
切换语言
ElevatedButton(onPressed: () {
var locale = const Locale("zh",'CN');
Get.updateLocale(locale);
}, child: const Text("切换到中文")),
const SizedBox(
height: 20,
),
ElevatedButton(onPressed: () {
var locale = const Locale("en",'US');
Get.updateLocale(locale);
}, child: const Text("切换到英文")),
7.GetUtils工具库
GetUtils
是getx
为我们提供一些常用的工具类库,包括值是否为空、是否是数字、是否是视频、图片、音频、PPT、Word、APK、邮箱、手机号码、日期、MD5、SHA1等等。
验证邮箱
class _PageGet extends State<PageGet> {
TextEditingController textEditingController = TextEditingController();
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: textEditingController,
),
ElevatedButton(onPressed: (){
if (GetUtils.isEmail(textEditingController.text)){
Get.snackbar("正确", "验证成功");
}else{
Get.snackbar("错误", "错误的邮箱",colorText: Colors.red[100]);
}
}, child: const Text("验证邮箱"))
],
);
}
}
验证手机号
TextField(
controller: textEditingController,
),
ElevatedButton(onPressed: (){
if (GetUtils.isPhoneNumber(textEditingController.text) && textEditingController.text.length == 11){
Get.snackbar("正确", "验证成功");
}else{
Get.snackbar("错误", "错误的手机号",colorText: Colors.red[100]);
}
}, child: const Text("验证手机号")),