Flutter封装组动画混合动画AnimatedGroup示例详解

 更新时间:2023年01月19日 10:31:59   作者:SoaringHeart  
这篇文章主要为大家介绍了Flutter封装组动画混合动画AnimatedGroup示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

一、来源

项目中遇到混合动画的情况,每次实现都需要生命一堆属性,让代码变得杂乱,难以维护。

参考 iOS 组动画 CAAimationGroup, 随花半天时间封装一个混合动画组件 AnimatedGroup。

此组件基于极简、高扩展、高适用的封装原则,基本满足当前项目开发。

二、AnimatedGroup使用示例:

//
//  AnimatedGroupDemo.dart
//  flutter_templet_project
//
//  Created by shang on 12/6/21 5:52 PM.
//  Copyright © 12/6/21 shang. All rights reserved.
//
import 'package:flutter/material.dart';
import 'package:flutter_templet_project/basicWidget/animated_group.dart';
class AnimatedGroupDemo extends StatefulWidget {
  AnimatedGroupDemo({ Key? key, this.title}) : super(key: key);
  final String? title;
  @override
  _AnimatedGroupDemoState createState() => _AnimatedGroupDemoState();
}
class _AnimatedGroupDemoState extends State<AnimatedGroupDemo> {
  GlobalKey<AnimatedGroupState> _globalKey = GlobalKey();
  final _animations = <AnimatedGroupItemModel>[
    AnimatedGroupItemModel(
      tween: Tween<double>(begin: .0, end: 300.0,),
      begin: 0.0,
      end: 0.6
    ),
    AnimatedGroupItemModel(
      tween: ColorTween(begin: Colors.green, end: Colors.red,),
      begin: 0.0,
      end: 0.6
    ),
    AnimatedGroupItemModel(
      tween: Tween<EdgeInsets>(
        begin: const EdgeInsets.only(left: .0),
        end: const EdgeInsets.only(left: 100.0),
      ),
      begin: 0.6,
      end: 1.0
    ),
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title ?? "$widget"),
      ),
      body: Center(
        child: Column(
          children: [
            ElevatedButton(
              child: Text("start animation"),
              onPressed: (){
                _globalKey.currentState?.palyeAnimations(isRemovedOnCompletion: false);
              },
            ),
            Container(
              width: 300,
              height: 300,
              child: AnimatedGroup(
                key: _globalKey,
                duration: Duration(milliseconds: 2000),
                animations: _animations,
                child: Text("AnimatedGroupWidget 混合动画", style: TextStyle(color: Colors.white, backgroundColor: Colors.green),),
                builder: (BuildContext context, Widget? child, List<Animation<dynamic>> animations) {
                  final aHeight = animations[0];
                  final aColor = animations[1];
                  final aPadding = animations[2];
                  return Stack(
                    children: [
                      Container(
                        alignment: Alignment.bottomCenter,
                        padding: aPadding.value,
                        child: Container(
                          color: aColor.value,
                          width: 50.0,
                          height: aHeight.value,
                        ),
                      ),
                      Center(child: child!)
                    ],
                  );
                },
              ),
              decoration: BoxDecoration(
                color: Colors.black.withOpacity(0.1),
                border: Border.all(
                  color: Colors.black.withOpacity(0.5),
                )
              ),
            )
          ],
        ),
      ),
    );
  }
}

三、AnimatedGroup源码

