Flutter-动画

实现原理

  • 动画就是动起来得画面
  • 视觉暂留: 画面经视神经传入大脑后,不会立即消失(会保留一段时间)
  • 帧: 单个得画面,在学术上叫帧。每秒中展示得帧数简称为fps(Frame per Second)

动画分类

  1. 补间动画

    在补间动画中我们定义开始点和结束点、 时间线以及定义转换时间和速度曲线,然后由系统计算, 从开始运动到结束点、 从而形成动画效果

     例如:从透明度度0 到 1, 从颜色值 0  到 255
    
  • 拟物动画

    模拟动画是对真是世界得行为进行建模,是动画效果类似与现时中得物理效果。

    例如: 弹簧、重力、抛物线。。。。。
    

动画

AnimationController

在指定的时间内, 将组件属性值由初始值演变成终止值,从而形成动画效果。

属性类型说明
durationDuration动画的执行时间
reverseDurationDuration动画反向执行时间
lowerBound0.0lowerBound = 0.0 表示动画最小值
upperBound1.0upperBound= 1.0 表示动画最大值
valuelowerBound 、 upperBound动画初始值,默认是lowerBound
vsyncTickerProvider防止动画(动画页面切换到后台时)消耗不必要资源

动画状态

  • AnimationStatus.dismissed - 动画初始化状态
  • AnimationStatus.completed- 动画结束状态
  • AnimationStatus.forward - 动画处在从开始到结束的运行状态
  • AnimationStatus.reverse - 动画处在从结束到开始的运行状态

AnimationController 控制动画的方法

  1. AnimationController.forward() 可以正向执行动画
  2. AnimationController.reverse() 可以反向执行动画
  3. AnimationController.dispose() 用来释放动画资源(在不适用时调用此方法,否则会造成资源泄露)
  4. AnimationController.stop() 用来停止动画运行

使用步骤

  1. 创建动画

    controller = AnimationController(duration, vsync)
    
  2. 创建动画曲线

    动画曲线(CurvedAnimation)
    补间动画 (Tween)
    
  3. 监听动画曲线

    addListener() // 监听动画生成值
    addStatusListener() // 监听动画状态
    
  4. 执行动画

    controller.forward() // 正向执行
    controller.reverse() // 反向执行
    
  5. 组件销毁时移除动画

     @override
        void dispose() {
          // TODO: implement dispose
          super.dispose();
          controller.dispose();
        }
    

代码示例

在这里插入图片描述

import 'package:flutter/material.dart';


class Body extends StatefulWidget {
  Body({Key key}) : super(key: key);

  @override
  _BodyState createState() => _BodyState();
}

// 注意,使用动画时必须混入SingleTickerProviderStateMixin 类
class _BodyState extends State<Body> with SingleTickerProviderStateMixin{
  AnimationController controller;
  Animation animation;

  @override
    void initState() {
      super.initState();

      // 1. 创建controller;
      controller = AnimationController(
        // 设置动画时长
        duration: Duration(
          milliseconds: 1000,
        ),
        // 固定写法
        vsync: this,
      );

      // 2. 设置动画曲线
      animation = CurvedAnimation(
        curve: Curves.bounceIn, // 曲线
        parent: controller, // 动画曲线作用与某个动画
      );
      // 2.1 设置动画值得范围, 添加到controller 中, 注意这里时double 类型
      animation = Tween(begin: 20.0, end: 100.0).animate(controller);

      // 3.监听曲线变化
      animation.addListener((){
        print(animation.value);
        // 必须声明setState, 不然无法刷新组件
        setState(() {});
      });

      // 4.执行动画
      // controller.forward(); // 正向执行
    }
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          Icon(
            Icons.accessible_rounded,
            color: Colors.red,
            size: animation.value
          ),
          ElevatedButton(
            onPressed: () {
              // 4.执行动画
              controller.forward();
            },
            child: Text('放大'),
          ),
          ElevatedButton(
            onPressed: () {
              // 4.执行动画
              controller.reverse();
            },
            child: Text('缩小'),
          ),
          ElevatedButton(
            onPressed: () {
              // 4.执行动画
              controller.stop();
            },
            child: Text('停止'),
          ),
          ElevatedButton(
            onPressed: () {
              // 监听动画状态
              animation.addStatusListener((state) {
                // 判断动画状态
                if (state == AnimationStatus.dismissed) {
                  controller.forward();
                }

                if (state == AnimationStatus.completed) {
                  controller.reverse();
                }
              });
              controller.forward();
            },
            child: Text('重复执行'),
          ),
        ],
      ),
    );
  }
  @override
    void dispose() {
      // TODO: implement dispose
      super.dispose();
      controller.dispose();
    }
}


交织动画

交织动画是由多个单一动画叠加而成复杂动画
需要给每个动画设置时间间隔

在这里插入图片描述


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


class Body extends StatefulWidget {
  Body({Key key}) : super(key: key);

  @override
  _BodyState createState() => _BodyState();
}

class _BodyState extends State<Body> with SingleTickerProviderStateMixin{

  AnimationController controller;
  Animation animation;
  Animation sizeAnimation;
  Animation colorAnimation;
  Animation rotateAnimation;

  @override
    void initState() {
      super.initState();

      // 创建动画
      controller = AnimationController(
        duration: Duration(seconds: 3),
        vsync: this,
      );

      // 创建动画曲线
      animation = CurvedAnimation(
        curve: Interval(0.0, 0.5),
        parent: controller,
      )..addListener(() {
        setState((){});
      });

      sizeAnimation = Tween(begin:0.0, end:50.0).animate(animation);
      colorAnimation = ColorTween(begin: Colors.yellow, end: Colors.pink).animate(
        CurvedAnimation(
          curve: Interval(0.5, 0.8),
          parent: controller,
        )
      );
      rotateAnimation = Tween(begin: 0.0, end: 2*pi).animate(CurvedAnimation(
          curve: Interval(0.8, 1.0),
          parent: controller,
        )
      );

    }


  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: [
          Opacity(
            opacity: controller.value,
            child: Transform.rotate(
              angle: rotateAnimation.value,
              child: Container(
                width: sizeAnimation.value,
                height: sizeAnimation.value,
                color: colorAnimation.value,
                
              )
            )
          ),
          ElevatedButton(
            onPressed: () {
              // 4.执行动画
              controller.forward();
            },
            child: Text('放大'),
          ),
          ElevatedButton(
            onPressed: () {
              // 4.执行动画
              controller.reverse();
            },
            child: Text('缩小'),
          ),
          ElevatedButton(
            onPressed: () {
              // 4.执行动画
              controller.stop();
            },
            child: Text('停止'),
          ),
        ]
      ),
    );
  }
}

Hero 动画

Hero 动画用来实现跨页面的动画效果
在不同的页面中,声明一个共享组件,由于共享组件在不同页面中的位置,外观等不同,切换路由时,形成动画效果

实现思路

  1. 在A页面中定义初始Hero 组件(source hero), 声明tag

  2. 在B 页面中定义目标Hero 组件 (destination hero), 绑定相同tag

  3. 页面跳转时,通过Navigator, 传递tag

    tag路由切换时,共享组件的标记

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

夜丶陌颜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值