前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter】Animation 动画 ( Flutter 动画基本流程 | 创建动画控制器 | 创建动画 | 设置值监听器 | 设置状态监听器 | 布局中使用动画值 | 动画运行 )

【Flutter】Animation 动画 ( Flutter 动画基本流程 | 创建动画控制器 | 创建动画 | 设置值监听器 | 设置状态监听器 | 布局中使用动画值 | 动画运行 )

作者头像
韩曙亮
发布2023-03-29 09:08:43
1.3K0
发布2023-03-29 09:08:43
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

Flutter 动画基本流程 :

① 创建动画控制器

② 创建动画

③ 设置值监听器

④ 设置状态监听器

⑤ 布局中使用动画值

⑥ 动画运行

一、创建动画控制器


AnimationController 构造函数参数说明 :

代码语言:javascript
复制
AnimationController(
	{double? value, /// 动画的初始值
	Duration? duration, /// 动画正向播放持续时间
	Duration? reverseDuration, /// 动画逆序播放持续时间
	String? debugLabel, /// 调试期间标识动画的标志
	double lowerBound: 0.0, /// 动画最小值
	double upperBound: 1.0, /// 动画最大值 
	AnimationBehavior animationBehavior: AnimationBehavior.normal,
	/// 上下文的 TickerProvider , 用于防止屏幕外的动画消耗不必要的资源 , 
	/// 一般将 StatefulWidget 作为 vsync 值
	required TickerProvider vsync} 
)

上述参数中 , 只需要设置 required TickerProvider vsync 参数 与 Duration? duration 参数即可 ;

创建动画控制器代码示例 :

代码语言:javascript
复制
    /// 1. 初始化动画控制器
    animationController = AnimationController(
      // 动画绘制到屏幕外部时, 减少消耗
      vsync: this,
      // 动画持续时间 2 秒
      duration: Duration(seconds: 3),
    );

二、创建动画


这里创建 Tween 补间动画 , 设置动画的初始值 0 , 结束值 300 , 动画在执行的

3 秒时间内 ( 动画控制器中指定的动画持续时间 ) , 自动计算出每个时间点的 0 ~ 300 之间的动画值 ;

创建动画代码示例 :

代码语言:javascript
复制
    /// 2 . 构造 Tween 补间动画 ,
    /// 设置动画控制器 AnimationController 给该补间动画
    /// 动画的值是正方形组件的宽高
    animation = Tween<double>(
      begin: 0,
      end: 300
    ).animate(animationController)

三、设置值监听器


调用 Animation 的 addListener 方法 , 可以为动画添加值监听器 ;

简洁用法 : 上一行代码表达式必须是 animation, 结尾不能有分号 , 之后可以使用 ..addListener 用法 , 该用法等价于 animation.addListener ;

setState 方法 : 动画如果生效, 必须在监听器中调用 setState 方法 , 以便重新调用 build 方法进行布局渲染 , 否则 UI 界面不会刷新 ;

" 设置值监听器 " 代码示例 :

代码语言:javascript
复制
    /// 3 . 添加动画值监听器
    /// 该用法与 animation.addListener 效果是等价的
    /// 这种写法比较简洁
    /// 类似于链式调用, 上一行代码表达式必须是 animation, 结尾不能有分号
    /// 特别注意 : 动画如果生效, 必须在监听器中调用 setState 方法
    ..addListener(() {

      /// 调用 setState 方法后, 更新相关状态值后, 自动调用 build 方法重构组件界面
      setState(() {
        // 获取动画执行过程中的值
        animationValue = animation.value;
      });

    })

四、设置状态监听器


调用 Animation 的 addStatusListener方法 , 可以为动画添加值监听器 ;

简洁用法 : 上一行代码表达式必须是 animation, 结尾不能有分号 , 之后可以使用 ..addStatusListener 用法 , 该用法等价于 animation.addStatusListener ;

setState 方法 : 动画如果生效, 必须在监听器中调用 setState 方法 , 以便重新调用 build 方法进行布局渲染 , 否则 UI 界面不会刷新 ;

" 设置状态监听器 " 代码示例 :

代码语言:javascript
复制
    /// 4 . 添加动画状态监听器
    /// 设置动画状态监听器
    ..addStatusListener((status) {
      /// 调用 setState 方法后, 更新相关状态值后, 自动调用 build 方法重构组件界面
      setState(() {
        /// 获取动画状态
        animationStatus = status;
      });
    });

五、布局中使用动画值


在 build 方法中返回的布局组件中 , 使用上述监听器中获取的动画值 animationValue , 该值是

0 ~ 300 之间的浮点数 ;

这里使用动画值作为正方形组件的宽高 ;

" 布局中使用动画值 " 代码示例 :

代码语言:javascript
复制
          // 动画的主体组件
          // 6 . 布局组件中使用动画的值 , 以达到动画效果
          Container(
            /// 设置距离顶部 20 像素
            margin: EdgeInsets.only(top: 50),
            height: animationValue,
            width: animationValue,
            decoration: BoxDecoration(color: Colors.red),
          ),

