美文网首页
Flutter-toast loding 封装

Flutter-toast loding 封装

作者: SK丿希望 | 来源:发表于2021-11-09 10:41 被阅读0次

使用案例

Toast.showHud("测试"); // Toast 白色主题
Toast.showHud("测试", type: ToastType.black); // Toast 黑色主题
Toast.showLoding(context, userInteraction: true) // loding 白色主题 userInteraction 是否允许交互
Toast.showLoding(context, userInteraction: true, type: ToastType.black); // loding 黑色主题

/// isRealTime: 是否立即显示 ture立即显示 false 是延迟加载的 注意:在initState中方法调用必须为false 不然会出问题
Toast.showLoding(context, userInteraction: true, type: ToastType.black, isRealTime: false); // loding 黑色主题
Toast 白色主题
Toast 黑色主题 loding 白色主题
loding 黑色主题

源码

// 普通toast 是依赖 fluttertoast
请在`pubspec.yaml`添加
fluttertoast: ^8.0.8        # HUD
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';

enum ToastType {
  white, // 白色
  black, // 黑色
}

class Toast {

  static const defaultType = ToastType.white; // 默认样式
  /// 显示Toast
  /// msg: 显示内容
  /// type: 样式
  static void showHud(String msg, {ToastType type = defaultType}) {
    Fluttertoast.cancel();
    Fluttertoast.showToast(
        msg: msg,
        gravity: Platform.isIOS ? ToastGravity.CENTER : ToastGravity.BOTTOM, // iOS显示在中间 安卓显示在底部
        backgroundColor: type == ToastType.black ? Colors.black : Colors.white,
        textColor: type == ToastType.black ? Colors.white : Colors.black,
        fontSize: 16.0);
  }

  /// 取消Toast
  static void dismiss() {
    Fluttertoast.cancel();
    if (RealTimeLoadingDialog.isShow()) {
      RealTimeLoadingDialog.dismiss();
    }
    if (LoadingDialog.isShow()) {
      LoadingDialog.dismiss();
    }
  }

  /// 显示loding
  /// BuildContext context
  /// msg: 显示内容
  /// userInteraction: 是否允许交互
  /// type: 样式
  /// isRealTime: 是否立即显示 ture立即显示 false 是延迟加载的 注意:在initState中方法调用必须为false 不然会出问题
  static void showLoading(BuildContext context,
      {String msg = "",
      bool userInteraction = false,
      ToastType type = _defaultType,
      bool isRealTime = true}) {
    dismiss();
    if (isRealTime) {
      RealTimeLoadingDialog.showLoading(context,
          content: msg, userInteraction: userInteraction, type: type);
    } else {
      LoadingDialog.showLoading(context,
          content: msg, userInteraction: userInteraction, type: type);
    }
  }

///加载弹框
class LoadingDialog {
  static Timer _timer; // 超时定时器
  static ToastType _type;
  static OverlayEntry itemEntry;
  // 是否显示
  static  bool _isShow = false;

  /// 展示
  /// BuildContext context
  /// content 显示内容
  /// userInteraction 是否允许交互 默认不允许
  static void showLoading(BuildContext context,
      {String content = "数据加载中...",
        bool userInteraction = false,
        ToastType type}) async {
    dismiss();
    _type = type;
    _isShow = true;
    ///显示悬浮menu
    itemEntry = OverlayEntry(
        builder: (BuildContext context) => _Loading(
          userInteraction: userInteraction,
          child: _contentView(content),
        ));
    _startTimer();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      Overlay.of(context)?.insert(itemEntry);
    });
  }

  /// loding 是否显示
  static bool isShow() {
    return _isShow;
  }

  ///隐藏
  static void dismiss() {
    if (!_isShow) return;
    var tmp = itemEntry?.mounted;
    if (tmp == false) {
      Future.delayed(Duration(milliseconds: 3), () {
        dismiss();
      });
      return;
    }
    _cleanData();
    _isShow = false;
  }

  static _cleanData() {
    itemEntry?.remove();
    itemEntry = null;
    _stopTimer();
  }

  /// 内容View
  static _contentView(String content) {
    return _loadingContentView(_type, content);
  }

  /// 开始定时
  static _startTimer() {
    _timer = Timer(Duration(seconds: 60), () {
      // 60秒超时时间 自动消失
      LoadingDialog.dismiss();
    });
  }

  /// 销户定时
  static _stopTimer() {
    _timer?.cancel();
    _timer = null;
  }
}


