【Flutter】三十、Flutter动画(一)

一、使用Animation完成简单动画

import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';

class AnimationRoute extends StatefulWidget {
  @override
  _AnimationRouteState createState() {
    // TODO: implement createState
    return _AnimationRouteState();
  }
}

class _AnimationRouteState extends State<AnimationRoute> with SingleTickerProviderStateMixin{
  Animation animation;
  AnimationController controller;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    // 创建动画控制器
    controller = AnimationController(
        vsync: this,
        duration: Duration(seconds: 1)
    );
    // 创建动画曲线
    CurvedAnimation curveAnimation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
    animation = Tween(begin: Size(0,0), end: Size(300.0, 200.0)).animate(curveAnimation)
      ..addListener(() => setState((){}));
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Container(
            margin: EdgeInsets.symmetric(vertical: 40.0),
            height: 300,
            child: Image.asset(
              'assets/images/lake.jpg',
              width: animation.value.width,
              height: animation.value.height,
            ),
          ),
          Stack(
            children: <Widget>[
              Positioned(
                child: RaisedButton(
                  child: Text('start animate'),
                  onPressed: () {
                    if (animation.value.width == 300) {
                      controller.reverse();
                    } else {
                      controller.forward();
                    }
                    // controller.repeat(reverse: true); // 重复动画
                  },
                ),
              )
            ],
          )
        ],
      ),
    );
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

    点击按钮后,代用controller.forward()方法执行动画,使用controller.repeat(reverse: true)可以让动画重复执行。上面示例通过CurvedAnimation设置动画曲线,其中的curve属性就是曲线属性,Flutter提供了大量动画曲线,如lineareasebounceIn等。下面是一个展示各种动画曲线的一个示例,通过选择不同动画曲线,会有不同效果:
在这里插入图片描述
动画曲线代码:

import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';

class AnimationRoute extends StatefulWidget {
  @override
  _AnimationRouteState createState() {
    // TODO: implement createState
    return _AnimationRouteState();
  }
}