//
//  AnimatedGroupDemo.dart
//  flutter_templet_project
//
//  Created by shang on 1/19/23 8:21 AM.
//  Copyright © 1/19/23 shang. All rights reserved.
//
import 'package:flutter/material.dart';
/// 混合动画回调类型
typedef AnimatedGroupBuilder = Widget Function(BuildContext context, Widget? child, List<Animation<dynamic>> animations);
class AnimatedGroup extends StatefulWidget {
  /// 混合动画
  AnimatedGroup({
    Key? key,
    required this.animations,
    required this.builder,
    this.controller,
    this.duration = const Duration(milliseconds: 2000),
    this.child,
  }) : super(key: key);
  /// 混合动画数组
  List<AnimatedGroupItemModel> animations;
  /// 混合动画回调
  AnimatedGroupBuilder builder;
  /// 控制器
  AnimationController? controller;
  /// AnimationController 控制的 duration 属性
  Duration? duration;
  /// 不需要多次构建的部分
  Widget? child;
  @override
  AnimatedGroupState createState() => AnimatedGroupState();
}
/// 混合动画 State
class AnimatedGroupState extends State<AnimatedGroup> with TickerProviderStateMixin {
  AnimationController? _controller;
  /// 仅限于无法满足功能时使用(透传对象, 方便二次开发)
  AnimationController get controller => _controller!;
  List<Animation<dynamic>> _animations = [];
  @override
  void initState() {
    _controller = widget.controller ?? AnimationController(duration: widget.duration, vsync: this);
    _animations = widget.animations.map((e) => e.tween.animate(_buildAnim(e.begin, e.end))).toList();
    super.initState();
  }
  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller!,
      child: widget.child,
      builder: (BuildContext context, Widget? child){
        return widget.builder(context, child, _animations);
      }
    );
  }
  /// 开始执行动画
  ///
  /// isRemovedOnCompletion 是否单程动画
  ///
  /// isReverse 是否逆转动画
  palyeAnimations({bool isRemovedOnCompletion = true, bool isReverse = false}) async {
    try {
      if (!isReverse) {
        await _controller?.forward().orCancel;
        if (!isRemovedOnCompletion) {
          await _controller?.reverse().orCancel;
        }
      } else {
        await _controller?.reverse().orCancel;
        if (!isRemovedOnCompletion) {
          await _controller?.forward().orCancel;
        }
      }
    } on TickerCanceled {
      // the animation got canceled, probably because we were disposed
    };
  }
  /// 创建动画对象
  CurvedAnimation _buildAnim(double begin, double end) {
    return CurvedAnimation(
      parent: _controller!,
      curve: Interval(
        begin,
        end,
        curve: Curves.ease,
      ),
    );
  }
}
/// 混合动画单个动画模型
class AnimatedGroupItemModel{
  /// 混合动画单个动画模型
  AnimatedGroupItemModel({
    required this.tween,
    required this.begin,
    required this.end,
  });
  /// 动画 Tween
  Tween tween;
  /// 动画开始时间 (0 - 1.0)
  double begin;
  /// 动画结束时间 (0 - 1.0)
  double end;
}

最后

代码复制到项目中可直接运行;

github

以上就是Flutter封装组动画混合动画AnimatedGroup示例详解的详细内容,更多关于Flutter封装AnimatedGroup的资料请关注脚本之家其它相关文章!

相关文章

  • Android开发之自定义UI组件详解

    Android开发之自定义UI组件详解

    这篇文章主要给大家介绍了关于Android开发之自定义UI组件的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-05-05
  • OpenGL Shader实现简单转场效果详解

    OpenGL Shader实现简单转场效果详解

    转场效果常出现再视频剪辑当中,用于衔接两段视频片段切换的过渡效果。本文将介绍如何利用OpenGL Shader实现简单的转场效果,需要的小伙伴可以参考一下
    2022-02-02
  • 21天学习android开发教程之XML解析与生成

    21天学习android开发教程之XML解析与生成

    21天学习android开发教程之XML解析与生成,使用SAX来解析XML,在Android里面可以使用SAX和DOM,DOM需要把整个XML文件读入内存再解析,比较消耗内存,而SAX基于事件驱动的处理方式,可以在各节点触发回调函数,需要的朋友可以参考下
    2016-02-02
  • Android开发中的文件操作工具类FileUtil完整实例

    Android开发中的文件操作工具类FileUtil完整实例

    这篇文章主要介绍了Android开发中的文件操作工具类FileUtil,结合完整实例形式分析了Android文件操作的常用技巧,包括文件的获取、遍历、搜索、复制、删除、判断等功能,需要的朋友可以参考下
    2017-11-11
  • android教程之使用asynctask在后台运行耗时任务

    android教程之使用asynctask在后台运行耗时任务

    AsyncTask用在需要在ui线程中调用、在背景线程中执行耗时任务、并且在ui线程中返回结果的场合。下面就是一个在背景中运行的AsyncTask的实现DownloadDBTask
    2014-02-02
  • Android测量每秒帧数Frames Per Second (FPS)的方法

    Android测量每秒帧数Frames Per Second (FPS)的方法

    这篇文章主要介绍了Android测量每秒帧数Frames Per Second (FPS)的方法,涉及Android针对多媒体文件属性操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • Android 集成Google Cast 异常问题解析

    Android 集成Google Cast 异常问题解析

    这篇文章主要为大家介绍了Android 集成Google Cast 异常问题解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • Android实现底部切换标签

    Android实现底部切换标签

    这篇文章主要为大家详细介绍了Android实现底部切换标签,嵌套Fragment,方便自定义布局,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-07-07
  • Android中AsyncTask异步任务使用详细实例(一)

    Android中AsyncTask异步任务使用详细实例(一)

    AsyncTask是Android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程,通过本文给大家介绍Android中AsyncTask异步任务使用详细实例(一),需要的朋友参考下
    2016-02-02
  • 完美解决Android客户端RSA解密部分乱码的问题

    完美解决Android客户端RSA解密部分乱码的问题

    下面小编就为大家分享一篇完美解决Android客户端RSA解密部分乱码的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03

最新评论