# ScaleTransition
- 缩放动画
ScaleTransition(
scale: Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: controller!,
curve: Curves.fastOutSlowIn),
),
child: Container(
width: 200,
height: 200,
color: Colors.white,
child: Image.network(
"https://img1.baidu.com/it/u=610017077,4160995221&fm=11&fmt=auto&gp=0.jpg",
),
),
),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# RotationTransition
- 旋转加缩放
RotationTransition(
turns: Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: controller!,
curve: Curves.fastOutSlowIn),
),
child: Container(
width: 200,
height: 200,
color: Colors.white,
child: Image.network(
"https://img1.baidu.com/it/u=610017077,4160995221&fm=11&fmt=auto&gp=0.jpg",
),
),
),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# SlideTransition
- 左右滑动动画过渡
SlideTransition(
position: Tween<Offset>(begin: Offset(-1.0, 0.0),end: Offset(0.0, 0.0)).animate(CurvedAnimation(parent: animation1,curve: Curves.fastOutSlowIn)),
child: Container(
width: 200,
height: 200,
color: Colors.white,
child: Image.network(
"https://img1.baidu.com/it/u=610017077,4160995221&fm=11&fmt=auto&gp=0.jpg",
),
),
),
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# DefaultTextStyleTransition
- 文字样式过渡动画
const DefaultTextStyleTransition({
Key? key,
required Animation<TextStyle> style,
required this.child,
this.textAlign,
this.softWrap = true,
this.overflow = TextOverflow.clip,
this.maxLines,
}) : assert(style != null),
assert(child != null),
super(key: key, listenable: style);
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# AlignTransition
- 位置偏移过渡动画
const AlignTransition({
Key? key,
required Animation<AlignmentGeometry> alignment,
required this.child,
this.widthFactor,
this.heightFactor,
}) : assert(alignment != null),
assert(child != null),
super(key: key, listenable: alignment);
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# DecoratedBoxTransition
- 装饰盒过渡动画,可以给它的Decoration不同属性使用动画
const DecoratedBoxTransition({
Key? key,
required this.decoration,
this.position = DecorationPosition.background,
required this.child,
}) : assert(decoration != null),
assert(child != null),
super(key: key, listenable: decoration);
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
///举例
Animation<Decoration> animationTest;
AnimationController controllerTest;
controllerTest = new AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animationTest = DecorationTween(
begin: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(0.0)),
color: Colors.red
),
end: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
color: Colors.green
)
).animate(controllerTest);
DecoratedBoxTransition(
decoration: animationTest,
child: Container(
width: 100.0,
height: 100.0,
)
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# RelativePositionedTransition
- 相对定位过渡动画
const RelativePositionedTransition({
Key? key,
required Animation<Rect> rect,
required this.size,
required this.child,
}) : assert(rect != null),
assert(size != null),
assert(child != null),
super(key: key, listenable: rect);
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# PositionedTransition
- Positioned 位置变动过渡
const PositionedTransition({
Key? key,
required Animation<RelativeRect> rect,
required this.child,
}) : assert(rect != null),
super(key: key, listenable: rect);
1
2
3
4
5
6
2
3
4
5
6
///举例
Animation<RelativeRect> animation;
AnimationController controller;
controller = new AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = RelativeRectTween(
begin: RelativeRect.fromLTRB(200.0, 200.0, 200.0, 200.0),
end: RelativeRect.fromLTRB(20.0, 20.0, 20.0, 20.0))
.animate(controller);
Stack(children: <Widget>[
PositionedTransition(
rect: animation,
child: GestureDetector(
onTap: () {
controller.forward();
},
child: Container(
width: 100.0,
height: 100.0,
color: Colors.red,
),
),
)
]),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# SizeTransition
- 容器大小过渡动画
const SizeTransition({
Key? key,
this.axis = Axis.vertical,
required Animation<double> sizeFactor,
this.axisAlignment = 0.0,
this.child,
}) : assert(axis != null),
assert(sizeFactor != null),
assert(axisAlignment != null),
super(key: key, listenable: sizeFactor);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# AnimatedBuilder
- 用于构建动画的通用小部件。用它包裹可以实现根据animation变化而变化的动画
AnimatedBuilder(
animation: animation2,
builder: (BuildContext ctx, Widget child) {
return Container(
transform:
Matrix4.translationValues(0, animation2.value, 0),
alignment: Alignment.topLeft,
padding: EdgeInsets.fromLTRB(40.0, 30.0, 40.0, 0.0),
child: Column(
children: <Widget>[
Container(
alignment: Alignment.topLeft,
child: Text(
'我是标题',
style: TextStyle(fontSize: 18.0),
),
),
Container(
padding: EdgeInsets.only(top: 10.0),
alignment: Alignment.topLeft,
child: Text('我是内容啦啦啦啦'),
)
],
),
);
},
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# AnimatedModalBarrier
- 一个阻止用户与widget交互的widget
const AnimatedModalBarrier({
Key? key,
required Animation<Color?> color,
this.dismissible = true,
this.semanticsLabel,
this.barrierSemanticsDismissible,
}) : super(key: key, listenable: color);
1
2
3
4
5
6
7
2
3
4
5
6
7
上面各动画类,共同点在于继承 AnimatedWidget
# SliverFadeTransition
- Sliver 过渡渐入过渡动画
const SliverFadeTransition({
Key? key,
required this.opacity,
this.alwaysIncludeSemantics = false,
Widget? sliver,
}) : assert(opacity != null),
super(key: key, child: sliver);
1
2
3
4
5
6
7
2
3
4
5
6
7
# FadeTransition
- 渐隐渐现
FadeTransition(
opacity: Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: controller!,
curve: Curves.fastOutSlowIn),
),
child: Container(
width: 200,
height: 200,
color: Colors.white,
child: Image.network(
"https://img1.baidu.com/it/u=610017077,4160995221&fm=11&fmt=auto&gp=0.jpg",
),
),
),
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
上面各动画类,共同点在于继承 SingleChildRenderObjectWidget
# AnimatedDefaultTextStyle
- 文本样式切换过渡动画
const AnimatedDefaultTextStyle({
Key? key,
required this.child,
required this.style,
this.textAlign,
this.softWrap = true,
this.overflow = TextOverflow.clip,
this.maxLines,
this.textWidthBasis = TextWidthBasis.parent,
this.textHeightBehavior,
Curve curve = Curves.linear,
required Duration duration,
VoidCallback? onEnd,
}) : assert(style != null),
assert(child != null),
assert(softWrap != null),
assert(overflow != null),
assert(maxLines == null || maxLines > 0),
assert(textWidthBasis != null),
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
///
AnimatedDefaultTextStyle(child: Text('使用举例'), style: TextStyle(
color: widget.color
), duration: Duration(seconds: 2)
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# AnimatedContainer
- 属性改变, 根据设定的时间过渡 大小 颜色 位移 等,变化属性参考如下
AnimatedContainer({
Key? key,
this.alignment,
this.padding,
Color? color,
Decoration? decoration,
this.foregroundDecoration,
double? width,
double? height,
BoxConstraints? constraints,
this.margin,
this.transform,
this.transformAlignment,
this.child,
this.clipBehavior = Clip.none,
Curve curve = Curves.linear,
required Duration duration,
VoidCallback? onEnd,
}) : assert(margin == null || margin.isNonNegative),
assert(padding == null || padding.isNonNegative),
assert(decoration == null || decoration.debugAssertIsValid()),
assert(constraints == null || constraints.debugAssertIsValid()),
assert(color == null || decoration == null,
'Cannot provide both a color and a decoration\n'
'The color argument is just a shorthand for "decoration: BoxDecoration(color: color)".',
),
decoration = decoration ?? (color != null ? BoxDecoration(color: color) : null),
constraints =
(width != null || height != null)
? constraints?.tighten(width: width, height: height)
?? BoxConstraints.tightFor(width: width, height: height)
: constraints,
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# AnimatedOpacity
- Opacity的动画版本,在给定的透明度变化时,自动地在给定的一段时间内改变孩子的Opacity
const AnimatedOpacity({
Key? key,
this.child,
required this.opacity,
Curve curve = Curves.linear,
required Duration duration,
VoidCallback? onEnd,
this.alwaysIncludeSemantics = false,
}) : assert(opacity != null && opacity >= 0.0 && opacity <= 1.0),
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
///
AnimatedOpacity(
opacity: widget.opacity,
duration: Duration(seconds: 2),
child: Container(
width: 100.0,
height: 100.0,
color: Colors.black,
)
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# AnimatedPhysicalModel
- PhysicalModel的动画版本
const AnimatedPhysicalModel({
Key? key,
required this.child,
required this.shape,
this.clipBehavior = Clip.none,
this.borderRadius = BorderRadius.zero,
required this.elevation,
required this.color,
this.animateColor = true,
required this.shadowColor,
this.animateShadowColor = true,
Curve curve = Curves.linear,
required Duration duration,
VoidCallback? onEnd,
}) : assert(child != null),
assert(shape != null),
assert(clipBehavior != null),
assert(borderRadius != null),
assert(elevation != null && elevation >= 0.0),
assert(color != null),
assert(shadowColor != null),
assert(animateColor != null),
assert(animateShadowColor != null),
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
///阴影动画
AnimatedPhysicalModel(
duration: Duration(seconds: 2),
shape: BoxShape.rectangle,
elevation: 20.0,
color: Colors.transparent,
shadowColor: widget.color,
child: Container(
width: 100.0,
height: 100.0,
color: Colors.black,
)
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# AnimatedPositioned
- 动画版本的Positioned,每当给定位置的变化,自动在给定的时间内转换孩子的位置。相对于PositionedTransition简单一些, 但是功能相对单一
const AnimatedPositioned({
Key? key,
required this.child,
this.left,
this.top,
this.right,
this.bottom,
this.width,
this.height,
Curve curve = Curves.linear,
required Duration duration,
VoidCallback? onEnd,
}) : assert(left == null || right == null || width == null),
assert(top == null || bottom == null || height == null),
super(key: key, curve: curve, duration: duration, onEnd: onEnd);
///举例
Stack(children: <Widget>[
AnimatedPositioned(
width: widget.width,
duration: Duration(seconds: 2),
child: GestureDetector(
onTap: (){
setState(() {
widget.width = 100.0;
});
},
child: Container(
width: 100.0,
height: 100.0,
color: Colors.red,
),
)
)
])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# AnimatedSize
- 动画widget,当给定的孩子的大小变化时,它自动地在给定时间内转换它的大小。
const AnimatedSize({
Key? key,
Widget? child,
this.alignment = Alignment.center,
this.curve = Curves.linear,
required this.duration,
this.reverseDuration,
required this.vsync,
this.clipBehavior = Clip.hardEdge,
}) : assert(clipBehavior != null),
super(key: key, child: child);
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# AnimatedWidgetBaseState
- 具有隐式动画的widget的基类
abstract class AnimatedWidgetBaseState<T extends ImplicitlyAnimatedWidget> extends ImplicitlyAnimatedWidgetState<T> {
void initState() {
super.initState();
controller.addListener(_handleAnimationChanged);
}
void _handleAnimationChanged() {
setState(() { /* The animation ticked. Rebuild with new animation value */ });
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
以上继承 ImplicitlyAnimatedWidget 类
# Tween
- 线性动画,使用传入类型入常用的 double
Animation<double> animation;
AnimationController controller;
controller = new AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = Tween(
begin: 0.0,
end: 1.0)
.animate(controller);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# RelativeRectTween
- 继承Tween类,用法与Tween 类似
Animation<RelativeRect> animation;
AnimationController controller;
controller = new AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = RelativeRectTween(
begin: RelativeRect.fromLTRB(200.0, 200.0, 200.0, 200.0),
end: RelativeRect.fromLTRB(20.0, 20.0, 20.0, 20.0))
.animate(controller);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# DecorationTween
- 继承Tween类,用法与Tween 类似
Animation<Decoration> animation;
AnimationController controller;
controller = new AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
animation = DecorationTween(
begin: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(0.0)),
color: Colors.red
),
end: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
color: Colors.green
)
).animate(controller);
DecoratedBoxTransition(
decoration: animation,
child: Container(
width: 100.0,
height: 100.0,
)
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# AnimatedWidget
- transition 继承类始祖,可继承 自定义各种动画.当给定的Listenable改变值时,会重新构建该widget
const AnimatedWidget({
Key? key,
required this.listenable,
}) : assert(listenable != null),
super(key: key);
1
2
3
4
5
2
3
4
5
# AnimatedCrossFade
- 一个widget,在两个孩子之间交叉淡入,并同时调整他们的尺寸, firstChild 在一定时间逐渐变成 secondChild
const AnimatedCrossFade({
Key? key,
required this.firstChild,
required this.secondChild,
this.firstCurve = Curves.linear,
this.secondCurve = Curves.linear,
this.sizeCurve = Curves.linear,
this.alignment = Alignment.topCenter,
required this.crossFadeState,
required this.duration,
this.reverseDuration,
this.layoutBuilder = defaultLayoutBuilder,
}) : assert(firstChild != null),
assert(secondChild != null),
assert(firstCurve != null),
assert(secondCurve != null),
assert(sizeCurve != null),
assert(alignment != null),
assert(crossFadeState != null),
assert(duration != null),
assert(layoutBuilder != null),
super(key: key);
/// 举例
AnimatedCrossFade(
firstChild: Container(
width: 100.0,
height: 100.0,
color: Colors.green,
child: Text('123'),
),
secondChild: Container(
width: 200.0,
height: 100.0,
color: Colors.red,
child: Text('456'),
),
crossFadeState: widget.first ? CrossFadeState.showFirst : CrossFadeState.showSecond,
duration: Duration(seconds: 2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Hero
- 页面某一元素平滑过渡承接另一页面 参考网址 (opens new window)
const Hero({
Key? key,
required this.tag,
this.createRectTween,
this.flightShuttleBuilder,
this.placeholderBuilder,
this.transitionOnUserGestures = false,
required this.child,
}) : assert(tag != null),
assert(transitionOnUserGestures != null),
assert(child != null),
super(key: key);
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
以上类继承 StatefulWidget
# AnimatedList
- 动画列表显示加入动画
# AnimatedListState
- AnimatedListState 是 AnimatedList 的状态类 参考博客 (opens new window)
# AnimationController
- 动画控制器
AnimationController controller;
ontroller = new AnimationController(
duration: const Duration(milliseconds: 2000), vsync: this);
//动画开始、结束、向前移动或向后移动时会调用StatusListener
controller!.addStatusListener((status) {
if (status == AnimationStatus.completed) {
//动画从 controller.forward() 正向执行 结束时会回调此方法
print("status is completed");
//反向执行
controller?.reverse();
} else if (status == AnimationStatus.dismissed) {
//动画从 controller.reverse() 反向执行 结束时会回调此方法
print("status is dismissed");
controller?.forward();
} else if (status == AnimationStatus.forward) {
print("status is forward");
//执行 controller.forward() 会回调此状态
} else if (status == AnimationStatus.reverse) {
//执行 controller.reverse() 会回调此状态
print("status is reverse");
}
});
//启动动画
controller?.forward();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27