totast.dart 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import 'package:flutter/material.dart';
  2. class Toast {
  3. static ToastView preToast;
  4. static show(BuildContext context, String msg, int seconds, String toastType) {
  5. var overlayState = Overlay.of(context);
  6. var controllerShowAnim = new AnimationController(
  7. vsync: overlayState,
  8. duration: Duration(milliseconds: 250),
  9. );
  10. var controllerShowOffset = new AnimationController(
  11. vsync: overlayState,
  12. duration: Duration(milliseconds: 350),
  13. );
  14. var controllerHide = new AnimationController(
  15. vsync: overlayState,
  16. duration: Duration(milliseconds: 250),
  17. );
  18. var opacityAnim1 =
  19. new Tween(begin: 0.0, end: 1.0).animate(controllerShowAnim);
  20. var controllerCurvedShowOffset = new CurvedAnimation(
  21. parent: controllerShowOffset, curve: _BounceOutCurve._());
  22. var offsetAnim =
  23. new Tween(begin: 30.0, end: 0.0).animate(controllerCurvedShowOffset);
  24. var opacityAnim2 = new Tween(begin: 1.0, end: 0.0).animate(controllerHide);
  25. OverlayEntry overlayEntry;
  26. overlayEntry = new OverlayEntry(builder: (context) {
  27. return ToastWidget(
  28. opacityAnim1: opacityAnim1,
  29. opacityAnim2: opacityAnim2,
  30. offsetAnim: offsetAnim,
  31. child: buildToastLayout(msg, toastType),
  32. );
  33. });
  34. var toastView = ToastView();
  35. if (seconds != null) {
  36. toastView.seconds = seconds;
  37. }
  38. toastView.overlayEntry = overlayEntry;
  39. toastView.controllerShowAnim = controllerShowAnim;
  40. toastView.controllerShowOffset = controllerShowOffset;
  41. toastView.controllerHide = controllerHide;
  42. toastView.overlayState = overlayState;
  43. preToast = toastView;
  44. toastView._show();
  45. }
  46. static hide() {
  47. if (preToast != null) {
  48. preToast.dismiss();
  49. preToast = null;
  50. }
  51. }
  52. static LayoutBuilder buildToastLayout(String msg, String toastType) {
  53. return LayoutBuilder(builder: (context, constraints) {
  54. return Container(
  55. color: Colors.white.withOpacity(0),
  56. child: IgnorePointer(
  57. ignoring: true,
  58. child: Container(
  59. child: Material(
  60. color: Colors.white.withOpacity(0),
  61. child: new Container(
  62. margin: EdgeInsets.only(top:toastType == 'num'?0:0),
  63. padding: EdgeInsets.symmetric(
  64. horizontal: toastType == 'info' ? 15 : (toastType == 'num'?0:36)),
  65. height: toastType == 'info' ? 40 : (toastType=='num'?60:100),
  66. width: toastType=='num'?60:null,
  67. decoration: ShapeDecoration(
  68. color: Colors.black.withOpacity(toastType=='num'?0.8:0.4),
  69. shape: RoundedRectangleBorder(
  70. borderRadius: BorderRadius.all(
  71. Radius.circular(toastType=='num'?60:8.0),
  72. ),
  73. ),
  74. ),
  75. child: new Column(
  76. mainAxisAlignment: MainAxisAlignment.center,
  77. crossAxisAlignment: CrossAxisAlignment.center,
  78. children: _contentWidget(toastType, msg),
  79. ),
  80. )),
  81. alignment: Alignment.center,
  82. ),
  83. ),
  84. );
  85. });
  86. }
  87. }
  88. List<Widget> _contentWidget(toastType, msg) {
  89. List<Widget> widgetList = [];
  90. if (toastType == 'loading') {
  91. widgetList = [
  92. new CircularProgressIndicator(),
  93. new Padding(
  94. padding: const EdgeInsets.only(
  95. top: 20.0,
  96. ),
  97. child: new Text(
  98. msg,
  99. style: new TextStyle(fontSize: 14.0, color: Colors.white),
  100. ),
  101. ),
  102. ];
  103. } else if (toastType == 'success') {
  104. widgetList = [
  105. Icon(Icons.done, color: Colors.green, size: 50),
  106. new Padding(
  107. padding: const EdgeInsets.only(
  108. top: 10.0,
  109. ),
  110. child: new Text(
  111. msg,
  112. style: new TextStyle(fontSize: 14.0, color: Colors.white),
  113. ),
  114. ),
  115. ];
  116. } else if (toastType == 'num'){
  117. widgetList = [
  118. Text(
  119. msg,
  120. style: new TextStyle(fontSize: 24.0, color: Colors.white),
  121. ),
  122. ];
  123. }else {
  124. widgetList = [
  125. Text(
  126. msg,
  127. style: new TextStyle(fontSize: 14.0, color: Colors.white),
  128. ),
  129. ];
  130. }
  131. return widgetList;
  132. }
  133. class ToastView {
  134. OverlayEntry overlayEntry;
  135. AnimationController controllerShowAnim;
  136. AnimationController controllerShowOffset;
  137. AnimationController controllerHide;
  138. OverlayState overlayState;
  139. bool dismissed = false;
  140. int seconds = 3500;
  141. _show() async {
  142. overlayState.insert(overlayEntry);
  143. controllerShowAnim.forward();
  144. controllerShowOffset.forward();
  145. if (seconds != -1) {
  146. await Future.delayed(Duration(milliseconds: seconds));
  147. this.dismiss();
  148. }
  149. }
  150. dismiss() async {
  151. if (dismissed) {
  152. return;
  153. }
  154. this.dismissed = true;
  155. controllerHide.forward();
  156. await Future.delayed(Duration(milliseconds: 250));
  157. overlayEntry?.remove();
  158. }
  159. }
  160. class ToastWidget extends StatelessWidget {
  161. final Widget child;
  162. final Animation<double> opacityAnim1;
  163. final Animation<double> opacityAnim2;
  164. final Animation<double> offsetAnim;
  165. ToastWidget(
  166. {this.child, this.offsetAnim, this.opacityAnim1, this.opacityAnim2});
  167. @override
  168. Widget build(BuildContext context) {
  169. return AnimatedBuilder(
  170. animation: opacityAnim1,
  171. child: child,
  172. builder: (context, child_to_build) {
  173. return Opacity(
  174. opacity: opacityAnim1.value,
  175. child: AnimatedBuilder(
  176. animation: offsetAnim,
  177. builder: (context, _) {
  178. return Transform.translate(
  179. offset: Offset(0, offsetAnim.value),
  180. child: AnimatedBuilder(
  181. animation: opacityAnim2,
  182. builder: (context, _) {
  183. return Opacity(
  184. opacity: opacityAnim2.value,
  185. child: child_to_build,
  186. );
  187. },
  188. ),
  189. );
  190. },
  191. ),
  192. );
  193. },
  194. );
  195. }
  196. }
  197. class _BounceOutCurve extends Curve {
  198. const _BounceOutCurve._();
  199. @override
  200. double transform(double t) {
  201. t -= 1.0;
  202. return t * t * ((2 + 1) * t + 2) + 1.0;
  203. }
  204. }