【学习笔记】Flutter重要知识点

news/2024/10/17 20:32:07/

学习资料

4月28日-5月11日
按照这个视频边学习边敲代码
视频学习
争取两个星期把flutter和dart搞定!!!!

5月12日半夜更新学习日志
基本内容学的超不多了,感觉声明式编程真的好爱~~Android原生好久没搞了。接下来练几个Flutter项目!边学边找工作,相信自己,虽然二战考研失败了,但日子总是要过得…
加油!希望能在六月份之前在杭州找到工作!!

案例代码

点击跳转dart语法学习代码
点击跳转github案例代码
有新的代码我会push上去的。案例代码自个人跟着敲得,基本一些用法及笔记都标在注释里边了,这个学习视频其实版本是2020年的,有些组件废弃了,所以我也稍微修改了一下

一些说明

UI开发工具包Flutter,多用于移动端,跨平台,开发速度快(框架)

1.Dart语法学习

dart语言有很多其他语言的特征,js,python,java…

1.1 第一行代码

main(List<String> args) {print("Hello World");
}

VSCode运行
在这里插入图片描述

1.2 变量声明

// 1.变量声明String name = "WYJ";// 2.类型推导(var、final、const)// 变量是有类型的var age = 20;age = 30;// 3.final、const都是定义常量final height = 1.99;// height = 2.00;const address  ="浙江省";// address = "杭州市";//final与const之间的区别-final可以通过计算赋值,const必须赋值// const date1 = DateTime.now();写法错误final date1 = DateTime.now();

1.3 创建同一个实例和创建不同实例(final&const)

    //p1和p2不是同一个对象final p1 = Person("why");final p2 = Person("why");print(identical(p1, p2));//p1和p2是同一个对象const p3 = const Person("why");const p4 = const Person("why");const p5 = const Person("wangMing");print(identical(p3, p4));print(identical(p5, p4));
class Person {final String name;const Person(this.name);
}

运行截图
在这里插入图片描述

1.4 bool类型

void main(List<String> args) {// var flag = "abc"; 没有非空即真var flag = true;if(flag){print("执行代码");}
}

dart中没有非空即真,bool类型需要设为true或false

1.5 字符串定义及使用

void main(List<String> args) {var str1 = 'abc';var str2 = "abc";var str3 = """abcdef""";var name = "why";var age = 19;var height = 1.99;var message1 = "my name is ${name}, age is ${age}, height is ${height}";var message2 = "name is ${name}, type is ${name.runtimeType}";print(message1);print(message2);
}

在这里插入图片描述
说明:类似于es6里的变量代换,利用${}来操作。

1.6 集合类型

void main(List<String> args) {// 1.列表Listvar names = ["abc", "cba", "nba"];names.add("value");// 2.集合Setvar movies = {"aaa", "bbb", "ccc"};names = Set<String>.from(names).toList();print(names);// 3.映射Mapvar info = {"name":"key","age":18};
}

1.7 函数简单使用

void main(List<String> args) {print(sum(1, 2));
}int sum(int num1, int num2){return num1 + num2;
}

1.8 函数进阶(命名可选参数、位置可选参数)

void main(List<String> args) {sayHello1("why");sayHello2("why",18,178.1);sayHello3("why",age: 18, height: 178.1);
}
void sayHello1(String name){print(name);
}
//dart中没有函数的重载
//可选参数:位置可选参数-命名可选参数
//***位置可选参数***
//实参和形参进行匹配时,是根据位置进行匹配的
void sayHello2(String name, [int age = 0, double height = 0]) {print("my name is" + name + "; age is ${age}; height is ${height};");
}
//***命名可选参数***
void sayHello3(String name, {int age = 0, double height = 0}) {print("my name is" + name + "; age is ${age}; height is ${height};");
}

1.9 函数是第一公民

void main(List<String> args) {test(bar);test(() {print("匿名函数被调用");return 10;});//箭头函数:条件是只能有一行代码test(() => print("箭头函数被调用"));
}
//函数可以作为另一个函数的参数
void test(Function foo){foo();
}
void bar(){print("bar函数被调用");
}

这里用了箭头函数和匿名函数,箭头函数就用于只有一行代码的函数。

1.10 带参数的函数传入

如何在函数里面带参数呢,先简单写一段程序

void main(List<String> args) {test((num1, num2) {return num1 * num2;});
}
void test(int foo(int num1, int num2)) {foo(20,30);
}

确实可以实现传参,但是阅读起来不容易理解,所以改进一下。

typedef Calculate = int Function(int num1, int num2);
void test(Calculate calculate) {calculate(20, 30);
}

Function这阅读起来很不清楚,可以传参,也可以不传参,所以阅读性差;使用typedef定义一个函数,这样阅读起来简单明了

1.11 函数作为返回值

void main(List<String> args) {var demo1 = demo();print(demo1(20, 30));
}
typedef Calculate = int Function(int num1, int num2);
Calculate demo() {return ((num1, num2) {return num1 * num2;});
}

1.12 一般的运算符

问号使用

void main(List<String> args) {// ??= 有值则不赋值,没有值则赋值var name1 = "why";name1 ??= "lilei";print(name1);var name2 = null;name2 ??= "lilei";print(name2);//前面的数据为null,那么就使用后面的数据var name = null;var temp = name ?? "lilei";print(temp);
}

在这里插入图片描述

1.13 级联运算符

main(List<String> args) {var p = person()..name = "why"..eat()..run();print(p.name);
}
class person {String name = "";void run() {print("running...");}void eat() {print("eating...");}
}

在这里插入图片描述

1.14 for循环

void main(List<String> args) {// 1.基础for循环for(var i = 0; i < 10; i++) {print(i);}// 2.遍历数组var names = ["why", "cha", "cba"];for(var i = 0; i < names.length; i++) {print(names[i]);}for(var name in names) {print(name);}
}

在这里插入图片描述

1.15 类的定义

//dart支持函数式编程,但是大部分是面向对象,即类
void main(List<String> args) {var p = Person("why", 18);
}
class Person {String name;int age;原本写法// Person(String name, int age) {//   this.name = name;//   this.age = age;// }//简便写法Person(this.name, this.age);
}

1.16 构造函数

dynamic

  // Object调用方法时,编译时会出错// dynamic编译不会报错,但是运行时会报错// Object obj = "why";// print(obj.substring(1));dynamic obj = "why";// dynamic obj = 123;print(obj.substring(1));

命名构造函数

void main(List<String> args) {// Object调用方法时,编译时会出错// dynamic编译不会报错,但是运行时会报错// Object obj = "why";// print(obj.substring(1));dynamic obj = "why";// dynamic obj = 123;print(obj.substring(1));var p = Person.withNameAgeHeight("why", 18, 178.1);var p1 = Person.fromMap({"name": "lilei","age": 18,"height": 178.1 });print(p1);
}
class Person {String name = "";int age = 0;double height = 0.0;Person(this.name,this.age);//命名构造函数//这里的withNameAgeHeight和fromMap都是自定义的Person.withNameAgeHeight(this.name, this.age, this.height);Person.fromMap(Map<String, dynamic> map) {this.name = map["name"];this.age = map["age"];this.height = map["height"];}@overrideString toString() {return "$name $age $height";}
}

在这里插入图片描述

1.17 类的初始化列表

void main(List<String> args) {var p1 = Person("why");print(p1.age);var p2 = Person("why", age: 18);print(p2.age);
}
class Person {final String name;final int age;// 初始化age,初始化列表// Person(this.name): age = 10;// Person(this.name, {this.age = 10});Person(this.name, {age}): this.age = age ?? 10;
}

在这里插入图片描述
p1未传入参数,那么赋值为10,当age为null时,赋值为10,;否则如p2,则赋值为传入的值18.

1.18 重定向构造函数

void main(List<String> args) {Person p = Person("WYJ");print("My name is ${p.name}, age is ${p.age}");
}// 这里赋初始值是通过调用_internal函数的方式
// age 数值并未传入,但是初始化为0
class Person {String name;int age;Person(String name) :this._internal(name, 0);Person._internal(this.name,this.age);
}

在这里插入图片描述

1.19 常量构造函数

void main(List<String> args) {//这里传入相同的名称时,指向的是同一个实例const p1 = Person("why");const p2 = Person("why");print(identical(p1, p2));// const p1 = Person("why1");// const p2 = Person("why2");// print(identical(p1, p2));
}class Person {final String name;final int age;//常量构造函数const Person(this.name): this.age = 0;//dart不支持函数的重改// const Person(this.name, this.age);
}

1.20 工厂构造函数

void main(List<String> args) {final p1 = Person.withName("why");final p2 = Person.withName("why");print(identical(p1, p2));// final p1 = Person.withColor("yellow");// final p2 = Person.withColor("yellow");// print(identical(p1, p2));// final p1 = Person.withColor("yellow1");// final p2 = Person.withColor("yellow2");// print(identical(p1, p2));
}//工厂构造函数最大的特点是可以手动的返回一个对象
//普通构造函数会自动返回创建出来的对象,不能手动的返回
class Person {String name;String color;/* 缓存,当传入的姓名是一样的时候,就返回缓存中的已有实例,否则创建新的实例*/static final Map<String, dynamic> _nameCache = <String, Person>{};static final Map<String, dynamic> _colorCache = <String, Person>{};//返回类型为factory,意味着必须返回一个实例。//自定义withName函数factory Person.withName(String name) {//判断map中有没有该名字if(_nameCache.containsKey(name)) {//有名字则返回已有的实例return _nameCache[name];} else {//否则创建新实例,同时color设置为"default"final p = Person(name, "default");_nameCache[name] = p;return p;}}//  类似有下面函数factory Person.withColor(String color) {if(_colorCache.containsKey(color)) {return _colorCache[color];} else {final p = Person("default", color);_colorCache[color] = p;return p;}}Person(this.name, this.color);
}

在这里插入图片描述

1.21 getter和setter

void main(List<String> args) {final p = Person();//直接访问属性p.name = "why";print(p.name);//通过getter和setter访问p.setName = "lilei";print(p.getName);
}class Person {String name = "";//setterset setName(String name) {this.name = name;}//getterString get getName {return name;}
}

