From a5afab4f102765cc0084e7acbb3f0060b3599b95 Mon Sep 17 00:00:00 2001 From: xdd666 Date: Fri, 2 Sep 2022 14:07:54 +0800 Subject: [PATCH] Complete #75: add animationBuilder(Support highly custom animation) --- CHANGELOG.md | 1 + lib/flutter_smart_dialog.dart | 1 + .../compatible/compatible_smart_dialog.dart | 4 + lib/src/custom/custom_dialog.dart | 5 + lib/src/custom/custom_loading.dart | 3 + lib/src/custom/custom_toast.dart | 3 + lib/src/custom/main_dialog.dart | 7 +- lib/src/data/animation_param.dart | 131 ++++++++++++++++++ lib/src/helper/dialog_proxy.dart | 9 ++ lib/src/smart_dialog.dart | 25 ++++ lib/src/widget/attach_dialog_widget.dart | 39 ++++-- lib/src/widget/smart_dialog_widget.dart | 40 ++++-- pubspec.yaml | 2 +- 13 files changed, 247 insertions(+), 23 deletions(-) create mode 100644 lib/src/data/animation_param.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index dad30f1..c0adda3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Add displayTime (show/showAttach/showLoading) - Add SmartMaskTriggerType ([#71](https://github.com/fluttercandies/flutter_smart_dialog/issues/71)) - Fix [#72](https://github.com/fluttercandies/flutter_smart_dialog/issues/72) +- Complete [#75](https://github.com/fluttercandies/flutter_smart_dialog/issues/75): add animationBuilder(Support highly custom animation) # [4.3.x] diff --git a/lib/flutter_smart_dialog.dart b/lib/flutter_smart_dialog.dart index 8fe8118..6e08861 100644 --- a/lib/flutter_smart_dialog.dart +++ b/lib/flutter_smart_dialog.dart @@ -10,3 +10,4 @@ export 'src/config/smart_config_toast.dart'; export 'src/init_dialog.dart'; export 'src/smart_dialog.dart'; export 'src/widget/dialog_scope.dart' show SmartDialogController; +export 'src/data/animation_param.dart' show AnimationParam; diff --git a/lib/src/compatible/compatible_smart_dialog.dart b/lib/src/compatible/compatible_smart_dialog.dart index 7f9ceee..19f7de3 100644 --- a/lib/src/compatible/compatible_smart_dialog.dart +++ b/lib/src/compatible/compatible_smart_dialog.dart @@ -126,6 +126,7 @@ class CompatibleSmartDialog { animationType: isLoadingTemp ?? config.isLoading ? SmartAnimationType.centerFade_otherSlide : SmartAnimationType.centerScale_otherSlide, + animationBuilder: null, usePenetrate: isPenetrateTemp ?? config.isPenetrate, useAnimation: isUseAnimationTemp ?? config.isUseAnimation, animationTime: animationDurationTemp ?? config.animationDuration, @@ -281,6 +282,7 @@ class CompatibleSmartDialog { animationType: isLoadingTemp ?? false ? SmartAnimationType.fade : SmartAnimationType.scale, + animationBuilder: null, scalePointBuilder: null, usePenetrate: isPenetrateTemp ?? config.isPenetrate, useAnimation: isUseAnimationTemp ?? config.isUseAnimation, @@ -377,6 +379,7 @@ class CompatibleSmartDialog { animationType: isLoadingTemp ?? true ? SmartAnimationType.fade : SmartAnimationType.scale, + animationBuilder: null, usePenetrate: isPenetrateTemp ?? false, useAnimation: isUseAnimationTemp ?? config.isUseAnimation, animationTime: animationDurationTemp ?? config.animationDuration, @@ -477,6 +480,7 @@ class CompatibleSmartDialog { animationType: isLoadingTemp ?? true ? SmartAnimationType.fade : SmartAnimationType.scale, + animationBuilder: null, usePenetrate: isPenetrateTemp ?? true, useAnimation: isUseAnimationTemp ?? true, animationTime: animationDurationTemp ?? Duration(milliseconds: 200), diff --git a/lib/src/custom/custom_dialog.dart b/lib/src/custom/custom_dialog.dart index f2d0273..301054f 100644 --- a/lib/src/custom/custom_dialog.dart +++ b/lib/src/custom/custom_dialog.dart @@ -10,6 +10,7 @@ import 'package:flutter_smart_dialog/src/util/view_utils.dart'; import 'package:flutter_smart_dialog/src/widget/attach_dialog_widget.dart'; import '../config/enum_config.dart'; +import '../data/animation_param.dart'; import '../data/base_dialog.dart'; import '../smart_dialog.dart'; import '../widget/smart_overlay_entry.dart'; @@ -41,6 +42,7 @@ class CustomDialog extends BaseDialog { required bool useAnimation, required Duration animationTime, required SmartAnimationType animationType, + required AnimationBuilder? animationBuilder, required Color maskColor, required bool clickMaskDismiss, required bool debounce, @@ -72,6 +74,7 @@ class CustomDialog extends BaseDialog { useAnimation: useAnimation, animationTime: animationTime, animationType: animationType, + animationBuilder: animationBuilder, maskColor: maskColor, maskWidget: maskWidget, onDismiss: _handleDismiss(onDismiss, displayTime), @@ -97,6 +100,7 @@ class CustomDialog extends BaseDialog { required bool useAnimation, required Duration animationTime, required SmartAnimationType animationType, + required AnimationBuilder? animationBuilder, required ScalePointBuilder? scalePointBuilder, required Color maskColor, required bool clickMaskDismiss, @@ -133,6 +137,7 @@ class CustomDialog extends BaseDialog { useAnimation: useAnimation, animationTime: animationTime, animationType: animationType, + animationBuilder: animationBuilder, scalePointBuilder: scalePointBuilder, maskColor: maskColor, highlightBuilder: highlightBuilder, diff --git a/lib/src/custom/custom_loading.dart b/lib/src/custom/custom_loading.dart index 43e46a2..08ce1b9 100644 --- a/lib/src/custom/custom_loading.dart +++ b/lib/src/custom/custom_loading.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:flutter_smart_dialog/src/helper/dialog_proxy.dart'; +import '../data/animation_param.dart'; import '../data/base_dialog.dart'; import '../widget/smart_overlay_entry.dart'; @@ -19,6 +20,7 @@ class CustomLoading extends BaseDialog { required Widget widget, required bool clickMaskDismiss, required SmartAnimationType animationType, + required AnimationBuilder? animationBuilder, required bool usePenetrate, required bool useAnimation, required Duration animationTime, @@ -43,6 +45,7 @@ class CustomLoading extends BaseDialog { return mainDialog.show( widget: widget, animationType: animationType, + animationBuilder: animationBuilder, alignment: Alignment.center, maskColor: maskColor, maskWidget: maskWidget, diff --git a/lib/src/custom/custom_toast.dart b/lib/src/custom/custom_toast.dart index 6aad2c6..c1f6adf 100644 --- a/lib/src/custom/custom_toast.dart +++ b/lib/src/custom/custom_toast.dart @@ -4,6 +4,7 @@ import 'dart:collection'; import 'package:flutter/material.dart'; import '../config/enum_config.dart'; +import '../data/animation_param.dart'; import '../data/base_dialog.dart'; import '../smart_dialog.dart'; import '../widget/smart_overlay_entry.dart'; @@ -26,6 +27,7 @@ class CustomToast extends BaseDialog { required AlignmentGeometry alignment, required bool clickMaskDismiss, required SmartAnimationType animationType, + required AnimationBuilder? animationBuilder, required bool usePenetrate, required bool useAnimation, required Duration animationTime, @@ -54,6 +56,7 @@ class CustomToast extends BaseDialog { maskWidget: maskWidget, animationTime: animationTime, animationType: animationType, + animationBuilder: animationBuilder, useAnimation: useAnimation, usePenetrate: usePenetrate, onDismiss: null, diff --git a/lib/src/custom/main_dialog.dart b/lib/src/custom/main_dialog.dart index b22e322..8a9be39 100644 --- a/lib/src/custom/main_dialog.dart +++ b/lib/src/custom/main_dialog.dart @@ -9,6 +9,7 @@ import 'package:flutter_smart_dialog/src/widget/attach_dialog_widget.dart'; import 'package:flutter_smart_dialog/src/widget/smart_dialog_widget.dart'; import '../config/enum_config.dart'; +import '../data/animation_param.dart'; import '../widget/smart_overlay_entry.dart'; ///main function : customize dialog @@ -41,11 +42,12 @@ class MainDialog { required bool reuse, required SmartAwaitOverType awaitOverType, required SmartMaskTriggerType maskTriggerType, + required AnimationBuilder? animationBuilder, }) { //custom dialog _widget = SmartDialogWidget( key: reuse ? _uniqueKey : UniqueKey(), - controller: _controller = SmartDialogController(), + controller: _controller = SmartDialogWidgetController(), alignment: alignment, usePenetrate: usePenetrate, useAnimation: useAnimation, @@ -56,6 +58,7 @@ class MainDialog { child: widget, onMask: onMask, maskTriggerType: maskTriggerType, + animationBuilder: animationBuilder, ); _handleCommonOperate( @@ -80,6 +83,7 @@ class MainDialog { required bool useAnimation, required Duration animationTime, required SmartAnimationType animationType, + required AnimationBuilder? animationBuilder, required ScalePointBuilder? scalePointBuilder, required Color maskColor, required Widget? maskWidget, @@ -102,6 +106,7 @@ class MainDialog { useAnimation: useAnimation, animationTime: animationTime, animationType: animationType, + animationBuilder: animationBuilder, scalePointBuilder: scalePointBuilder, maskColor: maskColor, maskWidget: maskWidget, diff --git a/lib/src/data/animation_param.dart b/lib/src/data/animation_param.dart new file mode 100644 index 0000000..6f21112 --- /dev/null +++ b/lib/src/data/animation_param.dart @@ -0,0 +1,131 @@ +import 'package:flutter/material.dart'; + +/// example: +/// +/// ```dart +/// SmartDialog.show( +/// animationTime: const Duration(milliseconds: 3000), +/// animationBuilder: ( +/// AnimationController controller, +/// Widget child, +/// AnimationParam animationParam, +/// ) { +/// return RotationTransition( +/// turns: CurvedAnimation(parent: controller, curve: Curves.elasticIn), +/// child: child, +/// ); +/// }, +/// builder: (_) { +/// return Container( +/// color: Colors.white, +/// padding: const EdgeInsets.all(30), +/// child: const Text('custom animation dialog'), +/// ); +/// }, +/// ); +/// ``` +typedef AnimationBuilder = Widget Function( + AnimationController controller, + Widget child, + AnimationParam animationParam, +); + +/// advanced usage: +/// +/// ```dart +/// SmartDialog.show( +/// animationTime: const Duration(milliseconds: 3000), +/// animationBuilder: ( +/// AnimationController controller, +/// Widget child, +/// AnimationParam animationParam, +/// ) { +/// return CustomAnimation(child: child, animationParam: animationParam); +/// }, +/// builder: (_) { +/// return Container( +/// color: Colors.white, +/// padding: const EdgeInsets.all(30), +/// child: const Text('custom animation dialog'), +/// ); +/// }, +/// ); +/// +/// class CustomAnimation extends StatefulWidget { +/// const CustomAnimation({ +/// Key? key, +/// required this.child, +/// required this.animationParam, +/// }) : super(key: key); +/// +/// final Widget child; +/// +/// final AnimationParam animationParam; +/// +/// @override +/// State createState() => _CustomAnimationState(); +/// } +/// +/// class _CustomAnimationState extends State +/// with TickerProviderStateMixin { +/// late AnimationController _controller; +/// +/// @override +/// void initState() { +/// _controller = AnimationController( +/// vsync: this, +/// duration: widget.animationParam.animationTime, +/// ); +/// widget.animationParam.onForward = () { +/// _controller.value = 0; +/// _controller.forward(); +/// }; +/// widget.animationParam.onDismiss = () { +/// _controller.reverse(); +/// }; +/// super.initState(); +/// } +/// +/// @override +/// Widget build(BuildContext context) { +/// return RotationTransition( +/// turns: CurvedAnimation(parent: _controller, curve: Curves.elasticIn), +/// child: widget.child, +/// ); +/// } +/// +/// @override +/// void dispose() { +/// _controller.dispose(); +/// super.dispose(); +/// } +/// } +/// ``` +class AnimationParam { + AnimationParam({ + required this.alignment, + required this.animationTime, + this.onForward, + this.onDismiss, + }); + + /// showXxx#alignment + AlignmentGeometry alignment; + + /// showXxx#animationTime + Duration animationTime; + + /// The animation starts callback, indicating that the dialog is about to open; + /// if you use custom or multiple AnimationControllers, the animation should be run using forward() in this callback + /// + /// 动画开始回调, 表示该dialog即将打开; 如果使用自定义或多个AnimationController时, + /// 应该在此回调中使用forward()运行动画 + VoidCallback? onForward; + + /// The animation end callback, indicates that the dialog is about to close, + /// if you use custom or multiple AnimationController, you should use reverse() in this callback to reverse the animation + /// + /// 动画结束回调, 表示该dialog即将关闭; 如果使用自定义或多个AnimationController时, + /// 应该在此回调中使用reverse()反转运行动画 + VoidCallback? onDismiss; +} diff --git a/lib/src/helper/dialog_proxy.dart b/lib/src/helper/dialog_proxy.dart index f7b88ce..a69b369 100644 --- a/lib/src/helper/dialog_proxy.dart +++ b/lib/src/helper/dialog_proxy.dart @@ -10,6 +10,7 @@ import 'package:flutter_smart_dialog/src/widget/toast_helper.dart'; import '../config/enum_config.dart'; import '../config/smart_config.dart'; +import '../data/animation_param.dart'; import '../init_dialog.dart'; import '../widget/smart_overlay_entry.dart'; @@ -58,6 +59,7 @@ class DialogProxy { required bool useAnimation, required Duration animationTime, required SmartAnimationType animationType, + required AnimationBuilder? animationBuilder, required Color maskColor, required bool clickMaskDismiss, required Widget? maskWidget, @@ -84,6 +86,7 @@ class DialogProxy { useAnimation: useAnimation, animationTime: animationTime, animationType: animationType, + animationBuilder: animationBuilder, maskColor: maskColor, maskWidget: maskWidget, clickMaskDismiss: clickMaskDismiss, @@ -110,6 +113,7 @@ class DialogProxy { required bool useAnimation, required Duration animationTime, required SmartAnimationType animationType, + required AnimationBuilder? animationBuilder, required ScalePointBuilder? scalePointBuilder, required Color maskColor, required bool clickMaskDismiss, @@ -141,6 +145,7 @@ class DialogProxy { useAnimation: useAnimation, animationTime: animationTime, animationType: animationType, + animationBuilder: animationBuilder, scalePointBuilder: scalePointBuilder, maskColor: maskColor, maskWidget: maskWidget, @@ -162,6 +167,7 @@ class DialogProxy { Future showLoading({ required bool clickMaskDismiss, required SmartAnimationType animationType, + required AnimationBuilder? animationBuilder, required bool usePenetrate, required bool useAnimation, required Duration animationTime, @@ -176,6 +182,7 @@ class DialogProxy { return _loading.showLoading( clickMaskDismiss: clickMaskDismiss, animationType: animationType, + animationBuilder: animationBuilder, maskColor: maskColor, maskWidget: maskWidget, usePenetrate: usePenetrate, @@ -193,6 +200,7 @@ class DialogProxy { required AlignmentGeometry alignment, required bool clickMaskDismiss, required SmartAnimationType animationType, + required AnimationBuilder? animationBuilder, required bool usePenetrate, required bool useAnimation, required Duration animationTime, @@ -208,6 +216,7 @@ class DialogProxy { alignment: alignment, clickMaskDismiss: clickMaskDismiss, animationType: animationType, + animationBuilder: animationBuilder, usePenetrate: usePenetrate, useAnimation: useAnimation, animationTime: animationTime, diff --git a/lib/src/smart_dialog.dart b/lib/src/smart_dialog.dart index 390b9d4..f8ca525 100644 --- a/lib/src/smart_dialog.dart +++ b/lib/src/smart_dialog.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'compatible/compatible_smart_dialog.dart'; import 'config/enum_config.dart'; import 'config/smart_config.dart'; +import 'data/animation_param.dart'; import 'helper/dialog_proxy.dart'; import 'widget/attach_dialog_widget.dart'; import 'widget/dialog_scope.dart'; @@ -34,6 +35,8 @@ class SmartDialog { /// /// [animationType]:For details, please refer to the [SmartAnimationType] comment /// + /// [animationBuilder]:Support highly custom animation, please refer to [AnimationBuilder] description for details + /// /// [usePenetrate]:true(the click event will penetrate mask),false(not penetration) /// /// [useAnimation]:true(use the animation),false(not use) @@ -88,6 +91,8 @@ class SmartDialog { /// /// [animationType]:具体可参照[SmartAnimationType]注释 /// + /// [animationBuilder]:支持高度自定义动画, 具体可参照[AnimationBuilder]说明 + /// /// [usePenetrate]:true(点击事件将穿透遮罩),false(不穿透) /// /// [useAnimation]:true(使用动画),false(不使用) @@ -131,6 +136,7 @@ class SmartDialog { bool? usePenetrate, bool? useAnimation, SmartAnimationType? animationType, + AnimationBuilder? animationBuilder, Duration? animationTime, Color? maskColor, Widget? maskWidget, @@ -170,6 +176,7 @@ class SmartDialog { alignment: alignment ?? config.custom.alignment, clickMaskDismiss: clickMaskDismiss ?? config.custom.clickMaskDismiss, animationType: animationType ?? config.custom.animationType, + animationBuilder: animationBuilder, usePenetrate: usePenetrate ?? config.custom.usePenetrate, useAnimation: useAnimation ?? config.custom.useAnimation, animationTime: animationTime ?? config.custom.animationTime, @@ -212,6 +219,8 @@ class SmartDialog { /// /// [animationType]:For details, please refer to the [SmartAnimationType] comment /// + /// [animationBuilder]:Support highly custom animation, please refer to [AnimationBuilder] description for details + /// /// [scalePointBuilder]:he zoom point of the zoom animation, the default point is the center point of the attach widget as the zoom point; /// Offset(0, 0): Use the upper left point of the control as the zoom point, /// Offset(attach widget width, 0): Use the upper right point of the control as the zoom point @@ -284,6 +293,8 @@ class SmartDialog { /// /// [animationType]:具体可参照[SmartAnimationType]注释 /// + /// [animationBuilder]:支持高度自定义动画, 具体可参照[AnimationBuilder]说明 + /// /// [scalePointBuilder]:缩放动画的缩放点, 默认点将自定义dialog控件的中心点作为缩放点; /// Offset(0, 0): 将控件左上点作为缩放点, Offset(控件宽度, 0): 将控件右上点作为缩放点 /// Offset(0, 控件高度): 将控件左下点作为缩放点, Offset(控件宽度, 控件高度): 将控件右下点作为缩放点 @@ -334,6 +345,7 @@ class SmartDialog { AlignmentGeometry? alignment, bool? clickMaskDismiss, SmartAnimationType? animationType, + AnimationBuilder? animationBuilder, ScalePointBuilder? scalePointBuilder, bool? usePenetrate, bool? useAnimation, @@ -385,6 +397,7 @@ class SmartDialog { alignment: alignment ?? config.attach.alignment, clickMaskDismiss: clickMaskDismiss ?? config.attach.clickMaskDismiss, animationType: animationType ?? config.attach.animationType, + animationBuilder: animationBuilder, scalePointBuilder: scalePointBuilder, usePenetrate: usePenetrate ?? config.attach.usePenetrate, useAnimation: useAnimation ?? config.attach.useAnimation, @@ -415,6 +428,8 @@ class SmartDialog { /// /// [animationType]:For details, please refer to the [SmartAnimationType] comment /// + /// [animationBuilder]:Support highly custom animation, please refer to [AnimationBuilder] description for details + /// /// [usePenetrate]:true(the click event will penetrate mask), /// false(not penetration) /// @@ -450,6 +465,8 @@ class SmartDialog { /// /// [animationType]:具体可参照[SmartAnimationType]注释 /// + /// [animationBuilder]:支持高度自定义动画, 具体可参照[AnimationBuilder]说明 + /// /// [usePenetrate]:true(点击事件将穿透遮罩),false(不穿透) /// /// [useAnimation]:true(使用动画),false(不使用) @@ -475,6 +492,7 @@ class SmartDialog { SmartDialogController? controller, bool? clickMaskDismiss, SmartAnimationType? animationType, + AnimationBuilder? animationBuilder, bool? usePenetrate, bool? useAnimation, Duration? animationTime, @@ -489,6 +507,7 @@ class SmartDialog { return DialogProxy.instance.showLoading( clickMaskDismiss: clickMaskDismiss ?? config.loading.clickMaskDismiss, animationType: animationType ?? config.loading.animationType, + animationBuilder: animationBuilder, usePenetrate: usePenetrate ?? config.loading.usePenetrate, useAnimation: useAnimation ?? config.loading.useAnimation, animationTime: animationTime ?? config.loading.animationTime, @@ -521,6 +540,8 @@ class SmartDialog { /// /// [animationType]:For details, please refer to the [SmartAnimationType] comment /// + /// [animationBuilder]:Support highly custom animation, please refer to [AnimationBuilder] description for details + /// /// [usePenetrate]:true(the click event will penetrate mask), /// false(not penetration) /// @@ -557,6 +578,8 @@ class SmartDialog { /// /// [animationType]:具体可参照[SmartAnimationType]注释 /// + /// [animationBuilder]:支持高度自定义动画, 具体可参照[AnimationBuilder]说明 + /// /// [usePenetrate]:true(点击事件将穿透遮罩),false(不穿透) /// /// [useAnimation]:true(使用动画),false(不使用) @@ -581,6 +604,7 @@ class SmartDialog { AlignmentGeometry? alignment, bool? clickMaskDismiss, SmartAnimationType? animationType, + AnimationBuilder? animationBuilder, bool? usePenetrate, bool? useAnimation, Duration? animationTime, @@ -596,6 +620,7 @@ class SmartDialog { alignment: alignment ?? config.toast.alignment, clickMaskDismiss: clickMaskDismiss ?? config.toast.clickMaskDismiss, animationType: animationType ?? config.toast.animationType, + animationBuilder: animationBuilder, usePenetrate: usePenetrate ?? config.toast.usePenetrate, useAnimation: useAnimation ?? config.toast.useAnimation, animationTime: animationTime ?? config.toast.animationTime, diff --git a/lib/src/widget/attach_dialog_widget.dart b/lib/src/widget/attach_dialog_widget.dart index 248d7b4..cce8015 100644 --- a/lib/src/widget/attach_dialog_widget.dart +++ b/lib/src/widget/attach_dialog_widget.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/src/data/base_controller.dart'; +import 'package:flutter_smart_dialog/src/util/view_utils.dart'; import 'package:flutter_smart_dialog/src/widget/animation/highlight_mask_animation.dart'; import 'package:flutter_smart_dialog/src/widget/animation/scale_animation.dart'; import 'package:flutter_smart_dialog/src/widget/dialog_scope.dart'; @@ -7,6 +8,7 @@ import 'package:flutter_smart_dialog/src/widget/helper/attach_widget.dart'; import 'package:flutter_smart_dialog/src/widget/helper/mask_event.dart'; import '../config/enum_config.dart'; +import '../data/animation_param.dart'; import 'animation/fade_animation.dart'; import 'animation/size_animation.dart'; @@ -43,6 +45,7 @@ class AttachDialogWidget extends StatefulWidget { required this.alignment, required this.usePenetrate, required this.animationType, + required this.animationBuilder, required this.scalePointBuilder, required this.maskColor, required this.highlightBuilder, @@ -83,6 +86,9 @@ class AttachDialogWidget extends StatefulWidget { /// 仅仅针对中间位置的控件 final SmartAnimationType animationType; + /// 自定义动画 + final AnimationBuilder? animationBuilder; + /// 缩放动画的缩放点 final ScalePointBuilder? scalePointBuilder; @@ -107,6 +113,7 @@ class _AttachDialogWidgetState extends State // animation AnimationController? _maskController; late AnimationController _bodyController; + AnimationParam? _animationParam; // target info RectInfo? _targetRect; @@ -137,6 +144,10 @@ class _AttachDialogWidgetState extends State _bodyController.forward(); } + ViewUtils.addSafeUse(() { + _animationParam?.onForward?.call(); + }); + //bind controller widget.controller._bind(this); } @@ -157,7 +168,9 @@ class _AttachDialogWidgetState extends State beforeBuilder: beforeBuilder, alignment: widget.alignment, originChild: _child, - builder: (Widget child) => _buildBodyAnimation(child), + builder: (Widget child) { + return widget.useAnimation ? _buildBodyAnimation(child) : child; + }, belowBuilder: (targetOffset, targetSize) { return [ //暗色背景widget动画 @@ -231,6 +244,17 @@ class _AttachDialogWidgetState extends State } Widget _buildBodyAnimation(Widget child) { + if (widget.animationBuilder != null) { + return widget.animationBuilder!.call( + _bodyController, + child, + _animationParam = AnimationParam( + alignment: widget.alignment, + animationTime: widget.animationTime, + ), + ); + } + var type = widget.animationType; Widget fade = FadeAnimation(controller: _bodyController, child: child); Widget scale = ScaleAnimation( @@ -273,9 +297,11 @@ class _AttachDialogWidgetState extends State //over animation _maskController!.reverse(); _bodyController.reverse(); + _animationParam?.onDismiss?.call(); + var awaitTime = _bodyController.duration ?? widget.animationTime; if (widget.useAnimation) { - await Future.delayed(widget.animationTime); + await Future.delayed(awaitTime); } } @@ -297,13 +323,6 @@ class AttachDialogController extends BaseController { @override Future dismiss() async { - try { - await _state?.dismiss(); - } catch (e) { - print("-------------------------------------------------------------"); - print("SmartDialog error: ${e.toString()}"); - print("-------------------------------------------------------------"); - } - _state = null; + await _state?.dismiss(); } } diff --git a/lib/src/widget/smart_dialog_widget.dart b/lib/src/widget/smart_dialog_widget.dart index 07a3785..dd5b6e7 100644 --- a/lib/src/widget/smart_dialog_widget.dart +++ b/lib/src/widget/smart_dialog_widget.dart @@ -2,11 +2,13 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/src/data/base_controller.dart'; +import 'package:flutter_smart_dialog/src/util/view_utils.dart'; import 'package:flutter_smart_dialog/src/widget/animation/fade_animation.dart'; import 'package:flutter_smart_dialog/src/widget/animation/scale_animation.dart'; import 'package:flutter_smart_dialog/src/widget/animation/slide_animation.dart'; import '../config/enum_config.dart'; +import '../data/animation_param.dart'; import 'animation/mask_animation.dart'; import 'helper/mask_event.dart'; @@ -21,6 +23,7 @@ class SmartDialogWidget extends StatefulWidget { required this.animationTime, required this.useAnimation, required this.animationType, + required this.animationBuilder, required this.maskColor, required this.maskWidget, required this.maskTriggerType, @@ -30,7 +33,7 @@ class SmartDialogWidget extends StatefulWidget { final Widget child; ///widget controller - final SmartDialogController controller; + final SmartDialogWidgetController controller; /// 点击遮罩 final VoidCallback onMask; @@ -51,6 +54,9 @@ class SmartDialogWidget extends StatefulWidget { /// 仅仅针对中间位置的控件 final SmartAnimationType animationType; + /// 自定义动画 + final AnimationBuilder? animationBuilder; + /// 遮罩颜色 final Color maskColor; @@ -68,6 +74,7 @@ class _SmartDialogWidgetState extends State with TickerProviderStateMixin { AnimationController? _maskController; late AnimationController _bodyController; + AnimationParam? _animationParam; @override void initState() { @@ -91,6 +98,10 @@ class _SmartDialogWidgetState extends State _bodyController.forward(); } + ViewUtils.addSafeUse(() { + _animationParam?.onForward?.call(); + }); + //bind controller widget.controller._bind(this); } @@ -126,6 +137,17 @@ class _SmartDialogWidgetState extends State Widget _buildBodyAnimation() { var child = widget.child; + if (widget.animationBuilder != null) { + return widget.animationBuilder!.call( + _bodyController, + child, + _animationParam = AnimationParam( + alignment: widget.alignment, + animationTime: widget.animationTime, + ), + ); + } + var type = widget.animationType; Widget fade = FadeAnimation(controller: _bodyController, child: child); Widget scale = ScaleAnimation(controller: _bodyController, child: child); @@ -163,8 +185,11 @@ class _SmartDialogWidgetState extends State _maskController!.reverse(); _bodyController.reverse(); + _animationParam?.onDismiss?.call(); + + var awaitTime = _bodyController.duration ?? widget.animationTime; if (widget.useAnimation) { - await Future.delayed(widget.animationTime); + await Future.delayed(awaitTime); } } @@ -178,7 +203,7 @@ class _SmartDialogWidgetState extends State } } -class SmartDialogController extends BaseController { +class SmartDialogWidgetController extends BaseController { _SmartDialogWidgetState? _state; void _bind(_SmartDialogWidgetState _state) { @@ -187,13 +212,6 @@ class SmartDialogController extends BaseController { @override Future dismiss() async { - try { - await _state?.dismiss(); - } catch (e) { - print("-------------------------------------------------------------"); - print("SmartDialog error: ${e.toString()}"); - print("-------------------------------------------------------------"); - } - _state = null; + await _state?.dismiss(); } } diff --git a/pubspec.yaml b/pubspec.yaml index 6de7c80..2e2d305 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: An elegant Flutter Dialog solution, Easily implement Toast, Loading and custom Dialog, Make the use of the dialog easier! -version: 4.5.4+2 +version: 4.5.5 homepage: https://github.com/fluttercandies/flutter_smart_dialog # flutter pub publish --server=https://pub.dartlang.org