Flutter开发(十五)Flutter动画基础
1.哪些类型动画
2.添加动画
3.为动画添加监听器
4.AnimatedWidget 与 AnimatedBuilder
5.Hero动画
1.哪些类型动画
大概分为两类:基于 tween 和基于物理。
tween 动画就是补间动画,定义开始点和结束点、时间线和定义转化时间和速度的曲线。
基于物理的动画:就是模拟真实世界。比如扔个球,会做抛物线,然后弹了几下。
2.添加动画
几个常见类:
Animation : 动画库核心,生成指导动画的值。
CurvedAnimation : Animation 子类,将过程抽象为一个非线性曲线。
AnimationController : Animation 子类,管理 Animation。
Tween : 在正在执行动画的对象所使用的数据范围之间生成值。比如红到绿,它可以自动生成过程。
动画的几个状态方法:
forward() 启动动画
reverse({double from}) 倒放动画
reset() 重置动画
stop({bool canceled = true}) 停止动画
动画使用大概步骤:
① 创建 AnimationController ,指定动画时间;
② 创建 Tween ,传入区间大小变化,传入控制器 AnimationController ;
③ 添加动画变化监听器,类型是 double 类型,每回调一次就会用 setState() 刷新一次页面;
④ 添加动画状态监听器,来监听动画的状态:开始和停止等,利用 setState() 刷新页面;
⑤ 添加一个图片,动态设置它的大小;
示例代码如下,大概就是一个图标从宽高为0两秒内变成宽高为300的过程:
-
void main() {
-
runApp(MyApp());
-
}
-
-
class MyApp extends StatefulWidget {
-
@override
-
_MyHomePageState createState() => _MyHomePageState();
-
}
-
-
class _MyHomePageState extends State<MyApp>
-
with SingleTickerProviderStateMixin {
-
late Animation<double> animation;
-
late AnimationController controller;
-
//设置了一个初始状态。
-
late AnimationStatus animationStatus = AnimationStatus.reverse;
-
late double animationValue = 0;
-
-
@override
-
void initState() {
-
super.initState();
-
// ① 创建 AnimationController ,指定动画时间;
-
// 其中 vsync: this 表示该动画被别的页面遮挡,防止消耗不必要的资源。
-
controller =
-
AnimationController(duration: const Duration(seconds: 2), vsync: this);
-
// ② 创建 Tween ,传入区间大小变化,传入控制器 AnimationController ;
-
animation = Tween<double>(begin: 0, end: 300).animate(controller)
-
// ③ 添加动画变化监听器,类型是 double 类型,每回调一次就会用 setState() 刷新一次页面;
-
..addListener(() {
-
setState(() {
-
animationValue = animation.value;
-
});
-
})
-
// ④ 添加动画状态监听器,来监听动画的状态:开始和停止等,利用 setState() 刷新页面;
-
..addStatusListener((AnimationStatus status) {
-
setState(() {
-
animationStatus = status;
-
});
-
});
-
}
-
-
@override
-
Widget build(BuildContext context) {
-
return Container(
-
margin: EdgeInsets.only(top: 100),
-
child: Column(
-
children: [
-
//点击监听
-
GestureDetector(
-
onTap: () {
-
//重置动画
-
controller.reset();
-
//动画开始
-
controller.forward();
-
},
-
child: Text(
-
'Start',
-
textDirection: TextDirection.ltr,
-
),
-
),
-
Text('State:' animationStatus.toString(),
-
textDirection: TextDirection.ltr),
-
Text('Value:' animationValue.toString(),
-
textDirection: TextDirection.ltr),
-
// ⑤ 添加一个图片,动态设置它的大小;
-
Container(
-
height: animation.value,
-
width: animation.value,
-
child: FlutterLogo(),
-
)
-
],
-
));
-
}
-
-
@override
-
void dispose() {
-
controller.dispose();
-
super.dispose();
-
}
-
}
3.为动画添加监听器
上面代码中已经添加了两个监听:
..addListener 动画的值发生变化被调用
..addStatusListener 动画状态发生变化被调用
4.AnimatedWidget 与 AnimatedBuilder
上面代码中,必须得添加动画的变化监听,然后不停调用 setState ,才能显示动画。AnimatedWidget 可以简化这一个操作,AnimatedWidget 很常用,它的作用就是简化动画。
简化完成的代码:
-
import 'package:flutter/material.dart';
-
import 'package:flutter/animation.dart';
-
-
void main() {
-
runApp(MyApp());
-
}
-
-
class MyApp extends StatefulWidget {
-
-
_MyHomePageState createState() => _MyHomePageState();
-
}
-
-
class _MyHomePageState extends State<MyApp>
-
with SingleTickerProviderStateMixin {
-
late Animation<double> animation;
-
late AnimationController controller;
-
-
-
void initState() {
-
super.initState();
-
// ① 创建 AnimationController ,指定动画时间; 其中 vsync: this 表示该动画被别的页面遮挡,防止消耗不必要的资源。
-
controller =
-
AnimationController(duration: const Duration(seconds: 2), vsync: this);
-
// ② 创建 Tween ,传入区间大小变化,传入控制器 AnimationController ;
-
animation = Tween<double>(begin: 0, end: 300).animate(controller);
-
controller.forward();
-
}
-
-
-
Widget build(BuildContext context) {
-
return new AnimatedLogo(animation: animation);
-
}
-
-
-
void dispose() {
-
controller.dispose();
-
super.dispose();
-
}
-
}
-
-
class AnimatedLogo extends AnimatedWidget {
-
AnimatedLogo({Key? key, required Animation<double> animation})
-
: super(key: key, listenable: animation);
-
-
-
Widget build(BuildContext context) {
-
final Animation<double> animation = listenable as Animation<double>;
-
return new Center(
-
child: new Container(
-
margin: new EdgeInsets.symmetric(vertical: 10.0),
-
height: animation.value,
-
width: animation.value,
-
child: new FlutterLogo(),
-
)
-
);
-
}
-
}
AnimatedBuilder 是用于构建动画的通用 widget,作用是拆分动画,可以将动画和 widget 进行分离。
将上面的动画拆分为三块:显示图片,定义动画,渲染动画效果。
示例代码:
-
void main() {
-
runApp(MyApp());
-
}
-
-
class MyApp extends StatefulWidget {
-
-
_MyHomePageState createState() => _MyHomePageState();
-
}
-
-
class _MyHomePageState extends State<MyApp>
-
with SingleTickerProviderStateMixin {
-
late Animation<double> animation;
-
late AnimationController controller;
-
-
-
void initState() {
-
super.initState();
-
// ① 创建 AnimationController ,指定动画时间; 其中 vsync: this 表示该动画被别的页面遮挡,防止消耗不必要的资源。
-
controller =
-
AnimationController(duration: const Duration(seconds: 2), vsync: this);
-
// ② 创建 Tween ,传入区间大小变化,传入控制器 AnimationController ;
-
animation = Tween<double>(begin: 0, end: 300).animate(controller);
-
controller.forward();
-
}
-
-
-
Widget build(BuildContext context) {
-
return GrowTransition(child: LogoWidget(),animation: animation);
-
}
-
-
-
void dispose() {
-
controller.dispose();
-
super.dispose();
-
}
-
}
-
-
class GrowTransition extends StatelessWidget {
-
GrowTransition({required this.child, required this.animation});
-
-
final Widget child;
-
final Animation<double> animation;
-
-
-
Widget build(BuildContext context){
-
return Center(
-
child: AnimatedBuilder(
-
animation: animation,
-
builder: (context, child) {
-
return Container(
-
height: animation.value,
-
width: animation.value,
-
child: child,
-
);
-
},
-
child: child,
-
),
-
);
-
}
-
}
-
-
class LogoWidget extends StatelessWidget {
-
-
Widget build(BuildContext context) {
-
return new Container(
-
margin: EdgeInsets.symmetric(vertical: 10),
-
child: FlutterLogo(),
-
);
-
}
-
}
5.Hero动画
从第一个页面跳转到第二个页面,并且两个页面都有这个图标,可以用这个动画来实现。实现一个飞入的感觉。
效果可以看官网:Flutter Hero动画 - Flutter中文网
示例代码,下面代码我把 timeDilation = 5.0; 注释了,加上这个报错,不知道为什么,报错信息是
-
Error: Setter not found: 'timeDilation'.
-
timeDilation = 5.0;
有知道的小伙伴告诉我一下原因吧~
下面是完整代码:
-
-
import 'package:flutter/material.dart';
-
import 'package:flutter/scheduler.dart' show timeDilation;
-
-
-
void main() {
-
runApp(MaterialApp(home: HeroAnimation()));
-
}
-
-
class PhotoHero extends StatelessWidget {
-
const PhotoHero({ Key? key,required this.photo,required this.onTap, required this.width }) : super(key: key);
-
-
final String photo;
-
final VoidCallback onTap;
-
final double width;
-
-
Widget build(BuildContext context) {
-
return new SizedBox(
-
width: width,
-
child: new Hero(
-
tag: photo,
-
child: new Material(
-
color: Colors.transparent,
-
child: new InkWell(
-
onTap: onTap,
-
child: new Image.asset(
-
photo,
-
fit: BoxFit.contain,
-
),
-
),
-
),
-
),
-
);
-
}
-
}
-
-
class HeroAnimation extends StatelessWidget {
-
-
Widget build(BuildContext context) {
-
// timeDilation = 5.0;
-
-
return new Scaffold(
-
appBar: new AppBar(
-
title: const Text('Basic Hero Animation'),
-
),
-
body: new Center(
-
child: new PhotoHero(
-
photo: 'assets/images/my_icon.jpg',
-
width: 300.0,
-
onTap: () {
-
Navigator.of(context).push(new MaterialPageRoute<void>(
-
builder: (BuildContext context) {
-
return new Scaffold(
-
appBar: new AppBar(
-
title: const Text('Flippers Page'),
-
),
-
body: new Container(
-
// The blue background emphasizes that it's a new route.
-
color: Colors.lightBlueAccent,
-
padding: const EdgeInsets.all(16.0),
-
alignment: Alignment.topLeft,
-
child: new PhotoHero(
-
photo: 'assets/images/my_icon.jpg',
-
width: 100.0,
-
onTap: () {
-
Navigator.of(context).pop();
-
},
-
),
-
),
-
);
-
}
-
));
-
},
-
),
-
),
-
);
-
}
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfkekgg
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
photoshop蒙版画笔没反应怎么办
PHP中文网 06-24