Flutter Widget类收录---动画合集 (二)

2021/7/20 flutter

# 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

# 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

# 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

# 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

# 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

# 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
///举例
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

# 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

# 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
///举例
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

# 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

# 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

# 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

上面各动画类,共同点在于继承 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

# 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

上面各动画类,共同点在于继承 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

# 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

# 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

# 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

# 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

# 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

# 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

以上继承 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

# 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

# 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

# AnimatedWidget

  • transition 继承类始祖,可继承 自定义各种动画.当给定的Listenable改变值时,会重新构建该widget
  const AnimatedWidget({
    Key? key,
    required this.listenable,
  }) : assert(listenable != null),
       super(key: key);
1
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

# Hero

  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

以上类继承 StatefulWidget

# AnimatedList

  • 动画列表显示加入动画

# AnimatedListState

# 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
Last Updated: 2021/7/21 10:32:31