progress_dialog.dart 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. import 'package:flutter/material.dart';
  2. enum ProgressDialogType { normal, download }
  3. String _dialogMessage = "Loading...";
  4. double _progress = 0.0, _maxProgress = 100.0;
  5. Widget? _customBody;
  6. TextAlign _textAlign = TextAlign.left;
  7. Alignment _progressWidgetAlignment = Alignment.centerLeft;
  8. TextDirection _direction = TextDirection.ltr;
  9. bool _isShowing = false;
  10. BuildContext? _context, _dismissingContext;
  11. ProgressDialogType? _progressDialogType;
  12. bool _barrierDismissible = true, _showLogs = false;
  13. Color? _barrierColor;
  14. TextStyle _progressTextStyle = const TextStyle(
  15. color: Colors.black,
  16. fontSize: 12.0,
  17. fontWeight: FontWeight.w400,
  18. ),
  19. _messageStyle = const TextStyle(
  20. color: Colors.black,
  21. fontSize: 18.0,
  22. fontWeight: FontWeight.w600,
  23. );
  24. double _dialogElevation = 8.0, _borderRadius = 8.0;
  25. Color _backgroundColor = Colors.white;
  26. Curve _insetAnimCurve = Curves.easeInOut;
  27. EdgeInsets _dialogPadding = const EdgeInsets.all(8.0);
  28. Widget _progressWidget = Image.asset(
  29. 'assets/double_ring_loading_io.gif',
  30. package: 'progress_dialog',
  31. );
  32. class ProgressDialog {
  33. _Body? _dialog;
  34. ProgressDialog(
  35. BuildContext context, {
  36. ProgressDialogType? type,
  37. bool? isDismissible,
  38. bool? showLogs,
  39. TextDirection? textDirection,
  40. Widget? customBody,
  41. Color? barrierColor,
  42. }) {
  43. _context = context;
  44. _progressDialogType = type ?? ProgressDialogType.normal;
  45. _barrierDismissible = isDismissible ?? true;
  46. _showLogs = showLogs ?? false;
  47. _customBody = customBody;
  48. _direction = textDirection ?? TextDirection.ltr;
  49. _barrierColor = barrierColor ?? barrierColor;
  50. }
  51. void style({
  52. Widget? child,
  53. double? progress,
  54. double? maxProgress,
  55. String? message,
  56. Widget? progressWidget,
  57. Color? backgroundColor,
  58. TextStyle? progressTextStyle,
  59. TextStyle? messageTextStyle,
  60. double? elevation,
  61. TextAlign? textAlign,
  62. double? borderRadius,
  63. Curve? insetAnimCurve,
  64. EdgeInsets? padding,
  65. Alignment? progressWidgetAlignment,
  66. }) {
  67. if (_isShowing) return;
  68. if (_progressDialogType == ProgressDialogType.download) {
  69. _progress = progress ?? _progress;
  70. }
  71. _dialogMessage = message ?? _dialogMessage;
  72. _maxProgress = maxProgress ?? _maxProgress;
  73. _progressWidget = progressWidget ?? _progressWidget;
  74. _backgroundColor = backgroundColor ?? _backgroundColor;
  75. _messageStyle = messageTextStyle ?? _messageStyle;
  76. _progressTextStyle = progressTextStyle ?? _progressTextStyle;
  77. _dialogElevation = elevation ?? _dialogElevation;
  78. _borderRadius = borderRadius ?? _borderRadius;
  79. _insetAnimCurve = insetAnimCurve ?? _insetAnimCurve;
  80. _textAlign = textAlign ?? _textAlign;
  81. _progressWidget = child ?? _progressWidget;
  82. _dialogPadding = padding ?? _dialogPadding;
  83. _progressWidgetAlignment =
  84. progressWidgetAlignment ?? _progressWidgetAlignment;
  85. }
  86. void update({
  87. double? progress,
  88. double? maxProgress,
  89. String? message,
  90. Widget? progressWidget,
  91. TextStyle? progressTextStyle,
  92. TextStyle? messageTextStyle,
  93. }) {
  94. if (_progressDialogType == ProgressDialogType.download) {
  95. _progress = progress ?? _progress;
  96. }
  97. _dialogMessage = message ?? _dialogMessage;
  98. _maxProgress = maxProgress ?? _maxProgress;
  99. _progressWidget = progressWidget ?? _progressWidget;
  100. _messageStyle = messageTextStyle ?? _messageStyle;
  101. _progressTextStyle = progressTextStyle ?? _progressTextStyle;
  102. if (_isShowing) _dialog!.update();
  103. }
  104. bool isShowing() {
  105. return _isShowing;
  106. }
  107. Future<bool> hide() async {
  108. try {
  109. if (_isShowing) {
  110. _isShowing = false;
  111. if (_dismissingContext != null) {
  112. Navigator.of(_dismissingContext!).pop();
  113. }
  114. if (_showLogs) debugPrint('ProgressDialog dismissed');
  115. return Future.value(true);
  116. } else {
  117. if (_showLogs) debugPrint('ProgressDialog already dismissed');
  118. return Future.value(false);
  119. }
  120. } catch (err) {
  121. debugPrint('Seems there is an issue hiding dialog');
  122. debugPrint(err.toString());
  123. return Future.value(false);
  124. }
  125. }
  126. Future<bool> show() async {
  127. try {
  128. if (!_isShowing) {
  129. _dialog = _Body();
  130. showDialog<dynamic>(
  131. context: _context!,
  132. barrierDismissible: _barrierDismissible,
  133. barrierColor: _barrierColor,
  134. builder: (BuildContext context) {
  135. _dismissingContext = context;
  136. return WillPopScope(
  137. onWillPop: () async => _barrierDismissible,
  138. child: Dialog(
  139. backgroundColor: _backgroundColor,
  140. insetAnimationCurve: _insetAnimCurve,
  141. insetAnimationDuration: const Duration(milliseconds: 100),
  142. elevation: _dialogElevation,
  143. shape: RoundedRectangleBorder(
  144. borderRadius:
  145. BorderRadius.all(Radius.circular(_borderRadius)),
  146. ),
  147. child: _dialog,
  148. ),
  149. );
  150. },
  151. );
  152. // Delaying the function for 200 milliseconds
  153. // [Default transitionDuration of DialogRoute]
  154. await Future.delayed(const Duration(milliseconds: 200));
  155. if (_showLogs) debugPrint('ProgressDialog shown');
  156. _isShowing = true;
  157. return true;
  158. } else {
  159. if (_showLogs) debugPrint("ProgressDialog already shown/showing");
  160. return false;
  161. }
  162. } catch (err) {
  163. _isShowing = false;
  164. debugPrint('Exception while showing the dialog');
  165. debugPrint(err.toString());
  166. return false;
  167. }
  168. }
  169. }
  170. // ignore: must_be_immutable
  171. class _Body extends StatefulWidget {
  172. final _BodyState _dialog = _BodyState();
  173. update() {
  174. _dialog.update();
  175. }
  176. @override
  177. State<StatefulWidget> createState() {
  178. return _dialog;
  179. }
  180. }
  181. class _BodyState extends State<_Body> {
  182. update() {
  183. setState(() {});
  184. }
  185. @override
  186. void dispose() {
  187. _isShowing = false;
  188. if (_showLogs) debugPrint('ProgressDialog dismissed by back button');
  189. super.dispose();
  190. }
  191. @override
  192. Widget build(BuildContext context) {
  193. final loader = Align(
  194. alignment: _progressWidgetAlignment,
  195. child: SizedBox(
  196. width: 60.0,
  197. height: 60.0,
  198. child: _progressWidget,
  199. ),
  200. );
  201. final text = Expanded(
  202. child: _progressDialogType == ProgressDialogType.normal
  203. ? Text(
  204. _dialogMessage,
  205. textAlign: _textAlign,
  206. style: _messageStyle,
  207. textDirection: _direction,
  208. )
  209. : Padding(
  210. padding: const EdgeInsets.all(8.0),
  211. child: Column(
  212. mainAxisSize: MainAxisSize.min,
  213. children: <Widget>[
  214. const SizedBox(height: 8.0),
  215. Row(
  216. children: <Widget>[
  217. Expanded(
  218. child: Text(
  219. _dialogMessage,
  220. style: _messageStyle,
  221. textDirection: _direction,
  222. ),
  223. ),
  224. ],
  225. ),
  226. const SizedBox(height: 4.0),
  227. Align(
  228. alignment: Alignment.bottomRight,
  229. child: Text(
  230. "$_progress/$_maxProgress",
  231. style: _progressTextStyle,
  232. textDirection: _direction,
  233. ),
  234. ),
  235. ],
  236. ),
  237. ),
  238. );
  239. return _customBody ??
  240. Container(
  241. padding: _dialogPadding,
  242. child: Column(
  243. mainAxisSize: MainAxisSize.min,
  244. children: <Widget>[
  245. // row body
  246. Row(
  247. mainAxisSize: MainAxisSize.min,
  248. children: <Widget>[
  249. const SizedBox(width: 8.0),
  250. _direction == TextDirection.ltr ? loader : text,
  251. const SizedBox(width: 8.0),
  252. _direction == TextDirection.rtl ? loader : text,
  253. const SizedBox(width: 8.0)
  254. ],
  255. ),
  256. ],
  257. ),
  258. );
  259. }
  260. }