一个开源库,随着不断的迭代优化,难免会遇到一个很痛苦的问题
想使得该库更加的强大和健壮,必须要做一个重构
对于flutter_smart_dialog 4.0版本的改动,很多是为了解决自己以前考虑不周的历史遗留,以前这个库的初心,主要是为了解决loading和dialog穿透问题;现在扩展到:custom dialog,attach dialog,loading,toast,最初的设计真的力不从心了,config中的api难以去细分的控制这四个模块功能,一些参数的设计基于现在的功能和场景也不太合理等等
希望大家能够理解我为什么要重构🥺,我绝对不是在搞事情🥺
说明
SmartDialog.compatible.show(); SmartDialog.compatible.showAttach(); SmartDialog.compatible.showLoading(); SmartDialog.compatible.showToast();
SmartDialog.compatible.config;
增加compatible
中间变量,可快速兼容改动的各种参数
快速操作
SmartDialog.show
---> SmartDialog.compatible.show
SmartDialog.config
---> SmartDialog.compatible.config
方法 | 说明 |
---|---|
showLoading(...) | 删除background 参数(compatible不兼容该参数) |
showToast(...) | 删除alignment 参数(compatible不兼容该参数) |
showAttach(...) | 删除highlight 参数(compatible兼容该参数) |
void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: HomePage, // here navigatorObservers: [FlutterSmartDialog.observer], // here builder: FlutterSmartDialog.init( //default toast widget toastBuilder: (String msg) => CustomToastWidget(msg: msg), //default loading widget loadingBuilder: (String msg) => CustomLoadingWidget(msg: msg), ), ); } }
说明
background
和alignment
这俩个参数实在没什么用,用到的频率实在太低了
一般都是自定义toast和loading样式,想怎么画就怎么画;如果只是简单用下toast和loading,这俩个参数做不到很强的自定义效果,实在过于累赘,索性删除了
通过上面兼容API
和参数移除
就可以完整迁移了
这里我将变动的参数名完整的写下,大家可以对照下
原参数名 | 变动参数名 |
---|---|
widget | builder:和路由dialog参数对齐(具体见下面builder参数说明) |
isLoading / isLoadingTemp | animationType:方便后期扩展多种动画类型 |
isPenetrate / isPenetrateTemp | usePenetrate:true(点击事件将穿透背景),false(不穿透) |
isUseAnimation / isUseAnimationTemp | useAnimation:true(使用动画),false(不使用) |
clickBgDismiss / clickBgDismissTemp | clickMaskDismiss:true(点击遮罩后,关闭dialog),false(不关闭) |
animationDuration / animationDurationTemp | animationTime:动画持续时间 |
alignmentTemp | alignment:控制弹窗的位置 |
maskColorTemp | maskColor:遮罩颜色 |
maskWidgetTemp | maskWidget:可高度定制遮罩 |
debounceTemp | debounce:防抖功能 |
time(showToast) | displayTime:toast显示的时间 |
type(showToast) | displayType:toast显示逻辑的多种类型 |
4.0版本对自定义控件参数做了很大改变
SmartDialog.show( widget: Container( height: 80, width: 180, decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(10), ), alignment: Alignment.center, child: Text( 'easy custom dialog', style: TextStyle(color: Colors.white), ), ), );
SmartDialog.show(builder: (context) { return Container( height: 80, width: 180, decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(10), ), alignment: Alignment.center, child: Text( 'easy custom dialog', style: TextStyle(color: Colors.white), ), ); });
这个改动虽然会让使用麻烦了一点,但是有很重要的意义
// 自定义dialog,attach或loading,是否存在在界面上 SmartDialog.config.isExist; // 自定义dialog或attach是否存在在界面上 SmartDialog.config.isExistDialog; // loading是否存在界面上 SmartDialog.config.isExistLoading; // toast是否存在在界面上 SmartDialog.config.isExistToast;
SmartDialog.config ..custom = SmartConfigCustom() ..attach = SmartConfigAttach() ..loading = SmartConfigLoading() ..toast = SmartConfigToast();
SmartDialog.config ..custom = SmartConfigCustom( maskColor: Colors.black.withOpacity(0.35), useAnimation: true, ) ..attach = SmartConfigAttach( animationType: SmartAnimationType.scale, usePenetrate: false, ) ..loading = SmartConfigLoading( clickMaskDismiss: false, leastLoadingTime: const Duration(milliseconds: 0), ) ..toast = SmartConfigToast( intervalTime: const Duration(milliseconds: 100), displayTime: const Duration(milliseconds: 2000), );
说明
这个参数的含义是将SmartDialog将page绑定:如果在SmartDialog上跳转页面
关于在Dialog上面跳转页面的问题,4.0之前的版本,可以使用useSystem
参数解决
useSystem
参数时,本质是使用自带dialog作为载体,这样就可以合理的和page交互useSystem
时:usePenetrate
,tag
,KeepSingle
, permanent
都被禁止使用了4.0版本引入的bindPage的逻辑,可以避免使用useSystem
时的各种限制
bindPage是默认开启的(可在config中配置),也可以在使用show和showAttach时手动关闭或开启;在特殊的业务场景,按需使用bindPage
和useSystem
即可
使用效果
void _dialogBindPage() async { var index = 0; Function()? showDialog; toNewPage(bool useSystem) async { Get.to( () { return Scaffold( appBar: AppBar(title: Text('New Page ${++index}')), body: Container( color: randomColor(), alignment: Alignment.center, child: ElevatedButton( onPressed: () => showDialog?.call(), child: Text('test bindPage $index'), ), ), ); }, preventDuplicates: false, ); } showDialog = () { SmartDialog.show(builder: (_) { return Container( width: 300, height: 170, alignment: Alignment.center, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), ), child: ElevatedButton( onPressed: () => toNewPage(false), child: Text('test bindPage $index'), ), ); }); }; showDialog(); }
该功能和flutter路由关闭,携带返回数据功能对齐
show result
按钮,关闭弹窗,并将输入框中的数据返回void _dialogCarryResult() async { var result = await SmartDialog.show( builder: (_) { var message = ''; return Container( width: 300, height: 170, alignment: Alignment.center, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), ), child: Column(mainAxisSize: MainAxisSize.min, children: [ Container( width: 100, margin: EdgeInsets.only(bottom: 30), child: TextField(onChanged: (msg) => message = msg), ), ElevatedButton( onPressed: () => SmartDialog.dismiss(result: message), child: Text('show result'), ) ]), ); }, ); SmartDialog.showToast("$result"); }
将permanent
参数设置成true,打开的dialog将变成永久化dialog,框架内部所做的所有兜底关闭操作(返回事件,路由pop,点击遮罩等)将失效,只能手动关闭
该功能请结合实际业务场景使用,请勿滥用
SmartDialog.show( permanent: true, usePenetrate: true, builder: (_) => Container(width: 150, height: 150, color: Colors.black), );
SmartDialog.dismiss(force: true);
void _dialogPermanent() async { openPermanentDialog() { SmartDialog.show( permanent: true, alignment: Alignment.centerRight, usePenetrate: true, clickMaskDismiss: false, builder: (_) { return Container( width: 150, height: double.infinity, alignment: Alignment.center, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(20), bottomLeft: Radius.circular(20), ), boxShadow: [ BoxShadow(color: Colors.grey, blurRadius: 8, spreadRadius: 0.2) ], ), child: Text('permanent dialog'), ); }, ); } SmartDialog.show(builder: (_) { return Container( width: 300, height: 170, alignment: Alignment.center, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), ), child: Wrap(spacing: 20, children: [ ElevatedButton( onPressed: () => openPermanentDialog(), child: Text('open'), ), ElevatedButton( onPressed: () => SmartDialog.dismiss(force: true), child: Text('close'), ) ]), ); }); }
permanent dialog
config中loading中有个leastLoadingTime
参数,可以控制最小的加载时间
这个功能是为了解决接口请求太快,导致loading弹窗一闪而过的问题
void _loadingLeastTime() async { SmartDialog.config.loading = SmartConfigLoading( leastLoadingTime: const Duration(seconds: 2), ); SmartDialog.showLoading(); SmartDialog.dismiss(); SmartDialog.config.loading = SmartConfigLoading(); }
当多个toast连续显示的时候,前一个toast和后一个toast显示无间隔时间,看起来有点突兀
此处在SmartConfigToast
中增加了一个intervalTime
参数,用以控制间隔时间
默认的intervalTime
已经是个合理参数,如无必要,最好不要更改
intervalTime
数值就设置稍微大一些void _toastIntervalTime() async { SmartDialog.config.toast = SmartConfigToast( intervalTime: const Duration(milliseconds: 800), ); for (var i = 0; i < 3; i++) { SmartDialog.showToast("toast $i").then((value) { if (!SmartDialog.config.isExistToast) { SmartDialog.config.toast = SmartConfigToast(); } }); } }
SmartDialog 4.0版本是个非常重要的版本,标志着SmartDialog告别了羞涩,走向了成熟
经过这次重构,我也有了信心,去面对更加复杂的业务场景,进行各种拓展
这次重构我做了很多思考,也非常感谢大家给我提个各种issues
,是你们启发了我!