/// 实时加载弹框
class RealTimeLoadingDialog {
  static Timer _timer; // 超时定时器
  static BuildContext _context; // 理论上只有一个 不然就可以用一个数组保存
  static ToastType _type;

  /// 展示
  /// BuildContext context
  /// content 显示内容
  /// userInteraction 是否允许交互 默认不允许
  static void showLoading(BuildContext context,
      {String content = "数据加载中...",
        bool userInteraction = false,
        ToastType type}) async {
    LoadingDialog.dismiss(); // 如果之前有显示取消显示
    if (_context == null) {
      _context = context;
      _type = type;
      var child = _contentView(content);
      _LoadingRoute _route = _LoadingRoute(
        child: _Loading(
          userInteraction: userInteraction,
          child: child,
        ),
      );
      Future.delayed(Duration.zero, () {
        // 必须添加 因为请求是异步等待的 async await
        Navigator.push(
          context,
          _route
        );
      });
      _startTimer();
    }
  }

  /// loading 是否显示
  static bool isShow() {
    return _context==null?false:true;
  }

  ///隐藏
  static void dismiss() {
    if (_context == null) return;
      _stopTimer();
      Navigator.of(_context).pop();
      _context = null;
  }

  /// 内容View
  static _contentView(String content) {
    return _loadingContentView(_type, content);
  }

  /// 开始定时
  static _startTimer() {
    _timer = Timer(Duration(seconds: 60), () {
      // 60秒超时时间 自动消失
      RealTimeLoadingDialog.dismiss();
    });
  }

  /// 销户定时
  static _stopTimer() {
    if (_timer == null) return;
    _timer?.cancel();
    _timer = null;
  }
}


///Widget
class _Loading extends StatelessWidget {
  final Widget child;

  final bool userInteraction;

  _Loading({Key key, @required this.child, this.userInteraction = false})
      : assert(child != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        onTap: () {
          if (userInteraction == false) return;
          LoadingDialog.dismiss();
        },
        child: Material(
            color: Colors.black12,
            child: Center(
              child: child,
            )));
  }
}

///Route
class _LoadingRoute extends PopupRoute {
  final Duration _duration = Duration(milliseconds: 300);
  Widget child;

  _LoadingRoute({@required this.child});

  @override
  Color get barrierColor => Colors.transparent;

  @override
  bool get barrierDismissible => true;

  @override
  String get barrierLabel => null;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation) {
    return child ?? Container();
  }

  @override
  Duration get transitionDuration => _duration;
}

Widget _loadingContentView(ToastType _type, String content, {Widget midView}) {
  if (midView == null) midView = _progress(_type);
  var contentView = Row(
    children: [
      Expanded(child: Container()),
      Container(
        decoration: BoxDecoration(
          color: _type == ToastType.black
              ? Color(0xFF252525).withOpacity(0.6)
              : Colors.white,
          borderRadius: BorderRadius.circular(12),
        ),
        padding: EdgeInsets.all(30),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [midView, _label(content, _type)],
        ),
      ),
      Expanded(child: Container())
    ],
  );
  return Column(
    children: [
      Expanded(child: Container()),
      contentView,
      Expanded(child: Container()),
    ],
  );
}

_progress(ToastType _type) {
  return Container(
    width: 28,
    height: 28,
    child: Theme(
      data: ThemeData(
        cupertinoOverrideTheme: CupertinoThemeData(
          // 菊花
          brightness:
          _type == ToastType.black ? Brightness.dark : Brightness.light,
        ),
      ),
      child: CupertinoActivityIndicator(
        radius: 14,
      ),
    ),
  );
}

_label(String content, ToastType _type) {
  if (content.length == 0)
    return Container();
  else {
    return Container(
        margin: EdgeInsets.only(top: 15),
        child: ConstrainedBox(
          constraints: BoxConstraints(
            maxWidth: 250,
          ),
          child: Text(
            content,
            overflow: TextOverflow.ellipsis,
            softWrap: true,
            maxLines: 5,
            style: TextStyle(
              fontSize: 16,
              color: _type == ToastType.black ? Colors.white : Colors.black,
            ),
          ),
        ));
  }
}

相关文章

网友评论

      本文标题:Flutter-toast loding 封装

      本文链接:https://www.haomeiwen.com/subject/jwsmzltx.html