Flutter 内置动画
上面的那些一般用起来不是很方便,即便是 AnimatedBuilder 还是要指定参与动画变化的 widget 属性,为了进一步方便我们,官方在 AnimatedWidget 的基础上封装了下面这些内置动画库,就是 android 中的那些,当然更多一些:
SlideTransition- 自身倍数位移动画AlignTransition- 没找到资料PositionedTransition- 缩放动画,限定父布局只能是 stackFadeTransition- 透明度动画ScaleTransition- 缩放动画,这个是 android 中的那种缩放动画,可以指定中心点SizeTransition- 宽高动画,限制是每次只能执行一个维度的动画,宽和高一起不行,那就是缩放动画了RotationTransition- 旋转动画,特点是其数值是 0-1 之间的,旋转90度 = 0.25
这些 transition 的特点就是,用一个参数接受 animation 动画,child 写 widget
FadeTransition
FadeTransition 是透明度动画,参数就是一个 opacity 指定动画,child 写 widget 就没了
animationController = AnimationController(
duration: Duration(milliseconds: 300),
vsync: this,
);
animation = CurvedAnimation(parent: animationController, curve: Curves.bounceInOut);
animation = Tween(begin: 0.0, end: 1.0).animate(animationController);
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FadeTransition(
opacity: animation,
child: Container(
margin: EdgeInsets.only(bottom: 20),
width: 300,
height: 300,
color: Colors.blueAccent,
),
),
RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
],
),
);
}
}
SlideTransition
SlideTransition 位移动画,使用 offset 来承载x,y轴数据。需要注意的是 Offset(0.0, 0.0) 中的数值都是 倍数,也就是说 SlideTransition 只支持按 widget 本身长宽的倍数位移,不支持具体的数值的位移操作
void initState() {
super.initState();
animationController = AnimationController(
duration: Duration(milliseconds: 300),
vsync: this,
);
animation = Tween(begin: Offset(0.0, 0.0), end: Offset(1.0, 1.0))
.animate(animationController);
}
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SlideTransition(
position: animation,
child: Container(
margin: EdgeInsets.only(bottom: 20),
width: 100,
height: 100,
color: Colors.blueAccent,
),
),
RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
],
),
);
}
PositionedTransition
PositionedTransition 缩放动画,必须在 stack 中使用,其缩放数值使用 RelativeRect 包裹,前后变化的是距 stack 父布局左上右下4个角的距离:
animation = RelativeRectTween(
begin: RelativeRect.fromLTRB(0, 0, 0, 0),
end: RelativeRect.fromLTRB(50, 200, 50, 200))
.animate(animationController);
大家看个图:
基本上就是这个思路了,限制有一些,下面是例子代码,不是上面 gif 的代码:
Animation<RelativeRect> animation;
AnimationController animationController;
CurvedAnimation curve;
void initState() {
super.initState();
animationController = AnimationController(
duration: Duration(milliseconds: 300),
vsync: this,
);
curve = CurvedAnimation(parent: animationController, curve: Curves.bounceInOut);
animation = RelativeRectTween(
begin: RelativeRect.fromLTRB(0, 0, 0, 0),
end: RelativeRect.fromLTRB(50, 200, 50, 200))
.animate(curve);
}
Widget build(BuildContext context) {
return Center(
child: Stack(
children: <Widget>[
PositionedTransition(
rect: animation,
child: Container(
width: 300,
height: 300,
color: Colors.blueAccent,
),
),
Positioned(
top: 20,
left: 20,
child: RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
),
],
),
);
}
最后大家注意啊,RelativeRectTween begin 的数值能影响 widget 初始显示时的宽高大小
ScaleTransition
ScaleTransition 这才是传统的缩放动画,使用 alignment: Alignment.topLeft 指定缩放中心点
Animation<double> animation;
AnimationController animationController;
CurvedAnimation curve;
@override
void initState() {
super.initState();
animationController = AnimationController(
duration: Duration(milliseconds: 300),
vsync: this,
);
curve =
CurvedAnimation(parent: animationController, curve: Curves.bounceInOut);
animation = Tween(
begin: 1.0,
end: 0.3,
).animate(curve);
}
Widget build(BuildContext context) {
return Center(
child: Stack(
children: <Widget>[
ScaleTransition(
alignment: Alignment.topLeft,
scale: animation,
child: Container(
width: 300,
height: 300,
color: Colors.blueAccent,
),
),
Positioned(
top: 20,
left: 20,
child: RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
),
],
),
);
}
SizeTransition
SizeTransition 宽高动画,限制是每次只能设定一个维度,不能宽和高一起,优点是宽高的变化不会引起内容的变形
axis: Axis.horizontal 就是指定动画作用与宽还是高
Widget build(BuildContext context) {
return Center(
child: Stack(
children: <Widget>[
SizeTransition(
axis: Axis.horizontal,
sizeFactor: animation,
child: Container(
color: Colors.blueAccent,
child: Icon(Icons.access_alarm, size: 300),
),
),
Positioned(
top: 20,
left: 20,
child: RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
),
],
),
);
}
RotationTransition
RotationTransition 旋转动画,特点是其数值是 0-1 之间的,旋转90度 = 0.25,依然可以设置原点
animation = Tween(
begin: 0.0,
end: 0.25,
).animate(curve);
Widget build(BuildContext context) {
return Center(
child: Stack(
children: <Widget>[
RotationTransition(
turns: animation,
alignment: Alignment.center,
child: Container(
color: Colors.blueAccent,
child: Icon(Icons.access_alarm, size: 300),
),
),
Positioned(
top: 20,
left: 20,
child: RaisedButton(
child: Text("放大"),
onPressed: () {
animationController?.forward();
},
),
),
],
),
);
}