progress_dialog.dart 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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 ?? null;
  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. Navigator.of(_dismissingContext).pop();
  112. if (_showLogs) debugPrint('ProgressDialog dismissed');
  113. return Future.value(true);
  114. } else {
  115. if (_showLogs) debugPrint('ProgressDialog already dismissed');
  116. return Future.value(false);
  117. }
  118. } catch (err) {
  119. debugPrint('Seems there is an issue hiding dialog');
  120. debugPrint(err.toString());
  121. return Future.value(false);
  122. }
  123. }
  124. Future<bool> show() async {
  125. try {
  126. if (!_isShowing) {
  127. _dialog = _Body();
  128. showDialog<dynamic>(
  129. context: _context,
  130. barrierDismissible: _barrierDismissible,
  131. barrierColor: _barrierColor,
  132. builder: (BuildContext context) {
  133. _dismissingContext = context;
  134. return WillPopScope(
  135. onWillPop: () async => _barrierDismissible,
  136. child: Dialog(
  137. backgroundColor: _backgroundColor,
  138. insetAnimationCurve: _insetAnimCurve,
  139. insetAnimationDuration: const Duration(milliseconds: 100),
  140. elevation: _dialogElevation,
  141. shape: RoundedRectangleBorder(
  142. borderRadius:
  143. BorderRadius.all(Radius.circular(_borderRadius)),
  144. ),
  145. child: _dialog,
  146. ),
  147. );
  148. },
  149. );
  150. // Delaying the function for 200 milliseconds
  151. // [Default transitionDuration of DialogRoute]
  152. await Future.delayed(const Duration(milliseconds: 200));
  153. if (_showLogs) debugPrint('ProgressDialog shown');
  154. _isShowing = true;
  155. return true;
  156. } else {
  157. if (_showLogs) debugPrint("ProgressDialog already shown/showing");
  158. return false;
  159. }
  160. } catch (err) {
  161. _isShowing = false;
  162. debugPrint('Exception while showing the dialog');
  163. debugPrint(err.toString());
  164. return false;
  165. }
  166. }
  167. }
  168. // ignore: must_be_immutable
  169. class _Body extends StatefulWidget {
  170. final _BodyState _dialog = _BodyState();
  171. update() {
  172. _dialog.update();
  173. }
  174. @override
  175. State<StatefulWidget> createState() {
  176. return _dialog;
  177. }
  178. }
  179. class _BodyState extends State<_Body> {
  180. update() {
  181. setState(() {});
  182. }
  183. @override
  184. void dispose() {
  185. _isShowing = false;
  186. if (_showLogs) debugPrint('ProgressDialog dismissed by back button');
  187. super.dispose();
  188. }
  189. @override
  190. Widget build(BuildContext context) {
  191. final loader = Align(
  192. alignment: _progressWidgetAlignment,
  193. child: SizedBox(
  194. width: 60.0,
  195. height: 60.0,
  196. child: _progressWidget,
  197. ),
  198. );
  199. final text = Expanded(
  200. child: _progressDialogType == ProgressDialogType.normal
  201. ? Text(
  202. _dialogMessage,
  203. textAlign: _textAlign,
  204. style: _messageStyle,
  205. textDirection: _direction,
  206. )
  207. : Padding(
  208. padding: const EdgeInsets.all(8.0),
  209. child: Column(
  210. mainAxisSize: MainAxisSize.min,
  211. children: <Widget>[
  212. const SizedBox(height: 8.0),
  213. Row(
  214. children: <Widget>[
  215. Expanded(
  216. child: Text(
  217. _dialogMessage,
  218. style: _messageStyle,
  219. textDirection: _direction,
  220. ),
  221. ),
  222. ],
  223. ),
  224. const SizedBox(height: 4.0),
  225. Align(
  226. alignment: Alignment.bottomRight,
  227. child: Text(
  228. "$_progress/$_maxProgress",
  229. style: _progressTextStyle,
  230. textDirection: _direction,
  231. ),
  232. ),
  233. ],
  234. ),
  235. ),
  236. );
  237. return _customBody ??
  238. Container(
  239. padding: _dialogPadding,
  240. child: Column(
  241. mainAxisSize: MainAxisSize.min,
  242. children: <Widget>[
  243. // row body
  244. Row(
  245. mainAxisSize: MainAxisSize.min,
  246. children: <Widget>[
  247. const SizedBox(width: 8.0),
  248. _direction == TextDirection.ltr ? loader : text,
  249. const SizedBox(width: 8.0),
  250. _direction == TextDirection.rtl ? loader : text,
  251. const SizedBox(width: 8.0)
  252. ],
  253. ),
  254. ],
  255. ),
  256. );
  257. }
  258. }