toast.dart 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. import 'dart:async';
  2. import 'dart:ui';
  3. import 'package:flutter/cupertino.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:link/view/component/loading.dart';
  6. import '../../utils/size_fit.dart';
  7. class Toast {
  8. static final Toast _instance = Toast._internal();
  9. factory Toast() => _instance;
  10. OverlayEntry? _overlayEntry;
  11. bool _showing = false;
  12. Timer? _timer;
  13. AnimationController? controller;
  14. Toast._internal();
  15. // txt
  16. void showText(String text, {required BuildContext context}) {
  17. // ignore: non_constant_identifier_names
  18. Widget RCCardText = Card(
  19. color: Colors.black87,
  20. child: Padding(
  21. padding: const EdgeInsets.all(10),
  22. child: Text(
  23. text,
  24. style: const TextStyle(fontSize: 15, color: Colors.white),
  25. ),
  26. ),
  27. );
  28. _autoRemove(RCCardText, text, context: context);
  29. }
  30. // success
  31. void showSuccessText(String text, {required BuildContext context}) {
  32. _showIconInfoText(text, "assets/images/toast_success.png", context);
  33. }
  34. // info
  35. void showInfoText(String text, {required BuildContext context}) {
  36. _showIconInfoText(text, "assets/images/toast_tip.png", context);
  37. }
  38. // error
  39. void showErrorText(String text, {required BuildContext context}) {
  40. _showIconInfoText(text, "assets/images/alter_wro.png", context);
  41. }
  42. // hud + text
  43. void showHudText(String text, {required BuildContext context}) {
  44. // ignore: non_constant_identifier_names
  45. Widget HudText = Container(
  46. height: 80,
  47. decoration: const BoxDecoration(
  48. color: Colors.black54,
  49. borderRadius: BorderRadius.all(Radius.circular(24)),
  50. ),
  51. padding: const EdgeInsets.fromLTRB(32, 24, 32, 24),
  52. child: Column(
  53. children: <Widget>[
  54. Container(
  55. width: 60,
  56. height: 40,
  57. padding: const EdgeInsets.all(10),
  58. child: Theme(
  59. data: ThemeData(
  60. cupertinoOverrideTheme: const CupertinoThemeData(
  61. brightness: Brightness.dark,
  62. ),
  63. ),
  64. child: const CupertinoActivityIndicator(
  65. radius: 16,
  66. ),
  67. ),
  68. ),
  69. Material(
  70. color: Colors.transparent,
  71. child: Text(
  72. text,
  73. style: const TextStyle(
  74. fontSize: 16,
  75. color: Colors.white,
  76. ),
  77. ),
  78. ),
  79. ],
  80. ),
  81. );
  82. _handMovementRemove(HudText, context: context);
  83. }
  84. // hud
  85. void showHud({required BuildContext context}) {
  86. // ignore: non_constant_identifier_names
  87. Widget Hud = ClipRRect(
  88. borderRadius: BorderRadius.all(Radius.circular(24.px)),
  89. child: BackdropFilter(
  90. filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
  91. child: Container(
  92. width: 112.px,
  93. height: 112.px,
  94. color: const Color(0xB34D4D4D),
  95. alignment: Alignment.center,
  96. child: const Loading(),
  97. ),
  98. ),
  99. );
  100. _handMovementRemove(Hud, context: context);
  101. }
  102. //alert
  103. void showCustomHud(Widget child, {required BuildContext context}) {
  104. // ignore: non_constant_identifier_names
  105. Widget Hud = Column(
  106. mainAxisAlignment: MainAxisAlignment.center,
  107. crossAxisAlignment: CrossAxisAlignment.center,
  108. children: [
  109. ClipRRect(
  110. borderRadius: BorderRadius.all(Radius.circular(24.px)),
  111. child: BackdropFilter(
  112. filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
  113. child: Container(
  114. width: 288.px,
  115. // height: 112.px,
  116. color: const Color(0xB34D4D4D),
  117. alignment: Alignment.center,
  118. child: Material(
  119. color: Colors.transparent,
  120. child: child,
  121. ),
  122. ),
  123. ),
  124. )
  125. ],
  126. );
  127. _handMovementRemove(Hud, context: context);
  128. }
  129. // dismiss
  130. void hideHud() {
  131. if (_overlayEntry != null) {
  132. _overlayEntry?.remove();
  133. _timer?.cancel();
  134. _overlayEntry = null;
  135. }
  136. }
  137. void _showIconInfoText(String text, String imageName, BuildContext context) {
  138. // ignore: non_constant_identifier_names
  139. Widget RCIconText = Column(children: [
  140. SizedBox(
  141. height: 100.px,
  142. ),
  143. ClipRRect(
  144. borderRadius: BorderRadius.all(Radius.circular(24.px)),
  145. child: BackdropFilter(
  146. filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
  147. child: Container(
  148. color: const Color(0xB34D4D4D),
  149. padding: EdgeInsets.fromLTRB(32.px, 24.px, 32.px, 24.px),
  150. child: Column(
  151. children: <Widget>[
  152. Image.asset(
  153. imageName,
  154. width: 48.px,
  155. height: 48.px,
  156. ),
  157. SizedBox(
  158. height: 12.px,
  159. ),
  160. Material(
  161. color: Colors.transparent,
  162. child: Text(
  163. text,
  164. textAlign: TextAlign.center,
  165. style: TextStyle(color: Colors.white, fontSize: 16.px),
  166. ),
  167. ),
  168. ],
  169. ),
  170. ),
  171. ))
  172. ]);
  173. _autoRemove(RCIconText, text, context: context);
  174. }
  175. void _autoRemove(Widget child, String text, {required BuildContext context}) {
  176. hideHud();
  177. // 简单写个消失的动画,可自行自定义
  178. _showing = true;
  179. _setOverlayEntry(
  180. AnimatedOpacity(
  181. opacity: _showing ? 1.0 : 0.0,
  182. duration: _showing
  183. ? const Duration(milliseconds: 50)
  184. : const Duration(milliseconds: 100),
  185. child: child,
  186. ),
  187. context);
  188. _removeText(text);
  189. }
  190. void _handMovementRemove(Widget child, {required BuildContext context}) {
  191. hideHud();
  192. _setOverlayEntry(child, context);
  193. }
  194. void _setOverlayEntry(Widget child, BuildContext context) {
  195. if (context == null) {
  196. // context = RCGlobalKey.currentState.context;
  197. }
  198. if (context == null)
  199. throw ("Error: Context is null, Please call init(context) before showing toast.");
  200. if (_overlayEntry == null) {
  201. _overlayEntry = OverlayEntry(
  202. builder: (BuildContext context) => Positioned(
  203. top: MediaQuery.of(context).padding.top + kToolbarHeight,
  204. child: Container(
  205. alignment: Alignment.center,
  206. color: Colors.transparent,
  207. width: MediaQuery.of(context).size.width,
  208. height: MediaQuery.of(context).size.height -
  209. kToolbarHeight -
  210. MediaQuery.of(context).padding.top,
  211. padding: EdgeInsets.only(
  212. bottom:
  213. kToolbarHeight + MediaQuery.of(context).padding.top),
  214. child: child,
  215. ),
  216. ));
  217. //插入到整个布局的最上层
  218. Overlay.of(context)?.insert(_overlayEntry!);
  219. } else {
  220. //重新绘制UI,类似setState
  221. _overlayEntry?.markNeedsBuild();
  222. }
  223. }
  224. // 传入text,根据字数判断显示的时长(1-3s)
  225. void _removeText(String text) {
  226. if (_overlayEntry != null) {
  227. // 显示时间
  228. int _showTime = text.length * 200;
  229. if (_showTime < 1000) {
  230. _showTime = 2000;
  231. } else if (_showTime > 2000) {
  232. _showTime = 2000;
  233. }
  234. _timer = Timer(Duration(milliseconds: _showTime), () {
  235. _showing = false;
  236. _overlayEntry?.markNeedsBuild();
  237. Future.delayed(const Duration(milliseconds: 200), () {
  238. _overlayEntry?.remove();
  239. _overlayEntry = null;
  240. _timer?.cancel();
  241. });
  242. });
  243. }
  244. }
  245. }