在这里插入图片描述

1.22 类的继承

void main(List<String> args) {final p = Person("name", 10);print(p.name);print(p.age);
}class Animal {int age;Animal(this.age);
}
class Person extends Animal {String name;//super(age)相当于调用Animal(this.age);Person(this.name, int age): super(age);
}

在这里插入图片描述

1.23 抽象类的使用

void main(List<String> args) {final map = Map();print(map.runtimeType);// final s = Shape();
}//抽象类不能调用原本的方法来实例化
abstract class Shape {int getArea();String getInfo() {return "形状";}//通过工厂实例化// factory Shape() {//   return Rectangle();// }
}//继承自抽象类后,抽象类必须实现抽象类的抽象方法
// class Rectangle extends Shape {
//   @override
//   int getArea() {
//     return 100;
//   }
// }

1.24 隐式接口

void main(List<String> args) {}//Dart中没有关键字定义接口,默认所有的
//当将一个类当作接口使用时,那么实现这个接口的类,必须实现这个接口中的所有方法
class Runner {void running() {print("running");}
}
class Flyer {void flying() {}
}
class Animal {void eating() {print("动物吃东西");}
}
class Superman extends Animal implements Flyer, Runner {@overridevoid running() {// TODO: implement running}@overridevoid flying() {// TODO: implement flying}@overridevoid eating() {// TODO: implement eatingsuper.eating();}
}

1.25 mixin混入的使用

void main(List<String> args) {final sm = SuperMan();sm.running();sm.flying();
}
class Animal {void eating() {print("动物吃东西");}void running() {print("animal running");}
}
mixin Flyer {void flying() {print("flying");}
}
mixin runner {void running() {print("runner running");}
}//调用顺序,先看自己有没有定义的方法,再去调用混入,没有再看继承的
class SuperMan extends Animal with runner, Flyer{@overridevoid eating() {// TODO: implement eatingsuper.eating();}// //加入混入就不需要写running// @override// void running() {//   // TODO: implement running//   super.running();// }//重写running,会最先调用这里的running// void running() {//   print("superMan running");// }
}

在这里插入图片描述

1.26 静态方法(类方法)和静态属性(类属性)

void main(List<String> args) {Person.courseTime = "8:00";Person.gotoCourse();
}
class Person {//成员属性String name = "";//静态属性(类属性)static String courseTime = "";//对象方法void eating() {print("eating");}//静态方法(类方法)static void gotoCourse() {print("去上课");}
}

在这里插入图片描述

1.27 枚举

// 枚举 enum ,枚举作用是安全,保证传入的数据安全,不会有其他规定以外的数据传入
void main(List<String> args) {final color = Colors.red;switch(color) {case Colors.red:print("red");break;case Colors.blue:print("blue");break;}print(Colors.values);print(Colors.red.index);
}
enum Colors {red,blue
}

在这里插入图片描述

1.28 库的使用

import 'dart:io';
import 'dart:async';
import 'dart:io';
import 'dart:math';
//系统库格式: import 'dart:库的名称'
import 'util.dart' as mUtils;
// import 'util.dart' show sum, mul;
// import 'util.dart' hide sum, mul;
void main(List<String> args) {//mathfinal num1 = 20;final num2 = 30;print(min(num1, num2));print(mUtils.sum(num1, num2));print(mUtils.mul(num1, num2));//下划线是区分方法是私有还是公有的// print(mUtils._privateSum)}
int sum(int num1, int num2) {return num1 + num2;
}

在这里插入图片描述
util.dart

export 'dateUtil.dart';
export 'mathUtils.dart';int sum(int num1, int num2) {return num1 + num2;
} 
int mul(int num1, int num2) {return num1 * num2;
}
int _privateSum(int num1, int num2) {return num1 * num2;
}

1.29 第三方库

// https://pub.dev/packages/http/install
import 'package:http/http.dart' as http;void main(List<String> args) async{var url = Uri.parse('https://example.com/whatsit/create');var response = await http.post(url, body: {'name': 'doodle', 'color': 'blue'});print('Response status: ${response.statusCode}');print('Response body: ${response.body}');print(await http.read(Uri.parse('https://example.com/foobar.txt')));
}

pubspec.yaml

name: WYJ
description: a dart library
environment:sdk: '>=2.10.0 <3.0.0'
dependencies: http: ^0.13.4

至此dart语法结束(5月6日补充新知识)

1.30 future简单使用

import 'dart:io';void main(List<String> args) {print("main start");//发送一个网络请求var future = getNetworkData();print(future);//需要在Future函数有结果,才执行下面的回调函数future.then((String value) {print(value);}).catchError((onError){print(onError);}).whenComplete(() => print("代码执行完成"));print("main end");
}
//模拟一个网络请求
Future<String> getNetworkData() {//将耗时的操作包裹在future的回调函数中//只要有回调函数,那么就执行Future对应的then的回调//如果没有结果返回,就抛出一个异常return Future<String>(() {sleep(Duration(seconds: 3));return "Hello World";throw Exception("错误信息");});
}

在这里插入图片描述

1.31 future链式调用

import 'dart:io';void main(List<String> args) {print("Main Start");Future(() {sleep(Duration(seconds: 3));return "第一次结果";}).then((value) {print(value);//第二次请求sleep(Duration(seconds: 2));return "第二次结果";}).then((value) {print(value);//第三次请求sleep(Duration(seconds: 1));return "第三次结果";}).then((value) => print(value));print("Main end");
}

在这里插入图片描述

1.32 future其他API

void main(List<String> args) {Future(() {return "Hello World";},).then((value) => print(value));Future.value("hahaha").then((value) => print(value));Future.error("error").catchError((Error){print(Error);});Future<String>.delayed(Duration(seconds: 3)).then((value) {return "Hello";}).then((value) => print(value));
}

在这里插入图片描述

1.33 await async

import 'dart:io';
void main(List<String> args) {print("main start");getData();print("main end");
}
void getData() async{//调用三次网络请求// getNetworkData("arguement").then((value) {//   print(value);//   return getNetworkData(value);// }).then((value) {//   print(value);//   return getNetworkData(value);// }).then((value) {//   print(value);// });var res1 = await getNetworkData("arguement");print(res1);var res2 = await getNetworkData(res1);print(res2);var res3 = await getNetworkData(res2);print(res3);
}
Future getNetworkData(String arg) {return Future((() {sleep(Duration(seconds: 3));return "Hello World" + arg;}));
}

1.34 isolate

import 'dart:isolate';void main(List<String> args) async{print("main start");// 1.创建IsolateIsolate.spawn((int message) { var total = 0;for(var i=0;i<message;i++){total+=i;}print(total);}, 100);//iolate双向通信// 1.创建管道ReceivePort receivePort = ReceivePort();// 2.创建IsolateIsolate isolate = await Isolate.spawn<SendPort>(foo, receivePort.sendPort);// 3.监听管道receivePort.listen((message) {print(message);receivePort.close();isolate.kill();},);print("main end");
}void foo(SendPort sendPort) {return sendPort.send("Hello World");
}

2. Flutter学习

2.1 创建一个新的Flutter项目(命令行创建)

Flutter create learn_flutter

打开main.dart,删除里面的内容,重写代码
每一个小组件是一个Widget,许多的Widget又构成一个个Widget。一个完整的App是一颗Widget树。
StatelessWidget是无状态Widget。
每一个Widget里面有一个必须实现的方法build

import 'package:flutter/material.dart';//只有一句代码就可以使用箭头函数
main() => runApp(MyApp());//Widget分为有状态和无状态
//有状态是运行过程中有一些状态需要改变
//无状态则是内容无需改变
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {// TODO: implement buildreturn MaterialApp(debugShowCheckedModeBanner: false, home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {// TODO: implement buildreturn Scaffold(appBar: AppBar(title: Text("标题"),),body: HYContentBody());}
}class HYContentBody extends StatelessWidget {@overrideWidget build(BuildContext context) {// TODO: implement buildreturn Center(child: Text("Hello World",style: TextStyle(fontSize: 30, color: Colors.orange),));}
}

在这里插入图片描述
这种写法使得多层嵌套的代码变得可读性强

2.2 案例一(chechbox)

需要构造一个这样的功能的界面
在这里插入图片描述

import 'package:flutter/material.dart';//只有一句代码就可以使用箭头函数
main() => runApp(MyApp());//Widget分为有状态和无状态
//有状态是运行过程中有一些状态需要改变
//无状态则是内容无需改变
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {// TODO: implement buildreturn MaterialApp(debugShowCheckedModeBanner: false, home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {// TODO: implement buildreturn Scaffold(appBar: AppBar(title: Text("标题"),),body: HYContentBody());}
}
//row是可以包含多个组件
class HYContentBody extends StatelessWidget {@overrideWidget build(BuildContext context) {// TODO: implement buildreturn Center(child: Row(//mainAxisAlignment居中mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Checkbox(value: true,onChanged: (value) => print(value),),Text("同意协议", style: TextStyle(fontSize: 20),)],),);}
}

但是点击checkbox的按钮,没什么反应,这是应为使用了statelessWiidget,更改代码

import 'package:flutter/material.dart';//只有一句代码就可以使用箭头函数
main() => runApp(MyApp());//Widget分为有状态和无状态
//有状态是运行过程中有一些状态需要改变
//无状态则是内容无需改变
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {// TODO: implement buildreturn MaterialApp(debugShowCheckedModeBanner: false, home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {// TODO: implement buildreturn Scaffold(appBar: AppBar(title: Text("标题"),),body: HYContentBody());}
}
class HYContentBody extends StatefulWidget {@overrideState<StatefulWidget> createState() {return HYContentBodyState();}
}
//stateful不能定义状态 -》 创建一个单独的类,这个类负责维护状态
class HYContentBodyState extends State<HYContentBody> {var flag = true;@overrideWidget build(BuildContext context) {return Center(child: Row(//mainAxisAlignment居中mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Checkbox(value: flag,onChanged: (value) {//这里的setSate是通知界面更新setState(() {flag = value!;});},),Text("同意协议", style: TextStyle(fontSize: 20),)],),);}
}

在这里插入图片描述
这样点击就可以改变选中和不选中了

2.3 案例二(Column和flutter项目安全区域)

在这里插入图片描述
构造上面界面,对应代码如下

import 'package:flutter/material.dart';
import 'package:flutter_learn/02_checkbox.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(home: HYHomePage(),);}
}
class HYHomePage extends StatelessWidget {const HYHomePage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("商品列表"),),body: HYHomeContent(),);}
}
class HYHomeContent extends StatelessWidget {const HYHomeContent({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {//Column能使里面的Widget按列的形式排列return Column(children: [HYHomeProjectItem("Apple", "MacBook", "https://wx2.sinaimg.cn/mw1024/005yGqLdly1h1uknlr8ojj30wi0f0t9k.jpg"),HYHomeProjectItem("banana", "WindowsBook", "https://wx3.sinaimg.cn/mw1024/005yGqLdly1h1uknm0xr4j30wi0f0wey.jpg"),HYHomeProjectItem("orange", "LinuxBook", "https://wx2.sinaimg.cn/mw1024/6c5b0aa9gy1h1uyicv0zzj20ah0cs74n.jpg"),],);}
}
class HYHomeProjectItem extends StatelessWidget {final String title;final String desc;final String imageURL;HYHomeProjectItem(this.title, this.desc, this.imageURL);@overrideWidget build(BuildContext context) {return Column(children: [Text(title),Text(desc),Image.network(imageURL)],);}
}

Column的作用是将里面的Widget按列的方式垂直排列,那么我们看到这种效果,在每一个HYHomeProjectItem
在这里插入图片描述
也需要Column对内部的Text,Text,Imag进行排列。

我们注意到下面有黄条
在这里插入图片描述
这个表示显示的内容超过了屏幕显示区域。

2.4 案例三(计数器)

import 'package:flutter/material.dart';
import 'package:flutter_learn/02_checkbox.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return MaterialApp(home: HYHomePage(),);}
}
class HYHomePage extends StatelessWidget {const HYHomePage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("商品列表"),),body: HYHomeContent(),);}
}//Widget是暴露给别人使用的,state是私有的
class HYHomeContent extends StatefulWidget {const HYHomeContent({Key? key}) : super(key: key);@overrideState<HYHomeContent> createState() => _HYHomeContentState();
}//当状态改变时,并不希望重新创建新的state
class _HYHomeContentState extends State<HYHomeContent> {int _counter = 0;@overrideWidget build(BuildContext context) {return Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [_getButton(),Text("当前计数: $_counter", style: TextStyle(fontSize: 25),)],),);}Widget _getButton() {return Row(mainAxisAlignment: MainAxisAlignment.center,children: [ElevatedButton(onPressed: () {setState(() {_counter++;});},child: Text("+", style: TextStyle(fontSize: 20, color: Colors.white),),style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.green)),),ElevatedButton(onPressed: () {setState(() {_counter--;});},child: Text("-", style: TextStyle(fontSize: 20, color: Colors.white),),style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.red)),)],);}
}

