flutter自定义toast弹窗组件

  1 import 'package:flutter/material.dart';
  2 
  3 enum ToastPosition { top, center, bottom }
  4 
  5 class Toast {
  6   static OverlayEntry _overlayEntry;
  7   static bool _showing = false;
  8   static ToastPosition toastPosition;
  9   static DateTime _startTime;
 10   static String _msg;
 11   static void show(BuildContext context,
 12       {String msg,
 13       int duration = 1, // 默认1秒
 14       ToastPosition toastPosition,
 15       Color background = const Color(0xB2000000),
 16       TextStyle textStyle = const TextStyle(
 17           fontSize: 16,
 18           color: Colors.white,
 19           backgroundColor: Colors.transparent),
 20       double backgroundRadius = 20,
 21       Border border}) async {
 22     OverlayState overlayState = Overlay.of(context);
 23     toastPosition = ToastPosition.center;
 24     _startTime = DateTime.now();
 25     _showing = true;
 26     _msg = msg;
 27     if (_overlayEntry == null) {
 28       _overlayEntry = OverlayEntry(
 29         builder: (BuildContext context) =>
 30             ToastWidget(
 31             widget: Container(
 32               width: MediaQuery.of(context).size.width,
 33               child: Container(
 34                   alignment: Alignment.center,
 35                   width: MediaQuery.of(context).size.width,
 36                   child: Container(
 37                     decoration: BoxDecoration(
 38                       color: background,
 39                       borderRadius: BorderRadius.circular(backgroundRadius),
 40                       border: border,
 41                     ),
 42                     margin: EdgeInsets.symmetric(horizontal: 20),
 43                     padding: EdgeInsets.symmetric(vertical: 5, horizontal: 20),
 44                     child: Text(_msg, softWrap: true, style: textStyle),
 45                   )),
 46             ),
 47             toastPosition: toastPosition),
 48       );
 49       overlayState.insert(_overlayEntry);
 50     } else {
 51       //重新绘制UI,类似setState
 52       _overlayEntry.markNeedsBuild();
 53     }
 54     await Future.delayed(Duration(seconds: duration));
 55     if (DateTime.now().difference(_startTime).inSeconds >= duration) {
 56       // 如果当前时间与toast显示的开始时间差大于等于显示时间就消失 否则继续显示
 57       dismiss();
 58     }
 59   }
 60 
 61   static dismiss() async {
 62     if (!_showing) {
 63       return;
 64     }
 65     _showing = false;
 66     _overlayEntry?.remove();
 67     _overlayEntry = null;
 68   }
 69 }
 70 
 71 class ToastWidget extends StatelessWidget {
 72   ToastWidget({
 73     Key key,
 74     @required this.widget,
 75     this.toastPosition,
 76   }) : super(key: key);
 77 
 78   final Widget widget;
 79   final ToastPosition toastPosition;
 80 
 81   @override
 82   Widget build(BuildContext context) {
 83     return Positioned(
 84         top: buildToastPosition(context),
 85         child: Material(
 86           color: Colors.transparent,
 87           child: widget,
 88         ));
 89   }
 90 
 91   double buildToastPosition(context) {
 92     var top;
 93     if (toastPosition == ToastPosition.top) {
 94       top = MediaQuery.of(context).size.height * 1 / 4;
 95     } else if (toastPosition == ToastPosition.center) {
 96       top = MediaQuery.of(context).size.height * 2 / 5;
 97     } else {
 98       top = MediaQuery.of(context).size.height * 3 / 4;
 99     }
100     return top;
101   }
102 }

调用 Toast.show(context, msg: '显示toast', duration: 5);

可以一直触发toast并且更新文本内容、直到需要显示的时间结束后消失

posted @ 2020-06-12 12:18  Rakan~  阅读(1327)  评论(0编辑  收藏  举报