Flutter 动画

1. AnimationController

动画控制器,控制动画的启动、停止,还可以获取动画的运行状态

class _AnimationDemoState extends State with SingleTickerProviderStateMixin

创建一个AnimationController

AnimationController(vsync:this, duration:Duration(seconds:3))

vsync:本身Widget(单个 AnimationController 的时候使用 SingleTickerProviderStateMixin,多个 AnimationController 使用 TickerProviderStateMixin), 存在vsync时会防止屏幕外动画消耗不必要的资源

动画的状态分为四种:

dismissed:动画停止在开始处。

forward:动画正在从开始处运行到结束处(正向运行)。

reverse:动画正在从结束处运行到开始处(反向运行)。

completed:动画停止在结束处。

动画的控制方法:

forward:正向执行动画。

reverse:反向执行动画。

repeat:反复执行动画。

reset:重置动画。

使用示例

监听页面状态变化

_animationController.addStatusListener((status) {

    if (status == AnimationStatus.completed) {

        _animationController.reset();

        setState(() {

            _islike =false;

        });        

    }

});

_animationController?.addListener(() {

    // 页面刷新

    setState(() {

    });

});

_animationController.value 默认值值是从0-1的

AnimationController销毁

void dispose() {

    super.dispose();

    _animationController?.dispose();

}

2.Tween 和 Curve

把从 0 -> 1 转换为 蓝色 -> 红色 行为称之为 Tween(映射)

Curve Tween的值之间变化的规律(线性...)

系统提供的 Tween(选中类Tween,快捷键Ctrol+h,查看类的继承关系)


系统的Tween

系统已经提供了38种常用到动画曲线 Curves.bounceIn

使用示例

ColorTween(begin: Colors.blue, end: Colors.red)

    .chain(CurveTween(curve: Curves.bounceIn))

    .animate(_animationController!)

另外一种使用方式

_animationController?.drive(CurveTween(curve: Curves.linear))

.drive(Tween(begin:100.0, end:200.0));

自定义curve

class MyCurve extends Curve {

      @override

      double transformInternal(double t) {

        return t; //线性执行

      }

需要继承 Curve 重写 transformInternal 方法

3.组合动画

实现 40%,widget由 100 -> 200, 20% widget大小保持不变, 40%widget 背景色由蓝色-> 红色

_tweenSequenceAnimation =TweenSequence([

    TweenSequenceItem(tween:Tween(begin:100.0, end:200.0), weight:40),

    TweenSequenceItem(tween:ConstantTween(200.0), weight:20),

    TweenSequenceItem(tween:ColorTween(begin: Colors.blue, end: Colors.red), weight:40),

]).animate(_animationController!);

TweenSequence 值使用

width:_tweenSequenceAnimation?.value is double ?_tweenSequenceAnimation?.value :200,

height:_tweenSequenceAnimation?.value is double ?_tweenSequenceAnimation?.value :200,

color:_tweenSequenceAnimation?.value is Color ?_tweenSequenceAnimation?.value : Colors.blue

4.隐性动画和显性动画

显性动画:动画组件只封装 setState 方法

隐性动画:组件封装了 AnimationController、Curve、Tween

显性动画系统的类

    

显性动画系统的类

隐性动画系统的类


隐性动画系统的类

使用示例 见下面路由动画

5.路由动画

自定义动画 需要实现PageRouteBuilder

自定义从左往右动画

class LeftToRightPageRouteextends PageRouteBuilder {

    final Widget_newpage;

    LeftToRightPageRoute(this._newpage)

    :super(pageBuilder: (BuildContext context, Animation animation,

    Animation secondaryAnimation) {

        return _newpage;

      }, transitionsBuilder: (BuildContext context,

            Animation animation,

            Animation secondaryAnimation,

            Widget child) {

            return SlideTransition(

                    position:Tween(begin:Offset(1,0), end:Offset(0,0))

                    .animate(animation),

                    child: child,

            );

        });

}

// 页面圆形形状 打开

class CirclePageRouteextends PageRouteBuilder {

    final Widget_newpage;

    CirclePageRoute(this._newpage)

        :super(pageBuilder: (BuildContext context, Animation animation,

            Animation secondaryAnimation) {

                return _newpage;

            }, transitionsBuilder: (BuildContext context,

                Animation animation,

                Animation secondaryAnimation,

                Widget child) {

                return AnimatedBuilder(

                    animation: animation,

                    builder: (context, child) {

                    return ClipPath(

                            clipper:_CustomClip(animation.value),

                              child: child,

                        );

                    },

                child: child,

           );

    });

}

自定义裁剪形状

class _CustomClipextends CustomClipper {

final doublevalue;

_CustomClip(this.value);

@override

  Path getClip(Size size) {

        Path _path =Path();

        double radius = value * sqrt(size.height * size.height + size.width * size.width);

        _path.addOval(Rect.fromCircle(center:Offset(size.width,0), radius: radius));

        return _path;

}

@override

  bool shouldReclip(covariant CustomClipper oldClipper) {

        return true;

    }

}

6.其他动画

Hero 动画,系统提供的动画插件animations: ^1.1.1(使用参考官方文档)

Flow(

    delegate:CirclePointFlowDelegate(),

    children: [

        _buildCirclePoint(2,Color(0xFF97B1CE), circleAnimation), // 自定义的组件,circleAnimation Animation    

    ],

)

class CirclePointFlowDelegateextends FlowDelegate {

    @override

      void paintChildren(FlowPaintingContext context) {

            print(context.size);

            double radius =30;

            double rx = context.size.width /2;

            double ry = context.size.height /2;

            for (int i =0;i < context.childCount;i++) {

                print(context.getChildSize(i));

                if (i %2 ==0) {

                    double x = rx + (radius) * cos(i *2 * pi / (context.childCount -1));

                    double y = ry + (radius) * sin(i *2 * pi / (context.childCount -1));

                    context.paintChild(i, transform:Matrix4.translationValues(x, y,0));

                }else {

                    double x = rx + (radius ) * cos((i -1) *2 * pi / (context.childCount -1) + 2 * pi / ((context.childCount -1) *3));

                    double y = ry + (radius) * sin((i -1) *2 * pi / (context.childCount -1) + 2 * pi / ((context.childCount -1) *3));

                    context.paintChild(i, transform:Matrix4.translationValues(x, y,0));

                }

        }

}

@override

  bool shouldRepaint(covariant FlowDelegate oldDelegate) {

        return true;

    }

}

你可能感兴趣的:(Flutter 动画)