前语
flutter
开发中难免会碰到一些动画操作,且运用率最高的动画基本上都是根底动画,本篇文章首要讲解一些常用的根底动画的运用
ps
:假如下面的根底动画不太满足要求,那么能够选用自定义的方法,其他地方应该有,动画,即动起来的画面,必要的时候,咱们能够合作定时器(requestAnimationFrame
)更新视图,也能完成咱们的动画作用,便是作用或许不是那么抱负,一般情况下根底动画也够用了
事例demo
动画
常用的根底动画首要分为隐式动画
、显式动画
ps
:运用时需求留意特点更新时会对布局的影响,合理挑选布局,防止因为参加动画造成不相同的作用
隐式动画
咱们更改某些组件特点的一起,会自动触发组件躲藏的特点动画,因而此类动画被称为隐式动画
,其在其他平台也应该常听到,运用很便利,但无法阻挠动画的暂停和持续
常见的隐式动画控件有:AnimatedPositioned
、AnimatedContainer
、AnimatedRotation
、AnimatedScale
、AnimatedOpacity
更新缩放份额 AnimatedScale
double scale = 1;
AnimatedScale(
duration: const Duration(seconds: 2),
scale: scale,
child: Container(
color: Colors.green,
width: 80,
height: 80,
child: TextButton(
onPressed: () {
if (scale > 1) {
setState(() {
scale = 1;
});
}else {
setState(() {
scale = 2;
});
}
},
child: const Text(
'缩放动画',
style: TextStyle(color: Colors.white),
),
),
),
),
更新透明度 AnimatedOpacity
double opacity = 1;
AnimatedOpacity(
duration: const Duration(seconds: 2),
opacity: opacity,
child: Container(
color: Colors.green,
width: 100,
height: 100,
child: TextButton(
onPressed: () {
if (opacity < 1) {
setState(() {
opacity = 1;
});
}else {
setState(() {
opacity = 0.1;
});
}
},
child: const Text(
'缩放动画',
style: TextStyle(color: Colors.white),
),
),
),
),
旋转 AnimatedRotation
旋转参数比较特殊,与其说特殊不如说失常,往常的都是填写视点、弧度等,这儿的是填写百分比
,且为占用一圈的百分比
,例如:1 则为顺时针 360,半圈便是 0.5
double turns = 0; //旋转视点占一圈的百分比
AnimatedRotation(
//旋转占一圈的百分比,360便是1,半圈便是 0.5,很奇怪是吧,哈哈,公式是这样的
//即:旋转 90,便是 1/4 圈,即 0.25圈
turns: turns, //旋转占一圈的百分比
duration: const Duration(seconds: 2),
child: Container(
color: Colors.green,
width: 100,
height: 100,
child: TextButton(
onPressed: () {
if (turns > 0) {
setState(() {
turns = 0;
});
} else {
setState(() {
//旋转 90,便是 1/4 圈,即 0.25圈
turns = 0.25;
});
}
},
child: const Text(
'旋转动画',
style: TextStyle(color: Colors.white),
),
),
),
),
更新方位等组合动画
通过上面也能够看到,隐式动画组件基本上和一般组件相同,只不过前面加上了 Animated
,因而咱们能够像更新一般组件相同运用它们,一起他们也支撑一起更新多个特点,即构成组合动画
double top = 0;
double left = 0;
double width = 80;
double height = 80;
Color color = Colors.green;
//假如打开Animated最初会发现很多类似组件,例如:Padding等,这儿面Container也改变了色彩等特点,也都支撑
//依据名字对应根底组件就知道动画是干什么的,很简略,就不多介绍了
AnimatedPositioned(
duration: const Duration(seconds: 2),
curve: Curves.easeInOut,
left: left,
top: top,
child: AnimatedContainer(
duration: const Duration(seconds: 2),
curve: Curves.easeInOut,
color: color,
width: width,
height: height,
child: TextButton(
onPressed: () {
if (left > 0) {
setState(() {
color = Colors.green;
left = 0;
top = 0;
width = 80;
height = 80;
});
} else {
setState(() {
color = Colors.yellow;
left = 160;
top = 400;
width = 160;
height = 160;
});
}
},
child: const Text(
'位移大小动画',
style: TextStyle(color: Colors.white),
),
),
),
),
显式动画
显式动画,是依据 Animation
相关动画功用模块构成的动画,支撑暂停和持续,能够更好的操控动画的周期变化
AnimationController
:动画操控器,能够操控方向,暂停,指定到某个值等,详细的能够点击去查看,需求继承 SingleTickerProviderStateMixin
Animation<T>
:动画事情,用于更新动画某个特点
更新缩放
class _ScaleTransitionWidgetState extends State<ScaleTransitionWidget> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
//操控动画
_controller = AnimationController(vsync: this, duration: const Duration(seconds: 1));
//设置补间
_animation = Tween<double>(
begin: 1,
end: 4,
).animate(_controller);
//能够设置补间动画动画的动画特性或许运动曲线
// .animate(
// CurvedAnimation(parent: _controller, curve: Curves.easeIn),
// );
//正向履行动画
_controller.forward();
//反向履行动画
_controller.reverse();
//停止动画
_controller.stop();
//动画是否履行完毕
_controller.isCompleted;
}
//直接更新缩放的显式动画组件
ScaleTransition(
scale: _animation,
child: Container(
color: Colors.green,
width: 80,
height: 80,
child: TextButton(
onPressed: () {
if (_controller.isCompleted) {
_controller.reverse();
}else {
_controller.forward();
}
},
child: const Text(
'缩放动画',
style: TextStyle(color: Colors.white),
),
),
),
),
更新透明度
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
//操控动画
_controller = AnimationController(vsync: this, duration: const Duration(seconds: 1));
//设置补间
_animation = Tween<double>(
begin: 1,
end: 0.1,
).animate(_controller);
}
FadeTransition(
opacity: _animation,
child: Container(
color: Colors.green,
width: 120,
height: 120,
child: TextButton(
onPressed: () {
if (_controller.isCompleted) {
_controller.reverse();
}else {
_controller.forward();
}
},
child: const Text(
'fade动画',
style: TextStyle(color: Colors.white),
),
),
),
),
旋转
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
//操控动画
_controller = AnimationController(vsync: this, duration: const Duration(seconds: 1));
//设置补间
_animation = Tween<double>(
begin: 0,
end: 0.25,
).animate(_controller);
}
RotationTransition(
turns: _animation,
child: Container(
color: Colors.green,
width: 120,
height: 120,
child: TextButton(
onPressed: () {
if (_controller.isCompleted) {
_controller.reverse();
}else {
_controller.forward();
}
},
child: const Text(
'旋转动画',
style: TextStyle(color: Colors.white),
),
),
),
),
组合动画(显式动画中推荐)
看了上面的 Transition
操作,感觉也不是那么好用,功用单一,代码还多了,且有些改换操作还贼难用,下面有一个显式动画中比较常用的组合控件,能够防止运用上面的一些列 Transition
,且愈加通用
AnimatedBuilder
:组合动画中比较常用的组件,能够防止运用 Transition
系列,其合作根底动画类,运用一般的组件 UI 即可完成动画作用,且不仅仅是组合动画,单个动画也能够哈
如下所示,咱们定义多个 Animation
事情,然后应用到组件中即可构成组合动画了(单个便是用一个 Animation 即可)
class _CombinAnimatedWidgetState extends State<CombinAnimatedWidget> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _widthAnimation;
late Animation<double> _opacityAnimation;
late Animation<BorderRadius> _borderRadiusAnimation;
late Animation<double> _borderWidthAnimation;
@override
void initState() {
super.initState();
//操控动画
_controller = AnimationController(vsync: this, duration: const Duration(seconds: 1));
//设置补间
_widthAnimation = Tween<double>(
begin: 100,
end: 240,
).animate(_controller);
_opacityAnimation = Tween<double>(
begin: 1,
end: 0.6,
).animate(_controller);
_borderRadiusAnimation = Tween<BorderRadius>(
begin: const BorderRadius.all(Radius.circular(0)),
end: const BorderRadius.all(Radius.circular(120)),
).animate(_controller);
_borderWidthAnimation = Tween<double>(
begin: 1,
end: 20,
).animate(_controller);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("组合动画"),
),
body: Center(
child: GestureDetector(
onTap: () {
if (_controller.isCompleted) {
_controller.reverse();
}else {
_controller.forward();
}
},
//咱们的动画组件,内部能够运用咱们常用的控件
child: AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget? child) {
return Opacity(
opacity: _opacityAnimation.value,
child: Container(
width: _widthAnimation.value,
height: _widthAnimation.value,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: _borderRadiusAnimation.value,
border: Border.all(
width: _borderWidthAnimation.value,
color: Colors.cyanAccent
),
),
),
);
},
),
),
),
);
}
}
最后
根底动画,便是这么简略,运用时需求留意别被外部布局挤压等影响,以造成动画作用不正常的问题,一般运用 Stack 布局作用更好