An open source library, with continuous iterative optimization, will inevitably encounter a very painful problem
- The original design was not very reasonable: a lot of new features that I wanted to add were hindered by this
To make the library more powerful and robust, a refactoring must be done
- Because the refactoring involves exposed APIs, everyone will encounter a more irritating problem: after updating the version, a large number of errors will be reported
- I have been thinking about it for a long time. How can I help you to migrate quickly? Finally came up with a reasonable solution
For the changes of flutter_smart_dialog version 4.0, many of them are to solve the historical legacy that I have not considered before. The original intention of this library was mainly to solve the problem of loading and dialog penetration; now it is extended to: custom dialog, attach dialog, loading, toast , the initial design is really inadequate, the API in config is difficult to subdivide the functions of these four modules, and the design of some parameters is not reasonable based on the current functions and scenarios, etc.
I hope everyone can understand why I want to refactor 🥺, I am definitely not doing things 🥺
Description
- show method is fast compatible
SmartDialog.compatible.show();
SmartDialog.compatible.showAttach();
SmartDialog.compatible.showLoading();
SmartDialog.compatible.showToast();
- config fast compatibility
SmartDialog.compatible.config;
Add the compatible
intermediate variable, which can quickly compatible with the changed parameters
Quick Actions
- Quick migration using global replace function:
SmartDialog.show
--->SmartDialog.compatible.show
- Mac: command + shift + r
- Windows: ctrl + shift + r
- Config:
SmartDialog.config
--->SmartDialog.compatible.config
- Mac: command + shift + r
- Windows: ctrl + shift + r
- Version 4.0 removed a few parameters
Method | Description |
---|---|
showLoading(...) | remove background parameter (not compatible with this parameter) |
showToast(...) | remove alignment parameter (compatible not compatible) |
showAttach(...) | remove highlight parameter (compatible with this parameter) |
- These parameters are removed, and a little adjustment is required when initializing custom loading and toast
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),
),
);
}
}
Description
The two parameters background
and alignment
are really useless, the frequency of use is too low
Generally, the toast and loading styles are customized, and you can draw as you want; if you simply use toast and loading, these two parameters cannot achieve a strong custom effect, which is too cumbersome and simply deleted.
Complete migration is possible through the above compatible API
and parameter removal
Here I will write down the changed parameter names completely, you can compare them
Original parameter name | Changed parameter name |
---|---|
widget | builder: Align with the routing dialog parameter (see the builder parameter description below for details) |
isLoading / isLoadingTemp | animationType: It is convenient to expand various animation types later |
isPenetrate / isPenetrateTemp | usePenetrate: true (click events will penetrate the background), false (not penetrate) |
isUseAnimation / isUseAnimationTemp | useAnimation: true (use animation), false (do not use) |
clickBgDismiss / clickBgDismissTemp | clickMaskDismiss: true (dismiss the dialog after clicking on the mask), false (do not close) |
animationDuration / animationDurationTemp | animationTime: animation duration |
alignmentTemp | alignment: controls the position of the popup window |
maskColorTemp | maskColor: mask color |
maskWidgetTemp | maskWidget: Highly customizable mask |
debounceTemp | debounce: Anti-shake function |
time(showToast) | displayTime:time displayed by toast |
type(showToast) | displayType:multi types of toast display logic |
Version 4.0 has made a lot of changes to custom control parameters
- old version
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),
),
),
);
- Version 4.0
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),
),
);
});
Although this change will make it a little more troublesome to use, it is very important.
- The first is to align with the api of the routing dialog, and the custom control parameters of the routing dialog are also builder
- Then solve the problem of dynamic refresh of the custom dialog itself: the custom layout has TextField, when the keyboard pops up, the custom dialog layout can dynamically adjust the distance (need to use the corresponding widget)
- You can use config to get whether the dialog exists
// Customize dialog, attach or loading, whether it exists on the interface
SmartDialog.config.isExist;
// Whether the custom dialog or attach exists on the interface
SmartDialog.config.isExistDialog;
// Whether loading exists on the interface
SmartDialog.config.isExistLoading;
// Whether toast exists on the interface
SmartDialog.config.isExistToast;
- config can control show, showAttach, showLoading, showToast and other pop-up windows in more detail
- The default parameters of SmartConfigXxx() are all set by me after deep thinking, no additional settings are required without special requirements
- If you do not need to customize the config value, the initialization code below does not need to be written
SmartDialog.config
..custom = SmartConfigCustom()
..attach = SmartConfigAttach()
..loading = SmartConfigLoading()
..toast = SmartConfigToast();
- You can customize the values in any config to meet the corresponding needs
- The code below is to demonstrate custom parameters
- You can set as needed
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),
);
Description
The meaning of this parameter is to bind the SmartDialog to the page: if the page is jumped on the SmartDialog
- Binding SmartDialog with the current page will automatically hide
- When returning to the binding page, the SmartDialog will be displayed
Regarding the problem of jumping pages on the Dialog, the version before 4.0 can be solved by using the useSystem
parameter
- When using the
useSystem
parameter, the essence is to use the built-in dialog as a carrier, so that you can interact with the page reasonably - But due to various limitations of the built-in dialog, when using
useSystem
:usePenetrate
,tag
,KeepSingle
,permanent
are all forbidden to use
The logic of bindPage introduced in version 4.0 can avoid various restrictions when using useSystem
bindPage is enabled by default (can be configured in config), and can also be manually disabled or enabled when using show and showAttach; in special business scenarios, bindPage
and useSystem
can be used as needed
Use effects
- Write a demo, this is the normal operation of jumping pages on the pop-up window
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();
}
- to see the effect
- Honestly, the effect is silky without the useSystem function
- But bindPage also solves the problem of jumping pages on the pop-up window, while retaining the functions of usePenetrate, tag, KeepSingle, permanent and so on
- Everyone needs to use
This function is closed with flutter routing, and the function of carrying return data is aligned
- Take a look at the demo: Click the
show result
button to close the popup and return the data in the input box
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");
}
- Effect
Set the permanent
parameter to true, the opened dialog will become a permanent dialog, and all closing operations (returning events, routing pops, clicking masks, etc.) inside the framework will be invalid and can only be closed manually
Please use this function in combination with actual business scenarios and do not abuse it
- open a permanent dialog
SmartDialog.show(
permanent: true,
usePenetrate: true,
builder: (_) => Container(width: 150, height: 150, color: Colors.black),
);
- Turn off permanent dialog
SmartDialog.dismiss(force: true);
- Take a look at the demo
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'),
)
]),
);
});
}
- Effect: You can see the pop route, click on the mask and return events, but you cannot close the
permanent dialog
There is a leastLoadingTime
parameter in loading in config, which can control the minimum loading time
This function is to solve the problem that the interface request is too fast, causing the loading pop-up window to flash by.
- Use: Please set appropriate data for this parameter according to the actual business scenario. The default value of leastLoadingTime is 0 seconds.
- This is only for demonstration, and config.loading is reassigned here. Generally, it is recommended to set the parameters in the app initialization position
- Call dismiss immediately after showLoading(), and loading will flash by
- Set the leastLoadingTime to 2 seconds, the loading will be forced to wait for two seconds before the dismiss will take effect
void _loadingLeastTime() async {
SmartDialog.config.loading = SmartConfigLoading(
leastLoadingTime: const Duration(seconds: 2),
);
SmartDialog.showLoading();
SmartDialog.dismiss();
SmartDialog.config.loading = SmartConfigLoading();
}
- Effect
When multiple toasts are displayed continuously, the previous toast and the next toast display no interval time, which looks a bit awkward
Here an intervalTime
parameter is added to SmartConfigToast
to control the interval time
The default intervalTime
is already a reasonable parameter, if not necessary, it is best not to change
- Take a look at the effect, just for demonstration, the value of
intervalTime
is set slightly larger
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();
}
});
}
}
- renderings
SmartDialog 4.0 version is a very important version, marking SmartDialog bid farewell to shyness and become mature
After this reconstruction, I also have the confidence to face more complex business scenarios and carry out various expansions.
I have done a lot of thinking about this refactoring, and I am very grateful to everyone for giving me various issues
, you have inspired me!