網站首頁 編程語言 正文
一、來源
項目中遇到混合動畫的情況,每次實現都需要生命一堆屬性,讓代碼變得雜亂,難以維護。
參考 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
相關推薦
- 2023-03-16 ProxyWidget和Element更新的正確方式詳解_Android
- 2022-10-18 react父組件調用子組件的方式匯總_React
- 2023-03-15 pandas計算相關系數corr返回空的問題解決_python
- 2022-05-22 flex彈性布局詳解_Flex
- 2021-12-06 React腳手架搭建的學習_React
- 2024-01-29 理解并使用 XPath 中的 `normalize-space` 函數
- 2022-04-16 WPF框架Prism中View?Injection用法介紹_基礎應用
- 2022-12-01 解決k8s?namespace?一直處于?Terminating?狀態的問題_云其它
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支