软件编程
位置:首页>> 软件编程>> flutter编程>> Flutter封装组动画混合动画AnimatedGroup示例详解

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

作者:SoaringHeart  发布时间:2022-12-29 17:17:05 

标签: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

来源:https://juejin.cn/post/7190184512532414522

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com