class _AnimationRouteState extends State<AnimationRoute>
    with SingleTickerProviderStateMixin {
  Animation animation;
  AnimationController controller;
  Curve _selectItem;
  Map<String, Curve> map = {
    'linear': Curves.linear,
    'decelerate': Curves.decelerate,
    'fastLinearToSlowEaseIn': Curves.fastLinearToSlowEaseIn,
    'ease': Curves.ease,
    'easeIn': Curves.easeIn,
    'easeInToLinear': Curves.easeInToLinear,
    'easeInSine': Curves.easeInSine,
    'easeInQuad': Curves.easeInQuad,
    'easeInCubic': Curves.easeInCubic,
    'easeInQuart': Curves.easeInQuart,
    'easeInQuint': Curves.easeInQuint,
    'easeInExpo': Curves.easeInExpo,
    'easeInCirc': Curves.easeInCirc,
    'easeInBack': Curves.easeInBack,
    'easeOut': Curves.easeOut,
    'linearToEaseOut': Curves.linearToEaseOut,
    'easeOutSine': Curves.easeOutSine,
    'easeOutQuad': Curves.easeOutQuad,
    'easeOutCubic': Curves.easeOutCubic,
    'easeOutQuart': Curves.easeOutQuart,
    'easeOutQuint': Curves.easeOutQuint,
    'easeOutExpo': Curves.easeOutExpo,
    'easeOutCirc': Curves.easeOutCirc,
    'easeOutBack': Curves.easeOutBack,
    'easeInOut': Curves.easeInOut,
    'easeInOutSine': Curves.easeInOutSine,
    'easeInOutQuad': Curves.easeInOutQuad,
    'easeInOutCubic': Curves.easeInOutCubic,
    'easeInOutQuart': Curves.easeInOutQuart,
    'easeInOutQuint': Curves.easeInOutQuint,
    'easeInOutExpo': Curves.easeInOutExpo,
    'easeInOutCirc': Curves.easeInOutCirc,
    'easeInOutBack': Curves.easeInOutBack,
    'fastOutSlowIn': Curves.fastOutSlowIn,
    'slowMiddle': Curves.slowMiddle,
    'bounceIn': Curves.bounceIn,
    'bounceOut': Curves.bounceOut,
    'bounceInOut': Curves.bounceInOut,
    'elasticIn': Curves.elasticIn,
    'elasticOut': Curves.elasticOut,
    'elasticInOut': Curves.elasticInOut
  };

  List<DropdownMenuItem> getDropMenuItems () {
    return map.keys.toList().map((item){
      return DropdownMenuItem(
        value: map[item],
        child: Text('$item'),
      );
    }).toList();
  }


  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _selectItem = map['linear'];
    controller = AnimationController(vsync: this, duration: Duration(seconds: 1));
    animation = Tween(begin: Size(0, 0), end: Size(300.0, 200.0))
        .animate(CurvedAnimation(parent: controller, curve: Curves.bounceIn))
          ..addListener(() => setState(() {}));
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          Container(
            margin: EdgeInsets.symmetric(vertical: 40.0),
            height: 200,
            child: Image.asset(
              'assets/images/lake.jpg',
              width: animation.value.width,
              height: animation.value.height,
            ),
          ),
          Wrap(
            runAlignment: WrapAlignment.center,
            alignment: WrapAlignment.center,
            children: <Widget>[
              DropdownButton(
                value: _selectItem,
                items: getDropMenuItems(),
                onChanged: (item){
                  setState(() {
                    _selectItem = item;
                    controller.reset();
                    animation = Tween(begin: Size(0, 0), end: Size(300.0, 200.0))
                        .animate(CurvedAnimation(parent: controller, curve: item))
                      ..addListener(() => setState(() {}));
                    controller.forward();
                  });
                },
              )
            ],
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

二、使用AnimatedWidget

    使用AnimatedWidget不再需要setState

import 'package:flutter/material.dart';

class AnimationWidgetDemo extends AnimatedWidget{
  AnimationWidgetDemo({Key key, Animation<Size> animation}): super(key: key, listenable: animation);
  @override
  Widget build(BuildContext context) {
    final Animation<Size> animation = listenable;
    // TODO: implement build
    return Image.asset(
      'assets/images/lake.jpg',
      width: animation.value.width,
      height: animation.value.height,
    );
  }

}

class AnimatinoWidgetRoute extends StatefulWidget{
  @override
  _AnimatinoWidgetRouteState createState() {
    // TODO: implement createState
    return _AnimatinoWidgetRouteState();
  }
}

class _AnimatinoWidgetRouteState extends State<AnimatinoWidgetRoute> with SingleTickerProviderStateMixin{
  AnimationController controller;
  Animation<Size> animation;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller = AnimationController(vsync: this, duration: Duration(seconds: 2));
    animation = Tween(begin: Size(0, 0), end: Size(300, 200)).animate(controller);
  }
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
      child: Column(
        children: <Widget>[
          Container(
            margin: EdgeInsets.symmetric(vertical: 40.0),
            height: 200,
            child: AnimationWidgetDemo(animation: animation,)
          ),
          RaisedButton(
            child: Text('start animation'),
            onPressed: () {
              controller.forward();
            },
          )
        ],
      ),
    );
  }
}

三、使用AnimatedBuilder

    使用AnimatedBuilderAnimatedWidget同样不需要调用setState,并且可以直接在组件中使用,不需要单独抽离出来。

import 'package:flutter/material.dart';

class AnimatedBuilderDemo extends StatefulWidget{
  @override
  _AnimatedBuilderDemoState createState() {
    // TODO: implement createState
    return _AnimatedBuilderDemoState();
  }
}

class _AnimatedBuilderDemoState extends State<AnimatedBuilderDemo> with SingleTickerProviderStateMixin{
  AnimationController controller;
  Animation animation;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    controller = AnimationController(vsync: this, duration: Duration(seconds: 2));
    animation = Tween(begin: Size(0, 0), end: Size(300, 200))
        .animate(CurvedAnimation(parent: controller, curve: Curves.bounceIn));
  }
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return AnimatedBuilder(
      animation: animation,
      builder: (context, child){
        return Center(
          child: Column(
            children: <Widget>[
              Container(
                  margin: EdgeInsets.symmetric(vertical: 40.0),
                  height: 200,
                  child: Image.asset(
                    'assets/images/lake.jpg',
                    width: animation.value.width,
                    height: animation.value.height,
                  )
              ),
              RaisedButton(
                child: Text('start animation'),
                onPressed: () {
                  controller.forward();
                },
              )
            ],
          ),
        );
      },
    );
  }
}

四、动画状态监听

    使用Animationd的addStatusListener方法可以监听动画状态。Flutter中有四种动画状态,在AnimationStatus枚举类中定义:

枚举值说明
dismissed动画在起始点停止
forward动画正在正向执行
reverse动画正在反向执行
completed动画在终点完成
animation = Tween(begin: Size(0, 0), end: Size(300, 200))
        .animate(CurvedAnimation(parent: controller, curve: Curves.bounceIn))
        ..addStatusListener((status){
          print(status);
        });
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MAXLZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值