在这里插入图片描述

2.5 从Widget传递信息到State

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

2.6 生命周期

生命周期说的简单些是回调,钩子。生命周期的函数作用是
1、初始化一些东西
2、监听组件的事件
3、管理内存(手动销毁)

在flutter中只需要监听Widget的生命周期。
statelessWidget调用build方法和构造函数

class HYHomePage extends StatelessWidget {final String str;HYHomePage(this.str) {print("构造函数调用");}@overrideWidget build(BuildContext context) {print("调用build方法");return Text("aaa");}
}

在这里插入图片描述

statefulWidget生命周期

import 'package:flutter/material.dart';
import 'package:flutter_learn/02_checkbox.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: HYHomePage(),);}
}
class HYHomePage extends StatelessWidget {HYHomePage() {print("调用HYHomePage的构造函数");}@overrideWidget build(BuildContext context) {print("调用HYHomePage的build方法");return Scaffold(appBar: AppBar(title: Text("生命周期"),),body: HYHomeContent(),);}
}
class HYHomeContent extends StatefulWidget {HYHomeContent() {print("1、调用HYHomeContent的构造函数");}@overrideState<HYHomeContent> createState() {print("2、调用_HYHomeContent的createState方法");return _HYHomeContentState();}
}class _HYHomeContentState extends State<HYHomeContent> {int _count = 0;_HYHomeContentState() {print("3、调用_HYHomeContentState的构造函数");}@overridevoid initState() {//这里是必须调用super//原因:父类做初始化、mustcallSuper注解print("4、调用_HYHomeContentState的initState方法");super.initState();}@overrideWidget build(BuildContext context) {print("5、调用_HYHomeContentState的build方法");return Column(children: [ElevatedButton(onPressed: () {setState(() {_count++;});},child: Icon(Icons.add)),Text("数字:$_count")],);}@overridevoid didChangeDependencies() {print("调用_HYHomeContentState的didChangeDependencies方法");super.didChangeDependencies();}@overridevoid didUpdateWidget(covariant HYHomeContent oldWidget) {print("调用_HYHomeContentState的didUpdateWidget方法");super.didUpdateWidget(oldWidget);}@overridevoid dispose() {print("6、调用_HYHomeContentState的dispose方法");super.dispose();}
}

在这里插入图片描述
按照图上的顺序1-5,以及dispose。当点击按钮时会调用build方法。

2.7 富文本使用

class HYHomeContent extends StatefulWidget {const HYHomeContent({Key? key}) : super(key: key);@overrideState<HYHomeContent> createState() => _HYHomeContentState();
}class _HYHomeContentState extends State<HYHomeContent> {@overrideWidget build(BuildContext context) {return Text.rich(TextSpan(children: [TextSpan(text: "Hello World",style: TextStyle(color: Colors.red, fontSize: 20)),WidgetSpan(child: Icon(Icons.favorite, color: Colors.red,)),TextSpan(text: "Hello World",style: TextStyle(color: Colors.red, fontSize: 20)),]));}
}

在这里插入图片描述

2.8 button widget

import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: HYHomePage(),);}
}
class HYHomePage extends StatelessWidget {const HYHomePage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("基础的Widget"),),body: HYHomeContent(),floatingActionButton: FloatingActionButton(onPressed: () => print("FloatingActionButton Click"),child: Icon(Icons.add),),floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,);}
}
class HYHomeContent extends StatefulWidget {const HYHomeContent({Key? key}) : super(key: key);@overrideState<HYHomeContent> createState() => _HYHomeContentState();
}class _HYHomeContentState extends State<HYHomeContent> {@overrideWidget build(BuildContext context) {return Column(//Column主轴是垂直,Row主轴是水平,Column在交叉轴上会居中显示内容crossAxisAlignment: CrossAxisAlignment.center,children: [ElevatedButton(onPressed: () => print("ElevatedButton Click"),child: Text("ElevatedButton"),style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.red),foregroundColor: MaterialStateProperty.all(Colors.white),),),TextButton(onPressed: () => print("TextButton Click"),child: Text("TextButton"),style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.lightBlue),foregroundColor: MaterialStateProperty.all(Colors.white),),),OutlinedButton(onPressed: () => print("OutlineButton"),child: Text("OutlinedButton"),style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.orange),foregroundColor: MaterialStateProperty.all(Colors.white),),),TextButton(onPressed: () => print("click"),child: Row(//row默认会在主轴延伸至最大,这里设置为最小mainAxisSize: MainAxisSize.min,children: [Icon(Icons.favorite, color: Colors.redAccent),Text("喜欢作者")],),style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.lightBlue),foregroundColor: MaterialStateProperty.all(Colors.white),shape: MaterialStateProperty.all(ContinuousRectangleBorder(side: BorderSide.none,borderRadius: BorderRadius.all(Radius.circular(20))))),)],);}
}

在这里插入图片描述

2.9 image widget


main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: HYHomePage(),);}
}class HYHomePage extends StatelessWidget {const HYHomePage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("基础的Widget"),),body: ImageDemo02(),);}
}class ImageDemo01 extends StatefulWidget {@overrideState<ImageDemo01> createState() => _ImageDemo01State();
}class _ImageDemo01State extends State<ImageDemo01> {final _imageURL = "https://img.zcool.cn/community/01ad5d57d418eb0000018c1b65ed20.jpg@1280w_1l_2o_100sh.jpg";@overrideWidget build(BuildContext context) {return Image(image: NetworkImage(_imageURL),width: 200,height: 200,//宽度为200,高度自适应fit: BoxFit.contain,//矩形框最左上角为(-1,-1),最右下角为(1,1),中间为(0.0)alignment: Alignment(0,0),color: Colors.green,colorBlendMode: BlendMode.colorDodge,repeat: ImageRepeat.repeatY,);}
}class ImageDemo02 extends StatefulWidget {@overrideState<ImageDemo02> createState() => _ImageDemo02State();
}class _ImageDemo02State extends State<ImageDemo02> {@overrideWidget build(BuildContext context) {// return Image(//   // 1、创建文件夹存储图片//   // 2、在pubspec.yaml进行配置//   // 3、使用图片//     image: AssetImage("assets/images/test.jpg")// );return Image.asset("assets/images/test.jpg");}
}

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

2.10 图片扩展案例&按钮扩展案例

import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: HYHomePage(),);}
}class HYHomePage extends StatelessWidget {const HYHomePage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("基础的Widget"),),body: ButtonExtension(),);}
}class ButtonExtension extends StatefulWidget {const ButtonExtension({Key? key}) : super(key: key);@overrideState<ButtonExtension> createState() => _ButtonExtensionState();
}class _ButtonExtensionState extends State<ButtonExtension> {@overrideWidget build(BuildContext context) {return Column(children: [ButtonTheme(minWidth: 30,height: 10,child: FlatButton(padding: EdgeInsets.all(0),color: Colors.red,materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,onPressed: () {},child: Text("Flate Button"),textColor: Colors.white,),)],);}
}class ImageExtensionDemo extends StatefulWidget {@overrideState<ImageExtensionDemo> createState() => _ImageExtensionDemoState();
}class _ImageExtensionDemoState extends State<ImageExtensionDemo> {final String _imageURL ="https://img.zcool.cn/community/01ad5d57d418eb0000018c1b65ed20.jpg@1280w_1l_2o_100sh.jpg";@overrideWidget build(BuildContext context) {return FadeInImage(fadeOutDuration: Duration(milliseconds: 1000),fadeInDuration: Duration(milliseconds: 1000),placeholder: AssetImage("assets/images/test.jpg"),image: NetworkImage(_imageURL));}
}

