From d1cc768847b1172cdad395f913b1e4b875ff1b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=91=86=E5=91=86666?= Date: Sun, 6 Oct 2024 10:29:28 +0800 Subject: [PATCH] add AdjustBuilder --- CHANGELOG.md | 1 + lib/flutter_smart_dialog.dart | 3 ++ lib/src/custom/custom_dialog.dart | 2 + lib/src/custom/main_dialog.dart | 2 + lib/src/data/attach_model.dart | 28 ++++++++++++ lib/src/helper/dialog_proxy.dart | 2 + lib/src/smart_dialog.dart | 20 ++++++--- lib/src/widget/attach_dialog_widget.dart | 55 ++++++++++++++++++++---- lib/src/widget/helper/attach_widget.dart | 50 ++++++++++++--------- pubspec.yaml | 2 +- 10 files changed, 128 insertions(+), 37 deletions(-) create mode 100644 lib/src/data/attach_model.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index ff8b449..f96fdf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Break change * Delete CompatibleSmartDialog * Delete SmartConfigCustom/SmartConfigAttach/SmartConfigLoading backDismiss +* Add AdjustBuilder * # [4.9.7+x] * optimize bindWidget, when bindWidget is not null, bindPage will be automatically set to false. diff --git a/lib/flutter_smart_dialog.dart b/lib/flutter_smart_dialog.dart index d495f49..1e4277d 100644 --- a/lib/flutter_smart_dialog.dart +++ b/lib/flutter_smart_dialog.dart @@ -8,6 +8,9 @@ export 'src/config/smart_config_loading.dart'; export 'src/config/smart_config_notify.dart'; export 'src/config/smart_config_toast.dart'; export 'src/data/animation_param.dart' show AnimationParam; + +/// model +export 'src/data/attach_model.dart'; export 'src/data/notify_style.dart'; /// dialog diff --git a/lib/src/custom/custom_dialog.dart b/lib/src/custom/custom_dialog.dart index a5d1c5f..4eda69d 100644 --- a/lib/src/custom/custom_dialog.dart +++ b/lib/src/custom/custom_dialog.dart @@ -101,6 +101,7 @@ class CustomDialog extends BaseDialog { required Widget widget, required TargetBuilder? targetBuilder, required ReplaceBuilder? replaceBuilder, + required AdjustBuilder? adjustBuilder, required Alignment alignment, required bool usePenetrate, required bool useAnimation, @@ -149,6 +150,7 @@ class CustomDialog extends BaseDialog { widget: widget, targetBuilder: targetBuilder, replaceBuilder: replaceBuilder, + adjustBuilder: adjustBuilder, alignment: alignment, usePenetrate: usePenetrate, useAnimation: useAnimation, diff --git a/lib/src/custom/main_dialog.dart b/lib/src/custom/main_dialog.dart index 4bbaad9..ead8d51 100644 --- a/lib/src/custom/main_dialog.dart +++ b/lib/src/custom/main_dialog.dart @@ -86,6 +86,7 @@ class MainDialog { required Widget widget, required TargetBuilder? targetBuilder, required ReplaceBuilder? replaceBuilder, + required AdjustBuilder? adjustBuilder, required Alignment alignment, required bool usePenetrate, required bool useAnimation, @@ -111,6 +112,7 @@ class MainDialog { targetContext: targetContext, targetBuilder: targetBuilder, replaceBuilder: replaceBuilder, + adjustBuilder: adjustBuilder, controller: _controller = AttachDialogController(), alignment: alignment, usePenetrate: usePenetrate, diff --git a/lib/src/data/attach_model.dart b/lib/src/data/attach_model.dart new file mode 100644 index 0000000..c6d7f35 --- /dev/null +++ b/lib/src/data/attach_model.dart @@ -0,0 +1,28 @@ +import 'package:flutter/cupertino.dart'; + +class AttachParam { + const AttachParam({ + required this.targetOffset, + required this.targetSize, + required this.selfWidget, + required this.selfOffset, + required this.selfSize, + }); + + final Offset targetOffset; + final Size targetSize; + + final Widget selfWidget; + final Offset selfOffset; + final Size selfSize; +} + +class AttachAdjustParam { + const AttachAdjustParam({ + this.builder, + this.alignment, + }); + + final WidgetBuilder? builder; + final Alignment? alignment; +} diff --git a/lib/src/helper/dialog_proxy.dart b/lib/src/helper/dialog_proxy.dart index e9c2407..9be14ef 100644 --- a/lib/src/helper/dialog_proxy.dart +++ b/lib/src/helper/dialog_proxy.dart @@ -200,6 +200,7 @@ class DialogProxy { required Widget widget, required TargetBuilder? targetBuilder, required ReplaceBuilder? replaceBuilder, + required AdjustBuilder? adjustBuilder, required Alignment alignment, required bool usePenetrate, required bool useAnimation, @@ -236,6 +237,7 @@ class DialogProxy { widget: widget, targetBuilder: targetBuilder, replaceBuilder: replaceBuilder, + adjustBuilder: adjustBuilder, alignment: alignment, usePenetrate: usePenetrate, useAnimation: useAnimation, diff --git a/lib/src/smart_dialog.dart b/lib/src/smart_dialog.dart index e07a3c2..b60c4bb 100644 --- a/lib/src/smart_dialog.dart +++ b/lib/src/smart_dialog.dart @@ -232,10 +232,12 @@ class SmartDialog { /// /// [builder]:the custom dialog /// - /// [replaceBuilder]:The widget returned in [replaceBuilder] will replace the widget returned in [builder]; - /// [replaceBuilder] will callback the offset and size of the target widget and the offset and size of the dialog itself. + /// [replaceBuilder]:deprecated, please use adjustBuilder + /// + /// [adjustBuilder]:The widget returned in [adjustBuilder] will replace the widget returned in [builder]; + /// [adjustBuilder] will callback the offset and size of the target widget and the offset and size of the dialog itself. /// You can customize a suitable replacement widget according to these parameters. - /// It is strongly recommended that the width and height of the custom widget returned by [replaceBuilder] should be consistent with that in [builder], + /// It is strongly recommended that the width and height of the custom widget returned by [adjustBuilder] should be consistent with that in [builder], /// and the positioning information in showAttach is calculated based on the widget in [builder]. /// /// [controller]:this controller can be used to refresh the layout of the custom dialog @@ -326,9 +328,11 @@ class SmartDialog { /// /// [builder]:自定义 dialog /// - /// [replaceBuilder]:[replaceBuilder]中返回widget会替换掉[builder]中返回的widget; - /// [replaceBuilder]将回调目标widget的坐标,大小和dialog自身的坐标,大小,你可以根据这些参数,重新自定义一个合适的替换widget, - /// 强烈建议[replaceBuilder]返回的自定义的widget宽高和[builder]中的保持一致, showAttach中定位信息都是根据[builder]中widget计算得来的 + /// [replaceBuilder]:已废弃, 请使用adjustBuilder + /// + /// [adjustBuilder]:[adjustBuilder]中返回widget会替换掉[builder]中返回的widget; + /// [adjustBuilder]将回调目标widget的坐标,大小和dialog自身的坐标,大小,你可以根据这些参数,重新自定义一个合适的替换widget, + /// 强烈建议[adjustBuilder]返回的自定义的widget宽高和[builder]中的保持一致, showAttach中定位信息都是根据[builder]中widget计算得来的 /// /// [controller]:可使用该控制器来刷新自定义的dialog的布局 /// @@ -401,7 +405,8 @@ class SmartDialog { static Future showAttach({ required BuildContext? targetContext, required WidgetBuilder builder, - ReplaceBuilder? replaceBuilder, + @Deprecated("Please use adjustBuilder") ReplaceBuilder? replaceBuilder, + AdjustBuilder? adjustBuilder, SmartDialogController? controller, TargetBuilder? targetBuilder, Alignment? alignment, @@ -452,6 +457,7 @@ class SmartDialog { ), targetBuilder: targetBuilder, replaceBuilder: replaceBuilder, + adjustBuilder: adjustBuilder, alignment: alignment ?? config.attach.alignment, clickMaskDismiss: clickMaskDismiss ?? config.attach.clickMaskDismiss, animationType: animationType ?? config.attach.animationType, diff --git a/lib/src/widget/attach_dialog_widget.dart b/lib/src/widget/attach_dialog_widget.dart index 35c9789..c51ad79 100644 --- a/lib/src/widget/attach_dialog_widget.dart +++ b/lib/src/widget/attach_dialog_widget.dart @@ -30,6 +30,8 @@ typedef ReplaceBuilder = Widget Function( Size selfSize, ); +typedef AdjustBuilder = AttachAdjustParam Function(AttachParam attachParam); + typedef ScalePointBuilder = Offset Function(Size selfSize); class AttachDialogWidget extends StatefulWidget { @@ -39,6 +41,7 @@ class AttachDialogWidget extends StatefulWidget { required this.targetContext, required this.targetBuilder, required this.replaceBuilder, + required this.adjustBuilder, required this.controller, required this.animationTime, required this.useAnimation, @@ -64,6 +67,8 @@ class AttachDialogWidget extends StatefulWidget { final ReplaceBuilder? replaceBuilder; + final AdjustBuilder? adjustBuilder; + /// 是否使用动画 final bool useAnimation; @@ -186,8 +191,8 @@ class _AttachDialogWidgetState extends State beforeBuilder: beforeBuilder, alignment: widget.alignment, originChild: _child, - builder: (Widget child) { - return _buildBodyAnimation(child); + builder: (Widget child, AttachAdjustParam? adjustParam) { + return _buildBodyAnimation(child, adjustParam); }, belowBuilder: (targetOffset, targetSize) { return [ @@ -219,12 +224,14 @@ class _AttachDialogWidgetState extends State ); } - Widget beforeBuilder( + AttachAdjustParam beforeBuilder( Offset targetOffset, Size targetSize, Offset selfOffset, Size selfSize, ) { + AttachAdjustParam? adjustParam; + //替换控件builder if (widget.replaceBuilder != null) { Widget replaceChildBuilder() { @@ -247,6 +254,32 @@ class _AttachDialogWidgetState extends State } } + // 处理调整组件 + if (widget.adjustBuilder != null) { + adjustParam = widget.adjustBuilder!( + AttachParam( + targetOffset: targetOffset, + targetSize: targetSize, + selfWidget: widget.child, + selfOffset: selfOffset, + selfSize: selfSize, + ), + ); + + final WidgetBuilder? adjustWidgetBuilder = adjustParam.builder; + if (adjustWidgetBuilder != null) { + // 必须要写在DialogScope的builder之外,保证在scalePointBuilder之前触发adjustBuilder + adjustWidgetBuilder(context); + //保证controller能刷新replaceBuilder + if (widget.child is DialogScope) { + _child = DialogScope( + controller: (widget.child as DialogScope).controller, + builder: (context) => adjustWidgetBuilder(context), + ); + } + } + } + //缩放动画的缩放点 if (widget.scalePointBuilder != null) { var halfWidth = selfSize.width / 2; @@ -259,16 +292,20 @@ class _AttachDialogWidgetState extends State _scaleAlignment = Alignment(rateX, rateY); } - return _child; + return AttachAdjustParam( + alignment: adjustParam?.alignment ?? widget.alignment, + builder: (context) => _child, + ); } - Widget _buildBodyAnimation(Widget child) { + Widget _buildBodyAnimation(Widget child, AttachAdjustParam? adjustParam) { + var alignment = adjustParam?.alignment ?? widget.alignment; if (widget.animationBuilder != null) { return widget.animationBuilder!.call( _bodyController, child, _animationParam = AnimationParam( - alignment: widget.alignment, + alignment: alignment, animationTime: widget.animationTime, ), ); @@ -282,7 +319,7 @@ class _AttachDialogWidgetState extends State child: child, ); Widget size = SizeAnimation( - alignment: widget.alignment, + alignment: alignment, controller: _bodyController, child: child, ); @@ -294,13 +331,13 @@ class _AttachDialogWidgetState extends State } else if (type == SmartAnimationType.scale) { animation = scale; } else if (type == SmartAnimationType.centerFade_otherSlide) { - if (widget.alignment == Alignment.center) { + if (alignment == Alignment.center) { animation = fade; } else { animation = size; } } else if (type == SmartAnimationType.centerScale_otherSlide) { - if (widget.alignment == Alignment.center) { + if (alignment == Alignment.center) { animation = scale; } else { animation = size; diff --git a/lib/src/widget/helper/attach_widget.dart b/lib/src/widget/helper/attach_widget.dart index 3a7f7a2..5c70d18 100644 --- a/lib/src/widget/helper/attach_widget.dart +++ b/lib/src/widget/helper/attach_widget.dart @@ -4,9 +4,12 @@ import 'package:flutter_smart_dialog/src/kit/view_utils.dart'; import '../attach_dialog_widget.dart'; -typedef AttachBuilder = Widget Function(Widget child); +typedef AttachBuilder = Widget Function( + Widget child, + AttachAdjustParam? adjustParam, +); -typedef BeforeBuilder = Widget Function( +typedef BeforeBuilder = AttachAdjustParam Function( Offset targetOffset, Size targetSize, Offset selfOffset, @@ -37,7 +40,7 @@ class AttachWidget extends StatefulWidget { /// 自定义坐标点 final TargetBuilder? targetBuilder; - final BeforeBuilder? beforeBuilder; + final BeforeBuilder beforeBuilder; final Alignment alignment; @@ -63,10 +66,13 @@ class _AttachWidgetState extends State { BuildContext? _childContext; late Widget _originChild; + late Alignment _alignment; + AttachAdjustParam? _adjustParam; + @override void initState() { + _alignment = widget.alignment; _resetState(); - super.initState(); } @@ -99,7 +105,7 @@ class _AttachWidgetState extends State { right: _targetRect?.right, top: _targetRect?.top, bottom: _targetRect?.bottom, - child: widget.builder(child), + child: widget.builder(child, _adjustParam), ), //above @@ -137,7 +143,7 @@ class _AttachWidgetState extends State { final screen = MediaQuery.of(context).size; //动画方向及其位置 - final alignment = widget.alignment; + final alignment = _alignment; if (alignment == Alignment.topLeft) { _targetRect = _adjustReactInfo( @@ -199,20 +205,24 @@ class _AttachWidgetState extends State { ); } - if (widget.beforeBuilder != null) { - _originChild = widget.beforeBuilder!.call( - targetOffset, - targetSize, - Offset( - _targetRect?.left != null - ? _targetRect!.left! - : screen.width - ((_targetRect?.right ?? 0) + selfSize.width), - _targetRect?.top != null - ? _targetRect!.top! - : screen.height - ((_targetRect?.bottom ?? 0) + selfSize.height), - ), - selfSize, - ); + AttachAdjustParam adjustParam = _adjustParam = widget.beforeBuilder.call( + targetOffset, + targetSize, + Offset( + _targetRect?.left != null + ? _targetRect!.left! + : screen.width - ((_targetRect?.right ?? 0) + selfSize.width), + _targetRect?.top != null + ? _targetRect!.top! + : screen.height - ((_targetRect?.bottom ?? 0) + selfSize.height), + ), + selfSize, + ); + _originChild = adjustParam.builder?.call(context) ?? _originChild; + if (_alignment != adjustParam.alignment) { + _alignment = adjustParam.alignment ?? Alignment.center; + _handleLocation(); + return; } //第一帧后恢复透明度,同时重置位置信息 diff --git a/pubspec.yaml b/pubspec.yaml index f09d7ff..66d5eda 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.9.8+2 +version: 4.9.8+3 homepage: https://github.com/fluttercandies/flutter_smart_dialog # flutter pub publish --server=https://pub.dartlang.org # flutter build web --release --base-href="/flutter_smart_dialog/web/"