diff --git a/README.md b/README.md index 2bab80c..2407978 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ An elegant Flutter Dialog solution. - **Support positioning widget, display the specified location dialog** - **Support highlight feature,dissolve the specified location mask** -- **Easily implement toast,loading,attach dialog,custome dialog** +- **Easily implement toast,loading,attach dialog,custome dialog,custome notify** # Quick start @@ -88,21 +88,51 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - home: HomePage(), + home: HomePage, // here navigatorObservers: [FlutterSmartDialog.observer], // here builder: FlutterSmartDialog.init( - //default toast widget + //custom default toast widget toastBuilder: (String msg) => CustomToastWidget(msg: msg), - //default loading widget + //custom default loading widget loadingBuilder: (String msg) => CustomLoadingWidget(msg: msg), + //custom default notify widget + notifyStyle: FlutterSmartNotifyStyle( + successBuilder: (String msg) => CustomSuccessWidget(msg: msg), + failureBuilder: (String msg) => CustomFailureWidget(msg: msg), + warningBuilder: (String msg) => CustomWarningWidget(msg: msg), + alertBuilder: (String msg) => CustomAlertWidget(msg: msg), + errorBuilder: (String msg) => CustomErrorWidget(msg: msg), + ), ), ); } } ```` +- SmartDialog supports default global configuration + +```dart +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), + ); +``` + ## Easy usage - **toast usage**💬 @@ -141,55 +171,4 @@ SmartDialog.show(builder: (context) { }); ``` -![dialogEasy](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211102232821.gif) - -# You may have questions - -For details, please check: [Some Consideration Details](https://github.com/fluttercandies/flutter_smart_dialog/blob/master/docs/Some%20Consideration.md) - -![initBack](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092132.gif) - -![hardClose](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092201.gif) - -# Attach Chapter - -For details, please check: [Attach Chapter Details](https://github.com/fluttercandies/flutter_smart_dialog/blob/master/docs/Attach%20Chapter.md) - -This is a very important function. I wanted to add it a long time ago, but it was busy and has been shelved; New Year's Day (2022.1.1) started, and it took some time to complete this function and related demos. - -![attachLocation](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103161314.gif) - -![attachImitate](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103161431.gif) - -![attachGuide](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103161443.gif) - -# Dialog Chapter - -For details, please check: [Dialog Chapter Details](https://github.com/fluttercandies/flutter_smart_dialog/blob/master/docs/Dialog%20Chapter.md) - -![dialogLocation](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092433.gif) - -![dialogPenetrate](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092442.gif) - -![dialogStack](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211106214858.gif) - -# Loading Chapter - -For details, please check: [Loading Chapter Details](https://github.com/fluttercandies/flutter_smart_dialog/blob/master/docs/Loading%20Chapter.md) - -![loadingOne](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092313.gif) - -![loadingSmile](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092359.gif) - -![loadingNormal](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092413.gif) - -# Toast Chapter - -For details, please check: [Toast Chapter Details](https://github.com/fluttercandies/flutter_smart_dialog/blob/master/docs/Toast%20Chapter.md) - -![toastOne](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092214.gif) - -![toastSmart](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092228.gif) - -![toastCustom](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092253.gif) - +![dialogEasy](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211102232821.gif) \ No newline at end of file diff --git a/docs/Attach Chapter.md b/docs/Attach Chapter.md deleted file mode 100644 index ccedf17..0000000 --- a/docs/Attach Chapter.md +++ /dev/null @@ -1,330 +0,0 @@ -# Attach articles - -This is a very important function. I wanted to add it for a long time, but I was busy and shelved it. It took some time to complete this function and related demos when New Year's Day (2022.1.1) started. - -## position - -It is not difficult to locate the coordinates of the target widget; but it is necessary to get the size of the custom widget we passed in, so that the custom widget can be stacked in a more suitable position (through some calculations, the center point is obtained) - -- In fact, Flutter provides a very suitable component `CustomSingleChildLayout`, which also provides offset coordinates function, which is very suitable in theory -- However, the `CustomSingleChildLayout` and `SizeTransition` animation controls have a footprint conflict and can only use the `AnimatedOpacity` fade animation -- Displacement animation can't be used, I can't bear it, I abandoned `CustomSingleChildLayout`; I used all kinds of tricky operations, and finally got the size of the custom widget, which perfectly achieved the effect - -**Locate the dialog, use the showAttach method, the parameter comments are written in great detail, just look at the comments if you don't understand the usage** - -> **Powerful positioning function** - -- The BuildContext of the target widget must be passed, and the coordinates and size of the target widget need to be calculated through it - -````dart -void _attachLocation() { - attachDialog(BuildContext context, Alignment alignment) async { - SmartDialog.showAttach( - targetContext: context, - usePenetrate: true, - alignment: alignment, - clickMaskDismiss: false, - builder: (_) => Container(width: 100, height: 100, color: randomColor()), - ); - await Future.delayed(Duration(milliseconds: 350)); - } - - //target widget - List contextList = []; - List funList = [ - () async => await attachDialog(contextList[0], Alignment.topLeft), - () async => await attachDialog(contextList[1], Alignment.topCenter), - () async => await attachDialog(contextList[2], Alignment.topRight), - () async => await attachDialog(contextList[3], Alignment.centerLeft), - () async => await attachDialog(contextList[4], Alignment.center), - () async => await attachDialog(contextList[5], Alignment.centerRight), - () async => await attachDialog(contextList[6], Alignment.bottomLeft), - () async => await attachDialog(contextList[7], Alignment.bottomCenter), - () async => await attachDialog(contextList[8], Alignment.bottomRight), - ]; - btn({ - required String title, - required Function(BuildContext context) onTap, - }) { - return Container( - margin: EdgeInsets.all(25), - child: Builder(builder: (context) { - Color? color = title.contains('all') ? randomColor() : null; - contextList.add(context); - return Container( - width: 130, - child: ElevatedButton( - style: ButtonStyle( - backgroundColor: ButtonStyleButton.allOrNull(color), - ), - onPressed: () => onTap(context), - child: Text('$title'), - ), - ); - }), - ); - } - - SmartDialog.show(builder: (_) { - return Container( - width: 700, - padding: EdgeInsets.all(50), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.white, - ), - child: SingleChildScrollView( - child: Wrap(alignment: WrapAlignment.spaceEvenly, children: [ - btn(title: 'topLeft', onTap: (context) => funList[0]()), - btn(title: 'topCenter', onTap: (context) => funList[1]()), - btn(title: 'topRight', onTap: (context) => funList[2]()), - btn(title: 'centerLeft', onTap: (context) => funList[3]()), - btn(title: 'center', onTap: (context) => funList[4]()), - btn(title: 'centerRight', onTap: (context) => funList[5]()), - btn(title: 'bottomLeft', onTap: (context) => funList[6]()), - btn(title: 'bottomCenter', onTap: (context) => funList[7]()), - btn(title: 'bottomRight', onTap: (context) => funList[8]()), - btn( - title: 'allOpen', - onTap: (_) async { - for (var item in funList) await item(); - }, - ), - btn( - title: 'allClose', - onTap: (_) => SmartDialog.dismiss(status: SmartStatus.allAttach), - ), - ]), - ), - ); - }); -} -```` - -![attachLocation](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224738.gif) - -The animation effect and the show method are almost the same. For this consistent experience, a lot of targeted optimizations have been made internally. - -> **Custom coordinate points** - -- In most cases, targetContext is basically used - -````dart -SmartDialog.showAttach( - targetContext: context, - builder: (_) => Container(width: 100, height: 100, color: Colors.red), -); -```` - -- Of course, there are still a few cases where custom coordinates need to be used. The targetBuilder parameter is also provided here: if the targetBuilder parameter is set, the targetContext will automatically become invalid. - - targetContext is a very common scenario, so here it is set as a mandatory parameter - - The callback parameters in targetBuilder are also calculated from targetContext - - In some special cases, the targetContext can be set to be empty, and the default value of the callback parameter in targetBuilder is zero - -````dart -SmartDialog.showAttach( - targetContext: widget, - target: Offset(100, 100);, - builder: (_) => Container(width: 100, height: 100, color: Colors.red), -); -```` - -- It seems that the custom coordinate point effect - -````dart -void _attachPoint() async { - targetDialog(Offset offset) { - var random = Random().nextInt(100) % 5; - var alignment = Alignment.topCenter; - if (random == 0) alignment = Alignment.topCenter; - if (random == 1) alignment = Alignment.centerLeft; - if (random == 2) alignment = Alignment.center; - if (random == 3) alignment = Alignment.centerRight; - if (random == 4) alignment = Alignment.bottomCenter; - SmartDialog.showAttach( - targetContext: null, - targetBuilder: (_, __) => offset, - usePenetrate: true, - clickMaskDismiss: false, - alignment: alignment, - keepSingle: true, - builder: (_) { - return ClipRRect( - borderRadius: BorderRadius.circular(10), - child: Container(width: 100, height: 100, color: randomColor()), - ); - }, - ); - } - - SmartDialog.show(builder: (_) { - return Container( - width: 600, - height: 400, - alignment: Alignment.center, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.white, - ), - child: GestureDetector( - onTapDown: (detail) => targetDialog(detail.globalPosition), - child: Container( - width: 500, - height: 300, - color: Colors.grey, - alignment: Alignment.center, - child: Text('click me', style: TextStyle(color: Colors.white)), - ), - ), - ); - }); -} -```` - -'targetBuilder is a very powerful param. Combine it with the 'scalePointBuilder' param to make a lot of very interesting bubble dialog. - -![attachPoint](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224747.gif) - -> **Imitate DropdownButton** - -- Actually imitating DropdownButton is not easy - - First calculate the position of the DropdownButton control and display the clicked collapsed control on its position - - Need to handle the click event of the area outside the DropdownButton (close the DropdownButton outside the click area) - - You also need to listen to the return event and manually pop the routing event; for this type of event, you need to close the DropdownButton - -- This thing needs to be customized, which is quite annoying; however, now you can use `SmartDialog.showAttach` to easily imitate one, and the above points need to be taken care of for you - -````dart -void _attachImitate() { - //Imitate DropdownButton - imitateDialog(BuildContext context) { - var list = ['Little Dude', 'Little Feifei', 'Little Pig']; - SmartDialog.showAttach( - targetContext: context, - usePenetrate: true, - builder: (_) { - return Container( - margin: EdgeInsets.all(10), - decoration: BoxDecoration(boxShadow: [ - BoxShadow(color: Colors.black12, blurRadius: 8, spreadRadius: 0.2) - ]), - child: Column( - children: List.generate(list.length, (index) { - return Material( - color: Colors.white, - child: InkWell( - onTap: () => SmartDialog.dismiss(), - child: Container( - height: 50, - width: 100, - alignment: Alignment.center, - child: Text('${list[index]}'), - ), - ), - ); - }), - ), - ); - }, - ); - } - - //imitate widget - dropdownButton({String title = 'Dropdown'}) { - return DropdownButton( - value: '1', - items: [ - DropdownMenuItem(value: '1', child: Text('$title: Xiao Dian')), - DropdownMenuItem(value: '2', child: Text('Little Feifei')), - DropdownMenuItem(value: '3', child: Text('Piggy')) - ], - onChanged: (value) {}, - ); - } - - imitateDropdownButton() { - return Builder(builder: (context) { - return Stack(children: [ - dropdownButton(title: 'Attach'), - InkWell( - onTap: () => imitateDialog(context), - child: Container(height: 50, width: 140, color: Colors.transparent), - ) - ]); - }); - } - - SmartDialog.show(builder: (_) { - return Container( - width: 600, - height: 400, - alignment: Alignment.center, - margin: EdgeInsets.all(20), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.white, - ), - child: MaterialApp( - debugShowCheckedModeBanner: false, - home: Container( - padding: EdgeInsets.symmetric(horizontal: 100), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [dropdownButton(), imitateDropdownButton()], - ), - ), - ), - ); - }); -} -```` - -![attachImitate](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224755.gif) - -## highlight - -This time, the function of highlighting a specific area of the mask has been added, which is a very practical function! - -- You just need to set the `highlightBuilder` parameter -- Define the highlighted area, it must be an opaque Widget, such as Contaienr, a color must be set (no color value required) - - You can also use pictures of all kinds of strange shapes, so that you can show the highlighted areas of various complex shapes -- The return type of `highlightBuilder` is Positioned, you can position any area on the screen that needs to be highlighted -- You can quickly get the coordinates and size of the target widget through the parameters of the `highlightBuilder` callback - -````dart -SmartDialog.showAttach( - targetContext: context, - alignment: Alignment.bottomCenter, - highlightBuilder: (Offset targetOffset, Size targetSize) { - return Positioned( - top: targetOffset.dy - 10, - left: targetOffset.dx - 10, - child: Container( - height: targetSize.height + 20, - width: targetSize.width + 20, - color: Colors.white, - ), - ); - }, - builder: (_) => Container(width: 100, height: 100, color: Colors.red), -) -```` - -> **Actual business scenarios** - -- Here are two common examples. The code is a little too much, so I won't post it. If you are interested, please check: [flutter_use](https://github.com/xdd666t/flutter_use) - -![attachBusiness](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224803.gif) - -The above two business scenarios are very common. Sometimes, we need to be above or below the target widget or a specific area without being covered by a mask. - -If you do it yourself, you can do it, but it will be cumbersome; now you can easily achieve this using the `highlightBuilder` parameter in `showAttach` - -> **Guide Actions** - -Guidance operations are still very common in apps, and you need to specify the area to highlight, and then introduce its functions - -- Using the `highlightBuilder` parameter in `showAttach` can also easily achieve this requirement, see the effect - - The code is also a little bit more, if you are interested, please check: [flutter_use](https://github.com/xdd666t/flutter_use) - -![attachGuide](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224816.gif) diff --git a/docs/Dialog Chapter.md b/docs/Dialog Chapter.md deleted file mode 100644 index 5433553..0000000 --- a/docs/Dialog Chapter.md +++ /dev/null @@ -1,130 +0,0 @@ -# Dialog articles - -## bells and whistles - -> The dialog pops up from different positions, and the animation is different - -![image-20211031221419600](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224824.png) - -- alignment: If this parameter is set differently, the animation effect will be different - -````dart -void _dialogLocation() async { - locationDialog({ - required Alignment alignment, - double width = double.infinity, - double height = double.infinity, - }) async { - SmartDialog.show( - alignment: alignment, - builder: (_) => Container(width: width, height: height, color: randomColor()), - ); - await Future.delayed(Duration(milliseconds: 500)); - } - - //left - await locationDialog(width: 70, alignment: Alignment.centerLeft); - //top - await locationDialog(height: 70, alignment: Alignment.topCenter); - //right - await locationDialog(width: 70, alignment: Alignment.centerRight); - //bottom - await locationDialog(height: 70, alignment: Alignment.bottomCenter); - //center - await locationDialog(height: 100, width: 100, alignment: Alignment.center); -} -```` - -![dialogLocation](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224832.gif) - -- usePenetrate: Interaction events penetrate the mask - -````dart -SmartDialog.show( - alignment: Alignment.centerRight, - usePenetrate: true, - clickMaskDismiss: false, - builder: (_) { - return Container( - width: 80, - height: double.infinity, - color: randomColor(), - ); - }, -); -```` - -![dialogPenetrate](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224839.gif) - -## dialog stack - -- This is a powerful and practical function: you can easily close a pop-up window at a fixed point - -````dart -void _dialogStack() async { - stackDialog({ - required Alignment alignment, - required String tag, - double width = double.infinity, - double height = double.infinity, - }) async { - SmartDialog.show( - tag: tag, - alignment: alignment, - builder: (_) { - return Container( - width: width, - height: height, - color: randomColor(), - alignment: Alignment.center, - child: Text('dialog $tag', style: TextStyle(color: Colors.white)), - ); - }, - ); - await Future.delayed(Duration(milliseconds: 500)); - } - - //left - await stackDialog(tag: 'A', width: 70, alignment: Alignment.centerLeft); - //top - await stackDialog(tag: 'B', height: 70, alignment: Alignment.topCenter); - //right - await stackDialog(tag: 'C', width: 70, alignment: Alignment.centerRight); - //bottom - await stackDialog(tag: 'D', height: 70, alignment: Alignment.bottomCenter); - - //center: the stack handler - SmartDialog.show( - alignment: Alignment.center, - builder: (_) { - return Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - ), - padding: EdgeInsets.symmetric(horizontal: 30, vertical: 20), - child: Wrap(spacing: 20, children: [ - ElevatedButton( - child: Text('close dialog A'), - onPressed: () => SmartDialog.dismiss(tag: 'A'), - ), - ElevatedButton( - child: Text('close dialog B'), - onPressed: () => SmartDialog.dismiss(tag: 'B'), - ), - ElevatedButton( - child: Text('close dialog C'), - onPressed: () => SmartDialog.dismiss(tag: 'C'), - ), - ElevatedButton( - child: Text('close dialog D'), - onPressed: () => SmartDialog.dismiss(tag: 'D'), - ), - ]), - ); - }, - ); -} -```` - -![dialogStack](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224848.gif) diff --git a/docs/Loading Chapter.md b/docs/Loading Chapter.md deleted file mode 100644 index 9eef8a7..0000000 --- a/docs/Loading Chapter.md +++ /dev/null @@ -1,237 +0,0 @@ -# Loading articles - -## Pit Avoidance Guide - -- After loading is turned on, it can be turned off using the following methods - - SmartDialog.dismiss(): can close loading and dialog - - status is set to SmartStatus.loading: just turn off loading - -````dart -// easy close -SmartDialog.dismiss(); -// exact close -SmartDialog.dismiss(status: SmartStatus.loading); -```` - -- Generally speaking, the loading pop-up window is encapsulated in the network library, and automatically opens and closes with the request status - - Based on this scenario, I suggest: when using dismiss, add the status parameter and set it to: SmartStatus.loading -- pit ratio scene - - When the network request is loaded, the loading is also turned on. At this time, it is easy to touch the back button by mistake and close the loading - - When the network request ends, the dismiss method will be called automatically - - Because loading has been closed, assuming that the page has a SmartDialog pop-up window at this time, dismiss without setting status will close the SmartDialog pop-up window - - Of course, this situation is easy to solve, encapsulate the loading of the network library, use: `SmartDialog.dismiss(status: SmartStatus.loading);` to close it -- The `status` parameter is a parameter designed to accurately close the corresponding type of pop-up window, which can play a huge role in some special scenarios - - If you understand the meaning of this parameter, then you must be confident about when to add the `status` parameter - -## Parameter Description - -The parameters are very detailed in the comments, so I won't go into details, let's see the effect - -- maskWidget: Powerful mask customization function 😆, use your brains. . . - -````dart -var maskWidget = Container( - width: double.infinity, - height: double.infinity, - child: Opacity( - opacity: 0.6, - child: Image.network( - 'https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211101103911.jpeg', - fit: BoxFit.fill, - ), - ), -); -SmartDialog.showLoading(maskWidget: maskWidget); -```` - -![loadingOne](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224902.gif) - -- maskColor: supports quick custom mask color - -````dart -SmartDialog.showLoading(maskColor: randomColor().withOpacity(0.3)); - -/// random color -Color randomColor() => Color.fromRGBO(Random().nextInt(256), Random().nextInt(256), Random().nextInt(256), 1); -```` - -![loadingTwo](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224910.gif) - -- animationType: animation effect switching - -````dart -SmartDialog.showLoading(animationType: SmartAnimationType.scale); -```` - -![loadingFour](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224929.gif) - -- usePenetrate: Interaction events can penetrate the mask, which is a very useful function and is critical for some special demand scenarios - -````dart -SmartDialog.showLoading(usePenetrate: true); -```` - -![loadingFive](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224945.gif) - -## Custom Loading - -Use `showLoading` to easily customize a powerful loading pop-up window; I have limited brains, so I will simply demonstrate - -> **Customize a loading layout** - -````dart -class CustomLoading extends StatefulWidget { - const CustomLoading({Key? key, this.type = 0}) : super(key: key); - - final int type; - - @override - _CustomLoadingState createState() => _CustomLoadingState(); -} - -class _CustomLoadingState extends State - with TickerProviderStateMixin { - late AnimationController _controller; - - @override - void initState() { - _controller = AnimationController( - duration: const Duration(milliseconds: 800), - vsync: this, - ); - _controller.forward(); - _controller.addStatusListener((status) { - if (status == AnimationStatus.completed) { - _controller.reset(); - _controller.forward(); - } - }); - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Stack(children: [ - // smile - Visibility(visible: widget.type == 0, child: _buildLoadingOne()), - - // icon - Visibility(visible: widget.type == 1, child: _buildLoadingTwo()), - - // normal - Visibility(visible: widget.type == 2, child: _buildLoadingThree()), - ]); - } - - Widget _buildLoadingOne() { - return Stack(alignment: Alignment.center, children: [ - RotationTransition( - alignment: Alignment.center, - turns: _controller, - child: Image.network( - 'https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211101174606.png', - height: 110, - width: 110, - ), - ), - Image.network( - 'https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211101181404.png', - height: 60, - width: 60, - ), - ]); - } - - Widget _buildLoadingTwo() { - return Stack(alignment: Alignment.center, children: [ - Image.network( - 'https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211101162946.png', - height: 50, - width: 50, - ), - RotationTransition( - alignment: Alignment.center, - turns: _controller, - child: Image.network( - 'https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211101173708.png', - height: 80, - width: 80, - ), - ), - ]); - } - - Widget _buildLoadingThree() { - return Center( - child: Container( - height: 120, - width: 180, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(15), - ), - alignment: Alignment.center, - child: Column(mainAxisSize: MainAxisSize.min, children: [ - RotationTransition( - alignment: Alignment.center, - turns: _controller, - child: Image.network( - 'https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211101163010.png', - height: 50, - width: 50, - ), - ), - Container( - margin: EdgeInsets.only(top: 20), - child: Text('loading...'), - ), - ]), - ), - ); - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } -} -```` - -> **Let's see the effect** - -- effect one - -````dart -SmartDialog.showLoading( - animationType: SmartAnimationType.scale, - builder: (_) => CustomLoading(), -); -await Future.delayed(Duration(seconds: 2)); -SmartDialog.dismiss(); -```` - -![loadingSmile](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224959.gif) - -- Effect two - -````dart -SmartDialog.showLoading( - animationType: SmartAnimationType.scale, - builder: (_) => CustomLoading(type: 1), -); -await Future.delayed(Duration(seconds: 2)); -SmartDialog.dismiss(); -```` - -![loadingIcon](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103225006.gif) - -- Effect three - -````dart -SmartDialog.showLoading(builder: (_) => CustomLoading(type: 2)); -await Future.delayed(Duration(seconds: 2)); -SmartDialog.dismiss(); -```` - -![loadingNormal](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103225013.gif) diff --git a/docs/Some Consideration.md b/docs/Some Consideration.md deleted file mode 100644 index 94a91fe..0000000 --- a/docs/Some Consideration.md +++ /dev/null @@ -1,143 +0,0 @@ -# Questions you may have - -When initializing the framework, compared to before, I actually asked everyone to write one more parameter (without setting the custom default toast and loading styles), I feel very guilty 😩 - -Closing a page is inherently a more complex situation involving - -- Physical return button -- AppBar's back button -- Manual pop - -In order to monitor these situations, a route monitoring parameter was added as a last resort. - -> **Entity return key** - -The monitoring of the return button is very important and can basically cover most situations - -![initBack](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103224708.gif) - -> **pop route** - -Although the monitoring of the return button can cover most scenarios, some manual pop scenarios require additional parameter monitoring - -- do not add `FlutterSmartDialog.observer` - - If the penetration parameter is turned on (you can interact with the page after the pop-up window), then manually close the page - - This is an embarrassing situation - -![initPopOne](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103225804.gif) - -- Add `FlutterSmartDialog.observer`, it can be handled reasonably - - Of course, the transition animation here also provides parameter control whether to enable 😉 - -![initPopTwo](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103225825.gif) - -> **About FlutterSmartDialog.init()** - -This method will not occupy your builder parameters. The builder is called back from init, and you can continue to use it with confidence. - -- For example: continue to set Bloc global instance 😄 - -````dart -class MyApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return MaterialApp( - home: HomePage, - navigatorObservers: [FlutterSmartDialog.observer], - builder: FlutterSmartDialog.init(builder: _builder), - ); - } -} - -Widget _builder(BuildContext context, Widget? child) { - return MultiBlocProvider( - providers: [ - BlocProvider.value(value: BlocSpanOneCubit()), - ], - child: child!, - ); -} -```` - -> **Super useful parameter: backDismiss** - -- This parameter is set to true by default, and the pop-up window will be closed by default when returning; if it is set to false, the page will not be closed - - This makes it very easy to make an emergency pop-up window that prohibits the user's next action -- Let's look at a scenario: Suppose an open source author decides to abandon the software and does not allow users to use the software's pop-up window - -````dart -SmartDialog.show( - backDismiss: false, - clickMaskDismiss: false, - builder: (_) { - return Container( - height: 480, - width: 500, - padding: EdgeInsets.all(20), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Colors.white, - ), - alignment: Alignment.topCenter, - child: SingleChildScrollView( - child: Wrap( - direction: Axis.vertical, - crossAxisAlignment: WrapCrossAlignment.center, - spacing: 10, - children: [ - // title - Text( - 'Extraordinary announcement', - style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold), - ), - // content - Text('I studied the following cheats day and night, and finally managed to catch a rich woman'), - Image.network( - 'https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211102213746.jpeg', - height: 200, - width: 400, - ), - Text('I thought about it for three seconds, and with a \'heavy\' mind, decided to abandon this open source software'), - Text('My future life is a rich woman and a distant place, I have no \'energy\' to maintain this open source software'), - Text('Everyone's hair, goodbye in the rivers and lakes!'), - // button (only method of close the dialog) - ElevatedButton( - onPressed: () => SmartDialog.dismiss(), - child: Text('Goodbye!'), - ) - ], - ), - ), - ); - }, -); -```` - -![hardClose](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103225957.gif) - -It can be seen from the above renderings that - -- Click on the mask to close the popup -- Clicking the back button does not close the popup -- Only click our own button to close the pop-up window. The logic of clicking the button can be directly written as closing the app, etc. - -Only two simple parameter settings are needed to achieve such a great emergency pop-up window - -> **Set global parameters** - -The global parameters of SmartDialog have a reasonable default value - -In order to cope with changing scenarios, you can modify the global parameters that meet your own requirements - -- Set the data that meets your requirements, put it in the app entry and initialize it - - Note: If there are no special requirements, you can not initialize global parameters (there are default values inside) - -````dart -SmartDialog.config - ..custom = SmartConfigCustom() - ..attach = SmartConfigAttach() - ..loading = SmartConfigLoading() - ..toast = SmartConfigToast(); -```` - -- The comments of the code are very well written. If you don't understand a certain parameter, just click in and take a look. diff --git a/docs/Toast Chapter.md b/docs/Toast Chapter.md deleted file mode 100644 index a2ba93c..0000000 --- a/docs/Toast Chapter.md +++ /dev/null @@ -1,98 +0,0 @@ -# Toast Chapter - -## The particularity of toast - -Strictly speaking, toast is a very special pop-up window, I think it should have the following characteristics - -> **Toast messages should be displayed one by one, and subsequent messages should not top off the previous toast** - -- This is a pit. If the inside of the frame is not processed, it is easy to cause the toast in the back to directly top off the toast in the front - - Of course, the type parameter is provided internally, you can choose the display logic you want - - -![toastOne](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103225022.gif) - -> **Displayed on the top layer of the page, should not be blocked by some pop-up windows and the like** - -- It can be found that the layout of loading and dialog masks, etc., do not block the toast information - -![toastTwo](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20220103225028.gif) - -> **Handle the keyboard occlusion situation** - -- The keyboard is a bit pitted, it will directly block all layouts, and it can only save the country with curves - - A special treatment is made here, when the keyboard is invoked, the toast will dynamically adjust the distance between itself and the bottom of the screen - - This will play a role, the keyboard will not block the toast effect - -![toastSmart](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092228.gif) - -## Custom Toast - -> **Parameter description** - -Some parameters of toast are not exposed, only msg is exposed - -- For example: toast font size, font color, toast background color, etc., no parameters are provided - - First, I feel that providing these parameters will make the overall parameter input very large, and the random flowers will gradually enter the charming eyes. - - The second is that even if I provide a lot of parameters, it may not meet those strange aesthetics and needs -- Based on the above considerations, I directly provided a large number of low-level parameters - - You can customize the toast as you like - - Note, not only toast can be customized, such as: success prompt, failure prompt, warning prompt, etc. - - Toast has done a lot of optimization, the `displayType` parameter allows you to have a variety of display logic, use your imagination - - Note: the `builder` parameter is used, the `msg` parameter will be invalid - -> **More powerful custom toast** - -- First, a whole custom toast - -````dart -class CustomToast extends StatelessWidget { - const CustomToast(this.msg, {Key? key}) : super(key: key); - - final String msg; - - @override - Widget build(BuildContext context) { - return Align( - alignment: Alignment.bottomCenter, - child: Container( - margin: EdgeInsets.only(bottom: 30), - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 7), - decoration: BoxDecoration( - color: _randomColor(), - borderRadius: BorderRadius.circular(100), - ), - child: Row(mainAxisSize: MainAxisSize.min, children: [ - //icon - Container( - margin: EdgeInsets.only(right: 15), - child: Icon(Icons.add_moderator, color: _randomColor()), - ), - - //msg - Text('$msg', style: TextStyle(color: Colors.white)), - ]), - ), - ); - } - - Color _randomColor() { - return Color.fromRGBO( - Random().nextInt(256), - Random().nextInt(256), - Random().nextInt(256), - 1, - ); - } -} -```` - -- use - -````dart -SmartDialog.showToast('', builder: (_) => CustomToast('custom toast')); -```` - -- Effect - -![toastCustom](https://raw.githubusercontent.com/xdd666t/MyData/master/pic/flutter/blog/20211103092253.gif)