在这里插入图片描述

2.11 图标使用

class IconExtension extends StatefulWidget {const IconExtension({Key? key}) : super(key: key);@overrideState<IconExtension> createState() => _IconExtensionState();
}class _IconExtensionState extends State<IconExtension> {@overrideWidget build(BuildContext context) {// 1、矢量图放大不失真// 字体图标可以设置颜色// 图标很多时,占据空间小// return Icon(Icons.pets, size: 300, color: Colors.orange,);// return Icon(IconData(0xe91d, fontFamily: 'MaterialIcons'), size: 300, color: Colors.orange,);//传入unicode编码return Text("\ue91d", style: TextStyle(fontSize: 100, color: Colors.orange, fontFamily: 'MaterialIcons'));}
}

在这里插入图片描述

2.12 登录功能案例

import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: HYHomePage(),theme: ThemeData(// Colors.red// Colors.red[100]// Color(0xffffffff)// Color.fromRGBO(111, 100, 100, 50)primaryColor: ,colorScheme: const ColorScheme.light(//顶部栏栏颜色primary: Colors.red,//顶部栏字体颜色onPrimary: Colors.white,onBackground: Colors.white,)),);}
}class HYHomePage extends StatelessWidget {const HYHomePage({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("基础的Widget"),),body: TextFieldDemo(),);}
}
class TextFieldDemo extends StatefulWidget {const TextFieldDemo({Key? key}) : super(key: key);@overrideState<TextFieldDemo> createState() => _TextFieldDemoState();
}class _TextFieldDemoState extends State<TextFieldDemo> {final usernameTextEditController = TextEditingController();final passwordTextEditController = TextEditingController();@overrideWidget build(BuildContext context) {return Padding(padding: const EdgeInsets.all(8.0),child: Column(children: [Padding(padding: const EdgeInsets.all(8.0),child: TextField(controller: usernameTextEditController,decoration: InputDecoration(labelText: "user name",icon: Icon(Icons.people),hintText: "请输入用户名",border: InputBorder.none,fillColor: Colors.red[100],filled: true),onChanged: (value) => {print(value)},onSubmitted: (value) => {print(value)},),),SizedBox(height: 10,),Padding(padding: const EdgeInsets.all(8.0),child: TextField(controller: passwordTextEditController,decoration: InputDecoration(labelText: "password",icon: Icon(Icons.lock),border: OutlineInputBorder()),),),Padding(padding: const EdgeInsets.all(8.0),child: Container(height: 40,width: double.infinity,child: FlatButton(child: Text("登 录", style: TextStyle(fontSize: 20, color: Colors.white),),onPressed: () {//获取用户名和密码final String username = usernameTextEditController.text;final String password = passwordTextEditController.text;print("账号:${username}; 密码:${password}");},color: Colors.blue,),),)],),);}
}

在这里插入图片描述

2.13 单个子组件布局案例

import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: HYHomeContent());}
}
class HYHomeContent extends StatelessWidget {const HYHomeContent({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: ContainerDemo(),appBar: AppBar(title: Text("布局"),),);}
}class ContainerDemo extends StatefulWidget {const ContainerDemo({Key? key}) : super(key: key);@overrideState<ContainerDemo> createState() => _ContainerDemoState();
}class _ContainerDemoState extends State<ContainerDemo> {@overrideWidget build(BuildContext context) {return Container(//这里的颜色加上会与decoration里面的颜色冲突,选择其中一个// color: Colors.red,width: 200,height: 200,//在container里面加入Alignment,里面有子组件时,构成一个三层机构,子组件文本不会放大,在Align里面居中显示//若不加上Alignment会使Text扩大到Container设置的宽度高度一般大小,这样文本从左上角开始排列,也就不是居中了// alignment: Alignment(0,0),padding: EdgeInsets.all(20),margin: EdgeInsets.all(50),child: Text("data"),// child: Icon(Icons.pets, size: 50, color: Colors.blue,),decoration: BoxDecoration(color: Colors.red,border: Border.all(width: 5,color: Colors.black),//圆形设置为100// borderRadius: BorderRadius.circular(100),borderRadius: BorderRadius.circular(10),boxShadow: [//Offset(x,y),x为正,往右,y为正,往下//spreadRadius延伸,在offset基础上延伸,blurRadius是模糊BoxShadow(color: Colors.orange,offset: Offset(10,10),spreadRadius: 5,blurRadius: 10),BoxShadow(color: Colors.green,offset: Offset(-10,-10),spreadRadius: 5,blurRadius: 10)]),);}
}class PaddingDemo extends StatefulWidget {const PaddingDemo({Key? key}) : super(key: key);@overrideState<PaddingDemo> createState() => _PaddingDemoState();
}class _PaddingDemoState extends State<PaddingDemo> {@overrideWidget build(BuildContext context) {return Column(children: [Padding(//EdgeInsets.symmetric(vertical: 5,horizontal: 0)padding: const EdgeInsets.only(bottom: 10),child: Text("Hello WYJ", style: TextStyle(fontSize: 30, backgroundColor: Colors.red),),),Text("Hello WYJ", style: TextStyle(fontSize: 30, backgroundColor: Colors.red),),Text("Hello WYJ", style: TextStyle(fontSize: 30, backgroundColor: Colors.red),)],);}
}class AlignDemo extends StatefulWidget {const AlignDemo({Key? key}) : super(key: key);@overrideState<AlignDemo> createState() => _AlignDemoState();
}class _AlignDemoState extends State<AlignDemo> {@overrideWidget build(BuildContext context) {//Center就是Alignreturn Container(width: 200,height: 200,color: Colors.amber,child: Align(// //高度和宽度的倍数// widthFactor: 5,// heightFactor: 5,//左上角为(-1,-1),右下角为(1,1),中心点为(0,0)alignment: Alignment(0, 0),child: Text("Hello"),// child: Icon(Icons.pets, size: 100,),),);}
}

在这里插入图片描述

2.14 flex

import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: HYHomeContent());}
}
class HYHomeContent extends StatelessWidget {const HYHomeContent({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: FlexDemo(),appBar: AppBar(title: Text("布局"),),);}
}class FlexDemo extends StatefulWidget {const FlexDemo({Key? key}) : super(key: key);@overrideState<FlexDemo> createState() => _FlexDemoState();
}class _FlexDemoState extends State<FlexDemo> {@overrideWidget build(BuildContext context) {//Row/Column:继承自Flex//Flex:CSS Flex布局//Axis.horizontal水平Row;Axis.vertical垂直columreturn Container(height: 300,child: Row(/*** start是主轴开始、end是主轴结束开始、center是主轴中心开始,其他元素评分距离* MainAxisAlignment* -spacebetween是左右两边设置为0,其他元素之间平分间距* -spaceAround左右两边的间距是其他元素之间的间距的一半* -spaceEvenly所有间距均分距离* CrossAxisAlignment* -start从交叉轴起始位置对齐* -end从交叉轴结束为止对齐* -center中心对齐* -baseline基线对齐,按照文字的基线对齐,当内容有文本时,基线对齐才起作用* -stretch是现将Row尽可能的拉伸最大的空间,将所有的子Widget交叉轴的高度拉伸到最大*/mainAxisAlignment: MainAxisAlignment.spaceEvenly,crossAxisAlignment: CrossAxisAlignment.stretch,textBaseline: TextBaseline.alphabetic,// textDirection: TextDirection.rtl,children: [Container(width: 80, height: 60,color: Colors.red, child: Text("Hello", style: TextStyle(fontSize: 10),)),Container(width: 90, height: 100,color: Colors.green, child: Text("Hello", style: TextStyle(fontSize: 30),)),Container(width: 50, height: 120,color: Colors.orange, child: Text("Hello", style: TextStyle(fontSize: 20),)),Container(width: 70, height: 110,color: Colors.blue, child: Text("Hello", style: TextStyle(fontSize: 40),)),],),);}
}
class FlexDemo02 extends StatefulWidget {const FlexDemo02({Key? key}) : super(key: key);@overrideState<FlexDemo02> createState() => _FlexDemo02State();
}class _FlexDemo02State extends State<FlexDemo02> {@overrideWidget build(BuildContext context) {return RaisedButton(color: Colors.blue,onPressed: () => print("按钮点击"),child: Row(mainAxisSize: MainAxisSize.min,children: [Icon(Icons.pets),Text("button")],),);}
}

在这里插入图片描述

expanded

class FlexDemo extends StatefulWidget {const FlexDemo({Key? key}) : super(key: key);@overrideState<FlexDemo> createState() => _FlexDemoState();
}class _FlexDemoState extends State<FlexDemo> {@overrideWidget build(BuildContext context) {return Container(height: 300,child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,crossAxisAlignment: CrossAxisAlignment.center,textBaseline: TextBaseline.alphabetic,children: [/*** Flexible中的属性:* - flex* Expanded(更多)-》flexible(fit:Flexfit:tight)* 空间分配问题**/Expanded(flex: 1,child: Container(width: 50,height: 60,color: Colors.red,)),Expanded(flex: 1,child: Container(width: 50,height: 100,color: Colors.green,),),Container(width: 50,height: 120,color: Colors.orange,),Container(width: 70,height: 110,color: Colors.blue,),],),);}
}

在这里插入图片描述

2.15 stack(组件重叠)

import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: HYHomeContent());}
}class HYHomeContent extends StatelessWidget {const HYHomeContent({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(body: StackDemo02(),appBar: AppBar(title: Text("布局"),),);}
}class StackDemo01 extends StatefulWidget {const StackDemo01({Key? key}) : super(key: key);@overrideState<StackDemo01> createState() => _StackDemo01State();
}class StackDemo02 extends StatefulWidget {const StackDemo02({Key? key}) : super(key: key);@overrideState<StackDemo02> createState() => _StackDemo02State();
}class _StackDemo02State extends State<StackDemo02> {bool _isFavorite = false;@overrideWidget build(BuildContext context) {return Stack(children: [Image.asset("assets/images/test.jpg",),Positioned(left: 0,right: 0,bottom: 0,child: Container(width: double.infinity,child: Padding(padding: const EdgeInsets.all(8.0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Text("photo",style: TextStyle(fontSize: 20, color: Colors.white),),// GestureDetector(child: Icon(Icons.favorite, color: Colors.white,)),IconButton(onPressed: () {setState(() {this._isFavorite = !this._isFavorite;});},icon: Icon(Icons.favorite,color: this._isFavorite == true ? Colors.red : Colors.white,))],),),color: Color.fromARGB(150, 0, 0, 0),),)],);}
}class _StackDemo01State extends State<StackDemo01> {@overrideWidget build(BuildContext context) {/*** Stack默认的大小是包裹内容的* - alignment从什么位置开始排布所有的子Widget* - fit:expand将子元素拉伸到尽可能大* - overflow:超出部分如何处理*/return Stack(alignment: Alignment.center,// fit: StackFit.expand,// clipBehavior: Clip.none,children: [Image.asset("assets/images/test.jpg",width: 300,fit: BoxFit.cover,),Positioned(left: 0,bottom: -50,child: Container(width: 150,height: 150,color: Colors.red,),),Positioned(child: Text("photo",style: TextStyle(fontSize: 20, color: Colors.green),),//left:0表示距离左侧为0left: 0,)],);}
}

在这里插入图片描述

2.16 gridView

import 'dart:math';import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(""),),body: HYHomeContent(),);}
}class HYHomeContent extends StatefulWidget {@overrideState<HYHomeContent> createState() => _HYHomeContentState();
}class _HYHomeContentState extends State<HYHomeContent> {@overrideWidget build(BuildContext context) {return GridViewDemo03();}
}class GridViewDemo03 extends StatelessWidget {const GridViewDemo03({Key? key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Padding(padding: const EdgeInsets.symmetric(horizontal: 8),child: GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2,mainAxisSpacing: 8,crossAxisSpacing: 8),itemBuilder: (BuildContext ctx, int index){return Container(color: Color.fromARGB(255, Random().nextInt(255),Random().nextInt(255), Random().nextInt(255)),);}),);}
}class GridViewDemo02 extends StatelessWidget {const GridViewDemo02({Key? key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Padding(padding: const EdgeInsets.symmetric(horizontal: 8),child: GridView(gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent: 200,crossAxisSpacing: 8,mainAxisSpacing: 8,childAspectRatio: 0.8),children: List.generate(100, (index) {return Container(color: Color.fromARGB(255, Random().nextInt(255),Random().nextInt(255), Random().nextInt(255)),);}),),);}
}class GridViewDemo01 extends StatelessWidget {const GridViewDemo01({Key? key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Padding(padding: const EdgeInsets.symmetric(horizontal: 8),child: GridView(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3,childAspectRatio: 0.8,crossAxisSpacing: 8,mainAxisSpacing: 8),children: List.generate(100, (index) {return Container(color: Color.fromARGB(255, Random().nextInt(255),Random().nextInt(255), Random().nextInt(255)),);}),),);}
}

2.17 scrollView

import 'dart:math';
import 'dart:ui';import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(// appBar: AppBar(//   title: Text("Custom ScrollView"),// ),body: HYHomeContent(),);}
}class HYHomeContent extends StatefulWidget {@overrideState<HYHomeContent> createState() => _HYHomeContentState();
}class _HYHomeContentState extends State<HYHomeContent> {@overrideWidget build(BuildContext context) {return CustomScrollView(slivers: [SliverAppBar(pinned: true,expandedHeight: 300,flexibleSpace: FlexibleSpaceBar(title: Text("Hello world",),background: Image.asset("assets/images/test.jpg", fit: BoxFit.cover,),),),SliverGrid(delegate: SliverChildBuilderDelegate((BuildContext ctx, int index) {return Container(color: Color.fromARGB(255, Random().nextInt(256), Random().nextInt(256),Random().nextInt(256)),);},childCount: 10),gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2,crossAxisSpacing: 8,mainAxisSpacing: 8,childAspectRatio: 1.5)),SliverList(delegate: SliverChildBuilderDelegate((BuildContext ctx, int index) {return ListTile(leading: Icon(Icons.people),title: Text("联系人$index"),);},childCount: 20))],);}
}class CustomScrollViewDemo01 extends StatelessWidget {const CustomScrollViewDemo01({Key? key,}) : super(key: key);@overrideWidget build(BuildContext context) {return CustomScrollView(slivers: [//区别safeAreaSliverSafeArea(sliver: SliverPadding(padding: EdgeInsets.all(8),sliver: SliverGrid(delegate:SliverChildBuilderDelegate((BuildContext ctx, int index) {return Container(color: Color.fromARGB(255, Random().nextInt(255),Random().nextInt(255), Random().nextInt(255)),);}, childCount: 10),gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2,crossAxisSpacing: 8,mainAxisSpacing: 8,childAspectRatio: 1.5)),),)],);}
}

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

2.18 监听滚动(NotificationListener)

import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatefulWidget {@overrideState<HYHomePage> createState() => _HYHomePageState();
}class _HYHomePageState extends State<HYHomePage> {ScrollController _controller = ScrollController(initialScrollOffset: 300);bool _isShowFloatingButton = false;@overridevoid initState() {super.initState();_controller.addListener(() {// print("监听到滚动--${_controller.offset}");setState(() {_isShowFloatingButton = _controller.offset >= 1000;});});}@overrideWidget build(BuildContext context) {/*** 两种方式可以监听:* controller:*    1、设置默认值*    2、监听滚动,也可以监听滚动的位置* NotificationListener*    1、监听开始滚动和结束滚动*/return Scaffold(appBar: AppBar(title: Text("Custom ScrollView"),),body: NotificationListener(onNotification: (ScrollNotification notification) {if(notification is ScrollStartNotification) {print("开始滚动");} else if (notification is ScrollEndNotification) {print("结束滚动");} else if(notification is ScrollUpdateNotification) {print("正在滚动...,总滚动的范围为${notification.metrics.maxScrollExtent};当前滚动的像素为${notification.metrics.pixels}");}return true;},child: ListView.builder(controller: _controller,itemCount: 100,itemBuilder: (BuildContext ctx, int index) {return ListTile(leading: Icon(Icons.people),title: Text("联系人$index"),);}),),floatingActionButton: _isShowFloatingButton? FloatingActionButton(child: Icon(Icons.arrow_upward),onPressed: () {_controller.animateTo(0,duration: Duration(seconds: 1), curve: Curves.easeIn);},): null,);}
}

2.19 网络请求

config.dart

class HttpConfig {static const String baseURL = "https://httpin.org";static const int timeout = 5000;
}

http_request.dart

import 'package:dio/dio.dart';
import 'package:flutter_learn/service/config.dart';class HttpRequest {static final BaseOptions baseOption = BaseOptions(baseUrl: HttpConfig.baseURL, connectTimeout: HttpConfig.timeout);static final Dio dio = Dio(baseOption);static Future<T> request<T>(String url, {String method = "get",required Map<String, dynamic> params,required Interceptor inter})  async{//创建单独配置final options = Options(method: method);//全局拦截器//创建默认的拦截器Interceptor dInter = InterceptorsWrapper(onRequest: (options, handler) {print("请求拦截");return handler.next(options);},onError: (error,handle){print("错误拦截");return handle.next(error);},onResponse: (response, handler){print("响应拦截");handler.next(response);});List<Interceptor> inters = [dInter];//请求单独拦截器inters.add(inter);//统一添加dio.interceptors.addAll(inters);//发送网络请求try{Response response = await dio.request(url, queryParameters: params, options: options);//返回数据return response.data;} on DioError catch(e) {//返回错误return Future.error(e);}}
}

main.dart

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_learn/service/http_request.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("网络请求"),),body: HYHomeContent(),);}
}class HYHomeContent extends StatefulWidget {@overrideState<HYHomeContent> createState() => _HYHomeContentState();
}class _HYHomeContentState extends State<HYHomeContent> {@overridevoid initState() {super.initState();//发送网络请求//1、创建dio对象//2、发送网络请求final dio = Dio();dio.get("https://httpbin.org/get").then((value) {print(value);});dio.post("https://httpbin.org/post").then((value) {print(value);});HttpRequest.request("https://httpbin.org/get", params: {"name": "WYJ"}, inter: InterceptorsWrapper(onRequest: null)).then((value) {print(value);}).catchError((err){print(err);});}@overrideWidget build(BuildContext context) {return Container();}
}

运行结果

Launching lib\main.dart on MIX 2S in debug mode...
Running Gradle task 'assembleDebug'...
������ʽ����ȷ -Built build\app\outputs\flutter-apk\app-debug.apk.
Debug service listening on ws://127.0.0.1:51131/opqAKK6pzn4=/ws
Syncing files to device MIX 2S...
W/Gralloc3(29843): mapper 3.x is not supported
I/flutter (29843): 请求拦截
I/flutter (29843): 响应拦截
I/flutter (29843): {args: {name: WYJ}, headers: {Accept-Encoding: gzip, Host: httpbin.org, User-Agent: Dart/2.16 (dart:io), X-Amzn-Trace-Id: Root=1-62760ff8-1a8a8c3820473ddb2fd8e98a}, origin: 39.190.86.190, url: https://httpbin.org/get?name=WYJ}
I/flutter (29843): {"args":{},"headers":{"Accept-Encoding":"gzip","Host":"httpbin.org","User-Agent":"Dart/2.16 (dart:io)","X-Amzn-Trace-Id":"Root=1-62760ff8-005c4ed00ec32e1b622c24bb"},"origin":"39.190.86.190","url":"https://httpbin.org/get"}
I/flutter (29843): {"args":{},"data":"","files":{},"form":{},"headers":{"Accept-Encoding":"gzip","Content-Length":"0","Content-Type":"application/json; charset=utf-8","Host":"httpbin.org","User-Agent":"Dart/2.16 (dart:io)","X-Amzn-Trace-Id":"Root=1-62760ff8-66ee2d1c07568fc34858e558"},"json":null,"origin":"39.190.86.190","url":"https://httpbin.org/post"}

2.20 flutter渲染流程

Widget----->Element------>Render Object(最终由Render Object渲染界面)------>layout、paint

Element层作用:增加一层类似于虚拟dom,花最小的开销修改Widget

    //组件Widget不会生成RenderObjectContainer()Text()//渲染Widget生成RenderObjectPadding()Row()

Padding->SingleChildRenderObjectWidget->RenderObjectWidget->Widget
在这里插入图片描述
在widget里面有一个重要的方法createRenderObject,这是抽象方法,查看SingleChildRenderObjectWidget,并没有实现这个方法。
在这里插入图片描述
那么SingleChildRenderObjectWidget的子类Padding实现了这个方法
在这里插入图片描述
Padding->RenderPadding->RenderShiftedBox->RenderBox->RenderObject

那么Element的创建呢
在这里插入图片描述
查看Container的父类StatelessWidget
在这里插入图片描述
凡是继承Widget,子类必然要实现CreateElement这个方法
在这里插入图片描述
createElement创建的对象不同,比如这里的statelessWidget创建了StatelessElement
在这里插入图片描述
查看ComponentElement
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最终还是调用了Widget里面的build方法,那么Widget是谁?
回到Container
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看出这里的widget赋值给_widget

对于RenderObject
在这里插入图片描述
在这里插入图片描述
做的是createRenderObject的操作

【补充】为什么能在state里面获取widget
在这里插入图片描述

2.21 key的作用

import 'dart:math';import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatefulWidget {@overrideState<HYHomePage> createState() => _HYHomePageState();
}class _HYHomePageState extends State<HYHomePage> {final List<String> names = ["aaaa", "bbbbb", "cccccc"];@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("列表测试"),),body: ListView(children:names.map((item) {return ListItemLess(item);}).toList(),),floatingActionButton: FloatingActionButton(child: Icon(Icons.delete),onPressed: () {setState(() {names.removeAt(0);});},),);}
}class ListItemLess extends StatelessWidget {final String name;final Color randColor = Color.fromARGB(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), Random().nextInt(256));ListItemLess(this.name);@overrideWidget build(BuildContext context) {return Container(child: Text(name),height: 80,color: randColor,width: double.infinity,);}
}

在这里插入图片描述
点击删除按钮,虽然删除了第一个item,但是颜色也重新build了,此时将statelessWidget转换为statefulWidget

import 'dart:math';import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatefulWidget {@overrideState<HYHomePage> createState() => _HYHomePageState();
}class _HYHomePageState extends State<HYHomePage> {final List<String> names = ["aaaa", "bbbbb", "cccccc"];@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("列表测试"),),body: ListView(children:names.map((item) {return ListItemFul(item);}).toList(),),floatingActionButton: FloatingActionButton(child: Icon(Icons.delete),onPressed: () {setState(() {names.removeAt(0);});},),);}
}// class ListItemLess extends StatelessWidget {
//   final String name;
//   final Color randColor = Color.fromARGB(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), Random().nextInt(256));
//   ListItemLess(this.name);
//
//   @override
//   Widget build(BuildContext context) {
//     return Container(
//       child: Text(name),
//       height: 80,
//       color: randColor,
//       width: double.infinity,
//     );
//   }
// }class ListItemFul extends StatefulWidget {final String name;ListItemFul(this.name);@overrideState<ListItemFul> createState() => _ListItemFulState();
}class _ListItemFulState extends State<ListItemFul> {final Color randColor = Color.fromARGB(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), Random().nextInt(256));@overrideWidget build(BuildContext context) {return Container(child: Text(widget.name),height: 80,color: randColor,width: double.infinity,);}
}

在这里插入图片描述
在这里插入图片描述
虽然删除了第一个,但是实际效果是删除了最后一个。
原因是如图
在这里插入图片描述
也就是说当没有key传入时,element数组默认会删除最有一个。
接下来修改代码,传入key

import 'dart:math';import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatefulWidget {@overrideState<HYHomePage> createState() => _HYHomePageState();
}class _HYHomePageState extends State<HYHomePage> {final List<String> names = ["aaaa", "bbbbb", "cccccc"];@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("列表测试"),),body: ListView(children:names.map((item) {//把名字作为keyreturn ListItemFul(item, key: ValueKey(item),);}).toList(),),floatingActionButton: FloatingActionButton(child: Icon(Icons.delete),onPressed: () {setState(() {names.removeAt(0);});},),);}
}class ListItemFul extends StatefulWidget {final String name;ListItemFul(this.name, {key}): super(key: key);@overrideState<ListItemFul> createState() => _ListItemFulState();
}class _ListItemFulState extends State<ListItemFul> {final Color randColor = Color.fromARGB(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), Random().nextInt(256));@overrideWidget build(BuildContext context) {return Container(child: Text(widget.name),height: 80,color: randColor,width: double.infinity,);}
}

传入key之后,element就会对比新的和旧的,他们的key时候一致,删除第一个,那么就没有对应的element与之对应,最终留下的是第二个和第三个
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
回到源码,这里的canUpdate方法里面的操作,他会比较runtimeType和key

  static bool canUpdate(Widget oldWidget, Widget newWidget) {return oldWidget.runtimeType == newWidget.runtimeType&& oldWidget.key == newWidget.key;}

key还可以强制界面刷新,比如随机生成一个不重复的key

          return ListItemFul(item, key: UniqueKey(),);

还可以传入对象生成key

          ObjectKey(对象)

GlobalKey的作用可以在Widget访问到子Widget内的属性、对象以及State内的属性和对象、子Widget的方法

import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatelessWidget {final GlobalKey<_HYHomeContentState> homeKey = GlobalKey();@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(""),),body: HYHomeContent(key: homeKey,),floatingActionButton: FloatingActionButton(child: Icon(Icons.gesture),onPressed: () {print(homeKey.currentState?.widget.message);print(homeKey.currentState?.name);},),);}
}
class HYHomeContent extends StatefulWidget {final String message = "aaaa";HYHomeContent({key}): super(key: key);@overrideState<HYHomeContent> createState() => _HYHomeContentState();
}class _HYHomeContentState extends State<HYHomeContent> {final String name = "bbbb";@overrideWidget build(BuildContext context) {return Container();}
}

在这里插入图片描述

2.22 共享数据

InheritedWidget

import 'package:flutter/material.dart';main() => runApp(MyApp());/*** 1、共享数据* 2、定义构造方法* 3、获取组件最近的当前InheritedWidget* 4、决定要不要回调State中的didChangeDependencies*/class HYCounterWidget extends InheritedWidget {final int counter;HYCounterWidget({required this.counter, child}): super(child: child);static HYCounterWidget? of(BuildContext context) {// 沿着Element树,去找到最近的HYCounterElementreturn context.dependOnInheritedWidgetOfExactType();}//返回true:执行依赖当前的InheritedWidget的state中的didChangeDependencies方法@overridebool updateShouldNotify(HYCounterWidget oldWidget) {// return true;//判断counter是否发生改变,改变就返回truereturn oldWidget.counter != counter;}
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatefulWidget {@overrideState<HYHomePage> createState() => _HYHomePageState();
}class _HYHomePageState extends State<HYHomePage> {int _counter = 100;@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("状态管理"),),body: HYCounterWidget(counter: _counter,child: Column(children: [HYShowData01(),HYShowData02()],),),floatingActionButton: FloatingActionButton(child: Icon(Icons.add),onPressed: () {setState(() {this._counter++;});},),);}
}
class HYShowData01 extends StatefulWidget {const HYShowData01({Key? key}) : super(key: key);@overrideState<HYShowData01> createState() => _HYShowData01State();
}class _HYShowData01State extends State<HYShowData01> {// 依赖InheritedWidget(HYCounterWidget),// 当数据改变时,会调用这里的didChangeDependencies方法@overridevoid didChangeDependencies() {super.didChangeDependencies();print("执行了_HYHomePageState中的didChangeDependencies方法");}@overrideWidget build(BuildContext context) {int? counter = HYCounterWidget.of(context)?.counter;return Card(color: Colors.red,child: Text("当前计数:${counter}"),);}
}
class HYShowData02 extends StatelessWidget {const HYShowData02({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {int? counter = HYCounterWidget.of(context)?.counter;return Card(color: Colors.blue,child: Text("当前计数:${counter}"),);}
}

provider、Consumer、selector

provider.dart

import 'package:flutter/material.dart';
import 'viewmodel/initialize.dart';
import 'package:provider/provider.dart';
import 'viewmodel/01_inheritedWidget.dart';
import 'viewmodel/02_UserViewModel.dart';/*** 1。创建自己需要共享的数据* 2.在应用程序的顶层加上ChangeNotifierProvider* 3.在其他位置使用共享的数据*  - provider.of:数据发生改变时,所在的Widget的build方法会重新执行*  - Consumer:只有consumer的build方法会重新构建*  - selector: 1.selector方法对原有数据进行转换;2、shouldRebuild是否要重新构建**  多个共享数据使用MultiProvider**/main() {runApp(MultiProvider(providers: provider,child: MyApp(),));
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(""),),body: Column(children: [HYShowData01(), HYShowData02(), HYShowData03()],),floatingActionButton:Selector<HYCounterViewModel, HYCounterViewModel>(selector: (ctx, counterVM) {return counterVM;},shouldRebuild: (prev, next) {return false;},builder: (ctx, builder, child) {return FloatingActionButton(child: child,onPressed: () {builder.counter++;},);},child: Icon(Icons.add),)// Consumer<HYCounterViewModel>(//     builder: (ctx, builder, child) {//       return FloatingActionButton(//         child: child,//         onPressed: () {//           builder.counter++;//         },//       );//     },//   child: Icon(Icons.add),,// ));}
}class HYShowData01 extends StatelessWidget {const HYShowData01({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {//拿到对象int counter = Provider.of<HYCounterViewModel>(context).counter;return Card(color: Colors.blue,child: Text("当前计数:$counter"),);}
}class HYShowData02 extends StatelessWidget {const HYShowData02({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {int counter = Provider.of<HYCounterViewModel>(context).counter;return Consumer<HYCounterViewModel>(builder: (ctx, builder, child) {return Card(color: Colors.red,child: Text("当前计数:${builder.counter}"),);});}
}class HYShowData03 extends StatelessWidget {const HYShowData03({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {// return Consumer<HYUserViewModel>(builder: (ctx, builder, child) {//   return Text("nickname:${builder.user.nickname}");// });return Consumer2<HYUserViewModel, HYCounterViewModel>(builder: (ctx, userVM, counterVM, child) {return Text("nickname:${userVM.user.nickname}, counter:${counterVM.counter}");});}
}

01_inheritedWidget.dart

import 'package:flutter/cupertino.dart';//with是混入,如果该类已经继承其他类就不能使用extends继承,而是with混入
class HYCounterViewModel with ChangeNotifier{int _counter = 100;int get counter => _counter;set counter(int value) {_counter = value;//通知所有使用过counter的监听者notifyListeners();}
}

02_UserViewModel.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter_learn/%E5%AD%A6%E4%B9%A0%E6%A1%88%E4%BE%8B/24_%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86/model/user_model.dart';class HYUserViewModel extends ChangeNotifier {UserInfo _user;HYUserViewModel(this._user);UserInfo get user => _user;set user(UserInfo value) {_user = value;}
}

initialize.dart

import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';import '../model/user_model.dart';
import '01_inheritedWidget.dart';
import '02_UserViewModel.dart';List<SingleChildWidget> provider = [ChangeNotifierProvider(create: (ctx) => HYCounterViewModel(),),ChangeNotifierProvider(create: (ctx) => HYUserViewModel(UserInfo("WYJ", 1, "1111")),)
];

在这里插入图片描述

2.23 手势监听

import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(""),),body: HYGuestureDemo03(),);}
}class HYGuestureDemo03 extends StatelessWidget {const HYGuestureDemo03({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Center(child: Stack(alignment: Alignment.center,children: [GestureDetector(onTapDown: (detail) {print("outer Click");},child: Container(width: 200, height: 200, color: Colors.red)),// IgnorePointer()  忽略手势GestureDetector(onTapDown: (detail) {print("inner Click");},child: Container(width: 100, height: 100, color: Colors.blue)),],),);}
}class HYGestureDemo02 extends StatelessWidget {const HYGestureDemo02({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Center(child: GestureDetector(onTapDown: (detail) {print("outer Click");},child: Container(width: 200,height: 200,color: Colors.red,//这里Container嵌套Container如果不加上Aligment属性,// 里面的Container会扩展至外部包裹的Container大小alignment: Alignment.center,child: GestureDetector(onTapDown: (detail) {print("inner Click");},child: Container(width: 100,height: 100,color: Colors.blue,),),),));}
}class HYGestureDemo extends StatelessWidget {const HYGestureDemo({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return Center(child: GestureDetector(onTap: () {print("手势点击");},onTapDown: (detail) {print("手势下落");},onTapUp: (detail) {print("手势抬起");},onTapCancel: () {print("手势取消");},child: Container(width: 200,height: 200,color: Colors.orange,),),);}
}class HYListenerDemo extends StatefulWidget {@overrideState<HYListenerDemo> createState() => _HYHYListenerDemoState();
}class _HYHYListenerDemoState extends State<HYListenerDemo> {@overrideWidget build(BuildContext context) {return Center(child: Listener(onPointerDown: (event) {print("指针按下:$event");print(event.position); //相对屏幕(左上角为0,0;往下为y,往右为x)print(event.localPosition); //相对当前组件的位置},onPointerMove: (event) {print("指针移动:$event");},onPointerUp: (event) {print("指针抬起:$event");},child: Container(width: 200,height: 200,color: Colors.red,),),);}
}

2.24 多Widget之间的通信(eventBus)

import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart';/*** 第一步:创建全局变量evenBus*/
final evenBus = EventBus();
class UserInfo {String nickname;int level;UserInfo(this.nickname, this.level);
}main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(""),),body: Column(children: [HYButton(),HYText()],),);}
}class HYText extends StatefulWidget {@overrideState<HYText> createState() => _HYTextState();
}class _HYTextState extends State<HYText> {String _message = "Hello World";@overridevoid initState() {super.initState();/*** 第三步:获取数据*/evenBus.on<UserInfo>().listen((event) {setState(() {_message = "${event.nickname}-${event.level}";});});}@overrideWidget build(BuildContext context) {return Text(_message);}
}class HYButton extends StatelessWidget {const HYButton({Key? key}) : super(key: key);@overrideWidget build(BuildContext context) {return RaisedButton(child: Text("按钮"),onPressed: () {/*** 第二步:发布数据*/final info = UserInfo("WYJ", 1);evenBus.fire(info);});}
}

2.25 路由管理

import 'package:flutter/material.dart';
import './about.dart';
import './detail.dart';
import 'error.dart';
import 'router/router.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent,),routes: HYRouter.routes,initialRoute: HYRouter.initialRoute,onGenerateRoute: HYRouter.generateRoute,onUnknownRoute: HYRouter.unknownRoute},);}
}class HYHomePage extends StatefulWidget {static const String routerName = "/";@overrideState<HYHomePage> createState() => _HYHomePageState();
}class _HYHomePageState extends State<HYHomePage> {String _message = "message";@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(""),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [RaisedButton(child: Text("跳转至详情"),onPressed: () => _jumpToDetail(context)),RaisedButton(child: Text("跳转至关于页面"),onPressed: () => _jumpToAbout(context)),RaisedButton(child: Text("跳转至详情页面"),onPressed: () => _jumpToDetail2(context)),RaisedButton(child: Text("跳转至设置页面"),onPressed: () => _jumpToSettings(context)),Text(_message)],),),);}void _jumpToDetail(BuildContext context) {//普通的跳转方式Future result = Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {return HYDetailScreen("home is message");}));result.then((value) {setState(() {_message = value;});print(value);});}void _jumpToAbout(BuildContext context) {Navigator.of(context).pushNamed(HYAboutPage.routerName, arguments: "a home message");}void _jumpToDetail2(BuildContext context) {Navigator.of(context).pushNamed(HYDetailScreen.routername, arguments: "a home detail2 message");}void _jumpToSettings(BuildContext context) {Navigator.of(context).pushNamed("/settings");}
}

router.dart

import 'package:flutter/material.dart';import '../27_路由管理.dart';
import '../about.dart';
import '../detail.dart';
import '../error.dart';class HYRouter {static final Map<String, WidgetBuilder> routes = {//命名路由HYHomePage.routerName: (ctx) => HYHomePage(),HYAboutPage.routerName: (ctx) => HYAboutPage()};static final String initialRoute = HYHomePage.routerName;static final RouteFactory generateRoute = (setting) {if (setting.name == HYDetailScreen.routername) {return MaterialPageRoute(builder: (ctx) {return HYDetailScreen(setting.arguments as String);});}return null;};static final RouteFactory unknownRoute = (settings) {return MaterialPageRoute(builder: (ctx) {return HYErrortPage();});};
}

detail.dart

import 'package:flutter/material.dart';class HYDetailScreen extends StatelessWidget {static const String routername = "/detail";String _message;HYDetailScreen(this._message);@overrideWidget build(BuildContext context) {return WillPopScope(onWillPop: () {_backToHome(context);/*** 当返回true时,可以自动返回* 当返回false时,自行返回代码*/return Future.value(false);},child: Scaffold(appBar: AppBar(title: Text("data"),// leading: IconButton(onPressed: () => {//   _backToHome(context)// }, icon: Icon(Icons.back_hand)),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text(_message,style: TextStyle(fontSize: 20,color: Colors.red),),RaisedButton(child: Text("back"),onPressed: () {_backToHome(context);})],),),),);}void _backToHome(BuildContext context) {Navigator.of(context).pop("a detail message");}
}

2.26 动画Animation

import 'package:flutter/material.dart';main() => runApp(MyApp());
/*** 1、Animation:抽象类*  - 监听动画值的改变*  - 监听动画状态的改变*  - value*  - status**  2、AnimationController继承Animation*  - vsync:同步信号,屏幕刷新率(要持续收到同步信号才会继续绘制)*  - vsync:this -》with SingleTickerProviderStateMixin*  - forward():向前执行动画*  - reverse():反转执行动画**  3、CurvedAnimation:*  - 作用:设置动画执行的速率(速度曲线)**  4、Tween:设置动画执行的value范围*  - begin:开始的大小*  - end:结束时大小**/
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatefulWidget {@overrideState<HYHomePage> createState() => _HYHomePageState();
}class _HYHomePageState extends State<HYHomePage>with SingleTickerProviderStateMixin {//1、创建AnimationControllerlate AnimationController _controller;late CurvedAnimation animation;late Animation valueAnimation;@overridevoid initState() {super.initState();_controller = AnimationController(vsync: this,duration: Duration(seconds: 1),lowerBound: 0,upperBound: 1);// 2、设置Curve的值animation = CurvedAnimation(parent: _controller, curve: Curves.elasticInOut);//3、TweenvalueAnimation = Tween(begin: 50.0, end: 150.0).animate(animation);// valueAnimation.addListener(() {//   setState(() {////   });// });_controller.addStatusListener((status) {if(status == AnimationStatus.completed) {_controller.reverse();} else  if(status == AnimationStatus.dismissed){_controller.forward();}});}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {print("执行_HYHomePageState的build方法");return Scaffold(appBar: AppBar(title: Text("动画"),),body: Center(//AnimatedBuilderchild: AnimatedBuilder(builder: (BuildContext context, Widget? child) {return Icon(Icons.favorite, color: Colors.red, size: valueAnimation.value);},animation: valueAnimation,),),floatingActionButton: FloatingActionButton(child: Icon(Icons.abc, color: Colors.red,),onPressed: () {if(_controller.isAnimating) {_controller.stop();}else {_controller.forward();}},),);}
}/*** AnimatedWidget* 1、将需要执行动画的Widget放到一个AnimatedWidget中的build方法进行返回* 2、缺点:A、每次都需要创建一个类;B、如果够贱的Widget有子类,那么子类依然会重复构建build** AnimatedBuilder* 最优选择*/
// class HYAnimatedIcon extends AnimatedWidget {
//   final Animation valueAnimation;
//   HYAnimatedIcon(this.valueAnimation) : super(listenable: valueAnimation);
//   @override
//   Widget build(BuildContext context) {
//     return Icon(Icons.favorite, color: Colors.red, size: valueAnimation.value);
//   }
// }

2.27 交织动画

import 'dart:math';import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatefulWidget {@overrideState<HYHomePage> createState() => _HYHomePageState();
}class _HYHomePageState extends State<HYHomePage>with SingleTickerProviderStateMixin {//1、创建AnimationControllerlate AnimationController _controller;late CurvedAnimation animation;late Animation valueAnimation;//交织动画:创建多个Tweenlate Animation _sizeAnimation;late Animation _colorAnimation;late Animation _opacityAnimation;late Animation _radiansAnimation;@overridevoid initState() {super.initState();_controller = AnimationController(vsync: this,duration: Duration(seconds: 1),lowerBound: 0,upperBound: 1);// 2、设置Curve的值animation =CurvedAnimation(parent: _controller, curve: Curves.elasticInOut);//3、TweenvalueAnimation = Tween(begin: 50.0, end: 150.0).animate(_controller);_colorAnimation =ColorTween(begin: Colors.blue, end: Colors.green).animate(_controller);_sizeAnimation = Tween(begin: 50.0, end: 150.0).animate(_controller);_opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(_controller);_radiansAnimation = Tween(begin: 0.0, end: 2.0 * pi).animate(_controller);_controller.addStatusListener((status) {if (status == AnimationStatus.completed) {_controller.reverse();} else if (status == AnimationStatus.dismissed) {_controller.forward();}});// //使用AnimatedBuilder就不需要setState// _controller.addListener(() {//   setState(() {});// });}@overridevoid dispose() {_controller.dispose();super.dispose();}@overrideWidget build(BuildContext context) {print("执行_HYHomePageState的build方法");/*** 交织动画:* 1、大小变化动画* 2、颜色变化动画* 3、透明度变化动画*/return Scaffold(appBar: AppBar(title: Text("动画"),),body: Center(//AnimatedBuilderchild: AnimatedBuilder(builder: (BuildContext context, Widget? child) {return Opacity(opacity: _opacityAnimation.value,child: Transform(transform: Matrix4.rotationZ(_radiansAnimation.value),alignment: Alignment.center, //对齐方式:以Container中心点居中对齐child: Container(height: _sizeAnimation.value,width: _sizeAnimation.value,color: _colorAnimation.value,),),);},animation: _controller,)),floatingActionButton: FloatingActionButton(child: Icon(Icons.abc,color: Colors.red,),onPressed: () {if (_controller.isAnimating) {_controller.stop();} else {_controller.forward();}},),);}
}

2.28 切换页面动画

import 'package:flutter/material.dart';
import 'modal_page.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(""),),body: Center(child: Text("Hello World"),),floatingActionButton: FloatingActionButton(child: Icon(Icons.add),onPressed: () {Navigator.of(context).push(PageRouteBuilder(transitionDuration: Duration(seconds: 3),pageBuilder: (ctx, animation1, animation2) {return FadeTransition(opacity: animation1,child: HYModalPage());})// MaterialPageRoute(builder: (ctx) {//   return HYModalPage();// }),);},),);}
}
import 'package:flutter/material.dart';
class HYModalPage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(backgroundColor: Colors.orange,appBar: AppBar(title: Text("Modal Page"),),body: Center(child: Text("Modal Page"),),);}
}

2.29 hero动画

import 'package:flutter/material.dart';
import 'modal_page.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue, splashColor: Colors.transparent),home: HYHomePage());}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(""),),body: Center(child: GridView(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2,crossAxisSpacing: 8,mainAxisSpacing: 8,childAspectRatio: 16 / 9),children: List.generate(20, (index) {final imageURL = "https://picsum.photos/200/300?random=$index";return GestureDetector(child: Hero(tag: imageURL,child: Image.network(imageURL, fit: BoxFit.cover),),onTap: () {Navigator.of(context).push(PageRouteBuilder(pageBuilder: (ctx, animation1, animation2) {return FadeTransition(opacity: animation1,child: HYModalPage(imageURL),);}),);},);}),),),);}
}
import 'package:flutter/material.dart';class HYModalPage extends StatelessWidget {final String _imageURL;HYModalPage(this._imageURL);@overrideWidget build(BuildContext context) {return Scaffold(backgroundColor: Colors.black,body: Center(child: GestureDetector(child: Hero(tag: _imageURL,child: Image.network(_imageURL,fit: BoxFit.cover,),),onTap: () {Navigator.of(context).pop();},),),);}
}

2.30 主题

import 'package:flutter/material.dart';main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(brightness: Brightness.light,//primarySwatch包含primaryColor和accentColorprimarySwatch: Colors.blue,//单独设置导航栏和TabBar的颜色primaryColor: Colors.orange,//单独设置FloatingButton/SwitchaccentColor: Colors.green,//Button的主题buttonTheme: ButtonThemeData(height: 25,minWidth: 10,buttonColor: Colors.yellow,),cardTheme: CardTheme(color: Colors.green,),textTheme: TextTheme(bodyText1: TextStyle(fontSize: 16),bodyText2: TextStyle(fontSize: 20),),),home: HYHomePage(),);}
}class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(""),),body: HYHomeContent(),floatingActionButton: FloatingActionButton(child: Icon(Icons.add),onPressed: () {},),bottomNavigationBar: BottomNavigationBar(items: [BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),BottomNavigationBarItem(icon: Icon(Icons.ac_unit), label: "首页"),],),);}
}class HYHomeContent extends StatefulWidget {@overrideState<HYHomeContent> createState() => _HYHomeContentState();
}class _HYHomeContentState extends State<HYHomeContent> {@overrideWidget build(BuildContext context) {return Theme(data: Theme.of(context).copyWith(primaryColor: Colors.purple,),child: Center(child: Column(children: [Text("Hello World",style: Theme.of(context).textTheme.bodyText2,),// Switch(value: true, onChanged: ),],),),);}
}

屏幕适配

import 'dart:ui';
class HYSizeFit {static double physicalWidth;static double physicalHeight;static double screenWidth;static double screenHeight;static double dpr;static double statueHeight;static double rpx;static double px;static void initialize() {//物理分辨率physicalWidth = window.physicalSize.width;physicalHeight = window.physicalSize.height;//获取dprdpr = window.devicePixelRatio;screenWidth = physicalWidth / dpr;screenHeight = physicalHeight / dpr;//状态栏高度statueHeight = window.padding.top / dpr;//计算rpx的大小rpx = screenWidth / 750;px = screenWidth / 750 * 2;}//适配IOSstatic double setRpx(double size) {return rpx * size;}static double setPx(double size) {return px * size;}
}

混合开发

Flutter想要一些原生的能力,相册、相机、

相机

3.实战

点击跳转


http://www.ppmy.cn/news/285037.html

相关文章

细说SSRF

目录 什么是SSRF形成原因容易出现SSRF的地方SSRF的危害脑图函数file_get_contents()fsockopen()curl_exec() 协议 漏洞检测常用绕过方式限制为http://www.xxx.com 域名时&#xff08;利用&#xff09;限制请求IP不为内网地址限制请求只为http协议利用[::]利用句号利用特殊地址利…

面试准备知识

信息收集 假如给你一个网站你怎么去渗透 步骤 首先看是什么类型的网站&#xff0c;大型网站可以去天眼查等查询法人股份等信息&#xff0c;小型网站可以查询使用了哪类建站系统。 whois信息查询 获取注册者邮箱姓名电话等 查询服务器旁站及子域名站点&#xff0c;因为主站一…

细说——SSRF

目录 什么是SSRF形成原因容易出现SSRF的地方SSRF的危害脑图SSRF相关函数和协议函数file_get_contents()fsockopen()curl_exec() 协议 漏洞检测常用绕过方式限制为http://www.xxx.com 域名时&#xff08;利用&#xff09;限制请求IP不为内网地址限制请求只为http协议利用[::]利用…

变电站综合自动化系统是将变电站内的二次设备经过功能的组合和优化设计

1.概述 本次建设内容包括&#xff1a;危险废物处理中心、有机废弃物处理中心、配套建设园区污水处理厂和园区管理中心等&#xff0c;该建设内容包括了安庆市静脉产业园项目红线范围内得所有固体废弃物处理子项目&#xff0c;以及园区红线范围内、外为园区配套的市政设施。全厂共…

变电站综合自动化系统如何提高综合性自动化功能?

安科瑞变电站综合自动化系统在安庆市静脉产业园应用 安科瑞 崔远航摘 要 变电站综合自动化系统是将变电站内的二次设备经过功能的组合和优化设计&#xff0c;利用计算机技术、通信技术、信号处理技术&#xff0c;实现对全变电站的主要设备和输、配电线路的自动监视、测量、控…

安科瑞变电站综合自动化系统 在安庆市静脉产业园应用

1.概述 静脉产业&#xff0c;这一概念最早由日本学者提出&#xff0c;专家们形象地将废弃物转换为再生资源的行业称为“静脉产业”——因其变废为宝&#xff0c;循环利用&#xff0c;如同将含有较多二氧化碳的血液送回心脏的静脉。安庆市静脉产业园是为创建安庆市经济健康持续 …

变电站综合自动化系统的选型与应用

摘 要&#xff1a;变电站综合自动化系统是将变电站内的二次设备经过功能的组合和优化设计&#xff0c;利用先进的计算机技术、通信技术、信号处理技术&#xff0c;实现对全变电站的主要设备和输、配电线路的自动监视、测量、控制、保护、并与上级调度通信的综合性自动化功能。为…

简析Acrel-1000安科瑞变电站综合自动化系统选型与应用

王兰 安科瑞电气股份有限公司 上海嘉定 201801 摘 要&#xff1a;变电站综合自动化系统是将变电站内的二次设备经过功能的组合和优化设计&#xff0c;利用先进的计算机技术、通信技术、信号处理技术&#xff0c;实现对全变电站的主要设备和输、配电线路的自动监视、测量、控…