六、动画运行


监听 GestureDetector 的 onTap 点击事件 , 点击该组件后 , 调用 animationController.forward() 方法 , 运行动画 ;

代码示例 :

代码语言:javascript
复制
          GestureDetector(
            // 5 . 点击按钮开启动画
            onTap: (){
              /// 按钮点击事件
              /// 首先将动画初始化
              animationController.reset();

              /// 正向执行动画, 即从初始值执行到结束值
              animationController.forward();

            },
            child: Container(
              alignment: Alignment.center,
              color: Colors.green,
              height: 50,
              child: Text(
                // 显示文本
                "动画开始",
                /// 文字方向 : 从左到右
                textDirection: TextDirection.ltr,
              ),
            ),
          ),

七、完整代码示例


完整代码示例 :

代码语言:javascript
复制
import 'package:flutter/material.dart';

void main() {
  runApp(AnimationApp());
}

/// 动画示例主界面组件
/// 该组件是有状态的, 因此需要定义 StatefulWidget 组件
class AnimationApp extends StatefulWidget{
  @override
  _AnimationAppState createState() => _AnimationAppState();
}

/// 为 StatefulWidget 组件创建 State 类
/// 每个 StatefulWidget 都需要一个配套的 State 类
class _AnimationAppState extends State<AnimationApp>
    with SingleTickerProviderStateMixin{

  /// 动画类
  Animation<double> animation;

  /// 动画控制器
  AnimationController animationController;

  /// 动画状态
  AnimationStatus animationStatus;

  /// 动画值
  /// 动画运行过程中, 动画计算出来的值
  double animationValue;


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

    /// 1. 初始化动画控制器
    animationController = AnimationController(
      // 动画绘制到屏幕外部时, 减少消耗
      vsync: this,
      // 动画持续时间 2 秒
      duration: Duration(seconds: 3),
    );


    /// 2 . 构造 Tween 补间动画 ,
    /// 设置动画控制器 AnimationController 给该补间动画
    /// 动画的值是正方形组件的宽高
    animation = Tween<double>(
      begin: 0,
      end: 300
    ).animate(animationController)


    /// 3 . 添加动画值监听器
    /// 该用法与 animation.addListener 效果是等价的
    /// 这种写法比较简洁
    /// 类似于链式调用, 上一行代码表达式必须是 animation, 结尾不能有分号
    /// 特别注意 : 动画如果生效, 必须在监听器中调用 setState 方法
    ..addListener(() {

      /// 调用 setState 方法后, 更新相关状态值后, 自动调用 build 方法重构组件界面
      setState(() {
        // 获取动画执行过程中的值
        animationValue = animation.value;
      });

    })

    /// 4 . 添加动画状态监听器
    /// 设置动画状态监听器
    ..addStatusListener((status) {
      /// 调用 setState 方法后, 更新相关状态值后, 自动调用 build 方法重构组件界面
      setState(() {
        /// 获取动画状态
        animationStatus = status;
      });
    });

  }

  /// 该方法与 initState 对应
  @override
  void dispose() {

    /// 释放动画控制器
    animationController.dispose();

    super.dispose();
  }


  @override
  Widget build(BuildContext context) {

    return Container(

      /// 设置距离顶部 20 像素
      margin: EdgeInsets.only(top: 100),

      child: Column(
        children: [

          GestureDetector(
            // 5 . 点击按钮开启动画
            onTap: (){
              /// 按钮点击事件
              /// 首先将动画初始化
              animationController.reset();

              /// 正向执行动画, 即从初始值执行到结束值
              animationController.forward();

            },
            child: Container(
              alignment: Alignment.center,
              color: Colors.green,
              height: 50,
              child: Text(
                // 显示文本
                "动画开始",
                /// 文字方向 : 从左到右
                textDirection: TextDirection.ltr,
              ),
            ),
          ),

          
          Text("动画状态 : $animationStatus", textDirection: TextDirection.ltr,),

          Text("动画值 : ${animationValue?.round()}", textDirection: TextDirection.ltr,),

          // 动画的主体组件
          // 6 . 布局组件中使用动画的值 , 以达到动画效果
          Container(
            /// 设置距离顶部 20 像素
            margin: EdgeInsets.only(top: 50),
            height: animationValue,
            width: animationValue,
            decoration: BoxDecoration(color: Colors.red),
          ),


        ],
      ),
    );
  }

}

运行效果 :

在这里插入图片描述
在这里插入图片描述

八、相关资源


参考资料 :

重要的专题 :

博客源码下载 :

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-03-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、创建动画控制器
  • 二、创建动画
  • 三、设置值监听器
  • 四、设置状态监听器
  • 五、布局中使用动画值
  • 六、动画运行
  • 七、完整代码示例
  • 八、相关资源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档