目录
6. animateto(double target, {duration? duration, curve curve = curves.linear})
7.animateback(double target, {duration? duration, curve curve = curves.linear})
8. addlistener(voidcallback listener)
10.addstatuslistener(animationstatuslistener listener)
11. removestatuslistener(animationstatuslistener listener)
前言
上一篇文章介绍了flutter中的隐式动画的用法。
我们会发现隐式动画使用起来非常的方便,我们只需要设置动画的旧值变化之后的值,flutter会帮助我们完整动画的中间过程。flutter中隐式动画的实现是全自动的。
今天我们介绍下flutter中的显式动画。
一、定义
在flutter中,显式动画(explicit animations)指的是那些需要你手动控制动画过程的动画。显式动画提供了更多的控制权,但也需要更多的代码和管理。显式动画通常涉及到以下几个核心组件:
- animationcontroller
- animation
- tween
- listeners
- builders
核心组件的详解如下:
1.animationcontroller
animationcontroller是 flutter 动画框架的核心部分之一,用于控制动画的播放、停止、前进、倒退等。它提供了丰富的 api 来管理和控制动画的行为。下面是 animationcontroller的一些常用 api 及其解释:
1.常用属性
1. value
当前动画的值。可以是 `double` 类型,表示动画当前的进度。
2. status
当前动画的状态,是animationstatus枚举类型,可能的值有dismissed、forward、reverse 和 completed。
3. duration
动画的时长。
4. upperbound和 lowerbound
动画的范围。
2.常用方法
1.forward
动画正向执行,从lowerbound到upperbound。
2.reverse
动画反向执行,从upperbound到lowerbound
3.repeat
重复执行动画,可以指定周期和是否反向。
4.stop
停止动画。
5. reset
重置动画到 `lowerbound`,并停止动画。
6. animateto(double target, {duration? duration, curve curve = curves.linear})
动画执行到指定值。
7.animateback(double target, {duration? duration, curve curve = curves.linear})
动画反向执行到指定值。
8. addlistener(voidcallback listener)
添加监听器,每次动画值改变时调用。
9. removelistener(voidcallback listener)
移除监听器。
10.addstatuslistener(animationstatuslistener listener)
添加状态监听器,动画状态改变时调用。
11. removestatuslistener(animationstatuslistener listener)
移除状态监听器。
2.animation
在 flutter 中,显式动画需要开发者手动管理动画的每个步骤,其中 animation 类是核心组件之一。animation 类本身是一个抽象类,它定义了动画的当前值和状态,并且可以被监听以响应动画的变化。通过 animation 类,开发者可以访问动画的值并将其应用到 ui 元素上。
在实际做动画的过程中,我们会用到各种各样的animation。例如我们做缩放动画的时候,animation的类型为double类型,渐变动画的时候,animation可以表示颜色的动画,平移动画的时候,animation可以表示平移的大小。
3.tween
定义动画的开始和结束值。常见的有 tween<double>、colortween 等。
4.listeners
通过 addlistener 和 addstatuslistener 可以监听动画的每一帧和动画状态的变化。
5.builders
通过 animatedbuilder 或 custompainter 等将动画值应用到ui上。
二、常见的显示动画组件
显示动画都以transition结尾。常见的显示动画有rotateanimation动画、fadetransition、scaletransition、slidetransition、animatedicon。在显示动画中,我们通过animatedcontroller控制动画的开始、暂停、重置、跳转、倒播等。
1.rotationtransition
rotationtransition主要用来做旋转动画。
我们以下面的效果为例,看看如何使用rotationtransition动画。
图1.rotationtransition动画
我们要做一个不停旋转的flutterlogo。
首先我们设置flutterlogo的大小为60。
我们要做一个不停旋转的显式动画,因此我们需要再flutterlogo的外面使用rotationtransition包裹起来。
代码如下:
@override
widget build(buildcontext context) {
return scaffold(
appbar: appbar(
title: const text('rotateanimation动画'),
),
body: center(
child: rotationtransition(
turns: controller,
child: const flutterlogo(
size: 60,
),
),
),
);
}
我们看一下rotatintransition的定义:
const rotationtransition({
super.key,
required animation<double> turns,
super.alignment = alignment.center,
super.filterquality,
super.child,
}) : super(animation: turns, ontransform: _handleturnsmatrix);
这里必须要传递animationcontroller对象。因此我们在定义animationcontroller。
为了让程序和手机的刷新频率保持一致,我们的stateful后面要实现singletickerproviderstatemixin。
代码如下:
class _rotateanimationdemosstate extends state<rotateanimationdemos> with singletickerproviderstatemixin{
// 定义animationcontroller
late animationcontroller controller;
}
然后我们widget的初始化方法中,初始化我们的animationcontroller。
这里我们设置下动画的时长,vsync参数传this。表示当前app和手机刷新的频率保持一致。
//初始化 animationcontroller
@override
void initstate() {
super.initstate();
//vsync: 让程序和手机的刷新频率统一
controller = animationcontroller(duration: const duration(seconds: 3), vsync: this);
}
ok.到这里之后,完整的代码如下:
import 'package:flutter/material.dart';
class rotateanimationdemos extends statefulwidget {
const rotateanimationdemos({super.key});
@override
state<rotateanimationdemos> createstate() => _rotateanimationdemosstate();
}
class _rotateanimationdemosstate extends state<rotateanimationdemos>
with singletickerproviderstatemixin {
// 定义animationcontroller
late animationcontroller controller;
//初始化 animationcontroller
@override
void initstate() {
super.initstate();
//vsync: 让程序和手机的刷新频率统一
controller =
animationcontroller(duration: const duration(seconds: 3), vsync: this);
}
@override
widget build(buildcontext context) {
return scaffold(
appbar: appbar(
title: const text('rotateanimation动画'),
),
body: center(
child: rotationtransition(
turns: controller,
child: const flutterlogo(
size: 60,
),
),
),
);
}
}
运行代码之后,页面加载出来了,但是flutterlogo没有转起来。
因为显式动画是手动控制动画的播放,因此我们还需要手动调用下animationcontroller的repeat方法。
//初始化 animationcontroller
@override
void initstate() {
super.initstate();
//vsync: 让程序和手机的刷新频率统一
controller = animationcontroller(duration: const duration(seconds: 3), vsync: this)..repeat();
}
再次运行,就发现flutterlogo旋转起来了。
完整代码如下:
import 'package:flutter/material.dart';
class rotateanimationdemos extends statefulwidget {
const rotateanimationdemos({super.key});
@override
state<rotateanimationdemos> createstate() => _rotateanimationdemosstate();
}
class _rotateanimationdemosstate extends state<rotateanimationdemos>
with singletickerproviderstatemixin {
// 定义animationcontroller
late animationcontroller controller;
//初始化 animationcontroller
@override
void initstate() {
super.initstate();
//vsync: 让程序和手机的刷新频率统一
controller = animationcontroller(duration: const duration(seconds: 3), vsync: this)..repeat();
}
@override
widget build(buildcontext context) {
return scaffold(
appbar: appbar(
title: const text('rotateanimation动画'),
),
body: center(
child: rotationtransition(
turns: controller,
child: const flutterlogo(
size: 60,
),
),
),
);
}
}
上述调用了animationcontroller的repeat方法,animationcontroller还提供了forward、reverse、stop、reset等常用方法,它们的含义如下:
- forward:动画仅执行一次
- reverse:动画倒序执行一次
- stop:动画停止
- reset:动画重置
- repeat:重复的执行动画
如果感兴趣,可以逐个调用这些方法看看效果。
2.fadetransition
fadetransition用于制作透明度动画。
fadetransition和rotationtransition的用法基本差不多。
下面的例子中,展示了使用fadetransition制作动画的过程。
图2.fadetransition动画
完整代码如下:
import 'package:flutter/material.dart';
class fadeanimationdemos extends statefulwidget {
const fadeanimationdemos({super.key});
@override
state<fadeanimationdemos> createstate() => _fadeanimationdemosstate();
}
class _fadeanimationdemosstate extends state<fadeanimationdemos> with singletickerproviderstatemixin{
// 定义animationcontroller
late animationcontroller controller;
//初始化 animationcontroller
@override
void initstate() {
super.initstate();
//vsync: 让程序和手机的刷新频率统一
controller = animationcontroller(
duration: const duration(seconds: 1),
vsync: this,
lowerbound: 0.1,
upperbound: 1.0,
)..repeat();
}
@override
widget build(buildcontext context) {
return scaffold(
appbar: appbar(
title: const text('fadetransition动画'),
),
body: center(
child:fadetransition(
opacity: controller,
child: const flutterlogo(size: 200,),
),
),
);
}
}
3.scaletransition
scaletransition用于制作缩放动画,依然可以使用animationcontroller更加精准的控制动画的细节。
图3.缩放动画
完整代码如下:
import 'package:flutter/material.dart';
class scaletransitiondemos extends statefulwidget {
const scaletransitiondemos({super.key});
@override
state<scaletransitiondemos> createstate() => _scaletransitiondemosstate();
}
class _scaletransitiondemosstate extends state<scaletransitiondemos> with singletickerproviderstatemixin{
// 定义animationcontroller
late animationcontroller controller;
//初始化 animationcontroller
@override
void initstate() {
super.initstate();
//vsync: 让程序和手机的刷新频率统一
controller = animationcontroller(
duration: const duration(seconds: 1),
vsync: this,
lowerbound: 0.1,
upperbound: 1.0,
)..repeat();
}
@override
widget build(buildcontext context) {
return scaffold(
appbar: appbar(
title: const text('scaletransition动画'),
),
body: center(
child:scaletransition(
scale: controller,
child: container(
width: 100,
height: 100,
color: colors.deeppurpleaccent,
),
),
),
);
}
}
4.slidetransition
slidetransition用于做平移动画。
下图是使用slidetransition制作的平移动画。
图4.slidetransition动画
完整代码如下:
import 'package:flutter/material.dart';
class slidetransitiondemos extends statefulwidget {
const slidetransitiondemos({super.key});
@override
state<slidetransitiondemos> createstate() => _slidetransitiondemosstate();
}
class _slidetransitiondemosstate extends state<slidetransitiondemos> with singletickerproviderstatemixin{
// 定义animationcontroller
late animationcontroller controller;
//初始化 animationcontroller
@override
void initstate() {
super.initstate();
//vsync: 让程序和手机的刷新频率统一
controller = animationcontroller(
duration: const duration(seconds: 1),
vsync: this,
lowerbound: 0.1,
upperbound: 1.0,
)..repeat();
}
@override
widget build(buildcontext context) {
return scaffold(
appbar: appbar(
title: const text('slidetransition动画'),
),
body: center(
child:slidetransition(
position: controller.drive(tween(begin: const offset(0, 0), end: const offset(0.5, 0))),
child: const flutterlogo(size: 200,),
),
),
);
}
}
我们还可以使用animationcontroller的drive方法修改动画的初始值。
例如在下面的缩放动画代码中,开始的时候,长度和宽度都是从0.5倍开始,2倍结束。
部分代码如下:
center(
child:scaletransition(
scale: controller.drive(tween(begin: 0.5, end: 2.0)),
child: container(
width: 100,
height: 100,
color: colors.deeppurpleaccent,
),
),
)
还可以调用animationcontroller的chain方法叠加动画的曲线。
三、自定义显式动画
这里我们看一下如何自定义显式动画。
例如我们这里有一个透明度为0.9的container组件,代码如下:
import 'package:flutter/material.dart';
class customexplicitpage extends statefulwidget {
const customexplicitpage({super.key});
@override
state<customexplicitpage> createstate() => _customexplicitpagestate();
}
class _customexplicitpagestate extends state<customexplicitpage> with singletickerproviderstatemixin {
late animationcontroller _controller;
@override
void initstate() {
super.initstate();
_controller = animationcontroller(vsync: this);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
widget build(buildcontext context) {
return scaffold(
appbar: appbar(
title: const text('自定义显示动画'),
),
body: center(
child: opacity(
opacity: 0.9,
child: container(
alignment: alignment.center,
color: colors.deeppurpleaccent,
width: 250,
height: 250,
child: const text('hi',style: textstyle(fontsize: 24),),
),
),
),
);
}
}
我们看下如何使用animatedbuilder实现自定义显式动画。
首先我们把需要制作动画的widget的外层包裹一个animatedbuilder。builder函数内部返回要操作的widget,把animatedcontroller传给animatedbuilder的animation属性。
部分代码如下:
center(
child: animatedbuilder(
animation: _controller,
builder: (buildcontext context, widget? child) {
return opacity(
opacity: 0.9,
child: container(
alignment: alignment.center,
color: colors.deeppurpleaccent,
width: 250,
height: 250,
child: const text('hi',style: textstyle(fontsize: 24),),
),
);
},
),
)
然后调用animationcontroller的repeat方法,一个自定义的显式动画就实现了。
完整代码如下:
import 'package:flutter/material.dart';
class customexplicitpage extends statefulwidget {
const customexplicitpage({super.key});
@override
state<customexplicitpage> createstate() => _customexplicitpagestate();
}
class _customexplicitpagestate extends state<customexplicitpage> with singletickerproviderstatemixin {
late animationcontroller _controller;
@override
void initstate() {
super.initstate();
_controller = animationcontroller(vsync: this,duration: const duration(seconds: 2))..repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
widget build(buildcontext context) {
return scaffold(
appbar: appbar(
title: const text('自定义显示动画'),
),
body: center(
child: animatedbuilder(
animation: _controller,
builder: (buildcontext context, widget? child) {
return opacity(
opacity: _controller.value,
child: container(
alignment: alignment.center,
color: colors.deeppurpleaccent,
width: 250,
height: 250,
child: const text('hi',style: textstyle(fontsize: 24),),
),
);
},
),
),
);
}
}
完整的效果如下:
图5.自定义显式动画
四、参考文章
1.教程 | flutter 中文文档 - flutter 中文开发者网站 - flutter
发表评论