Flutter封裝組動畫混合動畫AnimatedGroup示例詳解
一、來源
項(xiàng)目中遇到混合動畫的情況,每次實(shí)現(xiàn)都需要生命一堆屬性,讓代碼變得雜亂,難以維護(hù)。
參考 iOS 組動畫 CAAimationGroup, 隨花半天時(shí)間封裝一個(gè)混合動畫組件 AnimatedGroup。
此組件基于極簡、高擴(kuò)展、高適用的封裝原則,基本滿足當(dāng)前項(xiàng)目開發(fā)。
二、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'; /// 混合動畫回調(diào)類型 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); /// 混合動畫數(shù)組 List<AnimatedGroupItemModel> animations; /// 混合動畫回調(diào) AnimatedGroupBuilder builder; /// 控制器 AnimationController? controller; /// AnimationController 控制的 duration 屬性 Duration? duration; /// 不需要多次構(gòu)建的部分 Widget? child; @override AnimatedGroupState createState() => AnimatedGroupState(); } /// 混合動畫 State class AnimatedGroupState extends State<AnimatedGroup> with TickerProviderStateMixin { AnimationController? _controller; /// 僅限于無法滿足功能時(shí)使用(透傳對象, 方便二次開發(fā)) 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); } ); } /// 開始執(zhí)行動畫 /// /// isRemovedOnCompletion 是否單程動畫 /// /// isReverse 是否逆轉(zhuǎn)動畫 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 }; } /// 創(chuàng)建動畫對象 CurvedAnimation _buildAnim(double begin, double end) { return CurvedAnimation( parent: _controller!, curve: Interval( begin, end, curve: Curves.ease, ), ); } } /// 混合動畫單個(gè)動畫模型 class AnimatedGroupItemModel{ /// 混合動畫單個(gè)動畫模型 AnimatedGroupItemModel({ required this.tween, required this.begin, required this.end, }); /// 動畫 Tween Tween tween; /// 動畫開始時(shí)間 (0 - 1.0) double begin; /// 動畫結(jié)束時(shí)間 (0 - 1.0) double end; }
最后
代碼復(fù)制到項(xiàng)目中可直接運(yùn)行;
以上就是Flutter封裝組動畫混合動畫AnimatedGroup示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Flutter封裝AnimatedGroup的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android layoutAnimation詳解及應(yīng)用
這篇文章主要介紹了Android layoutAnimation詳解及應(yīng)用的相關(guān)資料,需要的朋友可以參考下2017-05-05Android編程實(shí)現(xiàn)泡泡聊天界面實(shí)例詳解(附源碼)
這篇文章主要介紹了Android編程實(shí)現(xiàn)泡泡聊天界面,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android泡泡聊天界面的窗體定義與功能實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11Android Studio 超級簡單的打包生成apk的方法
本篇文章主要介紹了Android Studio 超級簡單的打包生成apk的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10android使用handler ui線程和子線程通訊更新ui示例
這篇文章主要介紹了android使用handler ui線程和子線程通訊更新ui的方法,大家參考使用吧2014-01-01Android?Flutter實(shí)現(xiàn)有趣的頁面滾動效果
Flutter提供了?CustomScrollView?來粘合多個(gè)滑動組件,并且可以實(shí)現(xiàn)更有趣的滑動效果,本文就來為大家詳細(xì)講講實(shí)現(xiàn)的方法,需要的可以參考一下2022-06-06