flutter toast插件 OKToast的介绍

文章目录

OKToast 是一款 在 flutter 上 使用的 toast 插件

使用简单, 可定制性强, 纯 flutter, 调用不用 context

安装

查看文档:

在 pubspec 引入

1dependencies:
2  oktoast: ^2.2.0 # 这一步请查询pub的最新版本

获取包: $ flutter packages get

引入: import 'package:oktoast/oktoast.dart';

使用

在代码中定义 OKToast 组件

包裹你的 MaterialApp,不是包裹你的 Scaffold
包裹你的 MaterialApp,不是包裹你的 Scaffold
包裹你的 MaterialApp,不是包裹你的 Scaffold

 1class MyApp extends StatelessWidget {
 2  @override
 3  Widget build(BuildContext context) {
 4    return OKToast( // 这一步
 5      child: new MaterialApp(
 6        title: 'Flutter Demo',
 7        theme: new ThemeData(
 8          primarySwatch: Colors.blue,
 9        ),
10        home: new MyHomePage(),
11      ),
12    );
13  }
14}

这一步解释一下,因为一般情况下,一个 flutter 应用应该只有一个 MaterialApp(或是 WidgetsApp/CupertinoApp), 这里包裹后,可以缓存 Context 到 内存中,后续在调用显示时,不用传入 BuildContext

这样能满足一部分用户在无 context 的情况下调用 showToast 方法

调用

文本 toast

1showToast("hello world");  // 可选属性看自己需求

20190418104706.png

自定义 widget

1Widget widget = Center(
2  child:Container(
3      color:Colors.white,
4      child:Icon(Icons.add),
5  ),
6);
7showToastWidget(widget);

使用如下代码的效果

 1
 2  void _showCustomWidgetToast() {
 3    var w = Center(
 4      child: Container(
 5        padding: const EdgeInsets.all(5),
 6        color: Colors.black.withOpacity(0.7),
 7        child: Row(
 8          children: <Widget>[
 9            Icon(
10              Icons.add,
11              color: Colors.white,
12            ),
13            Text(
14              '添加成功',
15              style: TextStyle(color: Colors.white),
16            ),
17          ],
18          mainAxisSize: MainAxisSize.min,
19        ),
20      ),
21    );
22    showToastWidget(w);
23  }

20190418104819.png

简单的 toast 实现

其实简单的方案,直接使用 Overlay 就可以了,不需要插件只需要一个简单的工具类,而且代码量并不大

 1class ToastHelper {
 2  static void showToast(BuildContext context, String text) {
 3    const style = TextStyle(color: Colors.white, fontSize: 14.0);
 4
 5    Widget widget = Center(
 6      child: Container(
 7        color: Colors.black.withOpacity(0.5),
 8        padding: const EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0),
 9        child: Text(
10          text,
11          style: style,
12        ),
13      ),
14    );
15    var entry = OverlayEntry(
16      builder: (_) => widget,
17    );
18
19    Overlay.of(context).insert(entry);
20
21    Timer(const Duration(seconds: 2), () {
22      entry?.remove();
23    });
24  }
25}

那么为什么要用 OKToast 呢?

  1. 不用 context,方便一些在网络层的提示
  2. 比较方便的自定义,支持自建 widget
  3. 有一些小特性,比如软键盘弹出时自动移动位置防遮挡
  4. 支持手动隐藏 toast

进阶使用

隐藏已出现的 toast

有如下的方式可以隐藏

隐藏所有的 toast

手动隐藏:调用这个方法就可以关闭所有的 toast 了

1dismissAllToast();

在显示 toast 时隐藏之前显示的所有 toast,其实是根据这个参数在方法内调用dismissAllToast

1showToast("msg", dismissOtherToast: true);

全局设置隐藏之前的属性,这里设置后,每次当你显示新的 toast 时,旧的就会被关闭

1OKToast(
2  dismissOtherOnShow: true,
3  ...
4)

隐藏单独的 toast

每一个 showToast/showToastWidget 方法会有一个返回值,类型是 ToastFuture

1var future = showToast("msg");
2future.dismiss(); // 隐藏指定的toast

自定义属性

OKToast 组件有丰富的自定义属性

20190418102102.png

backgroundColor: 背景颜色

duration: 延迟隐藏时间

onDismiss: 隐藏时的回调

position: toast 的位置

radius: 圆角的尺寸

textAlign: 文字在内部的对齐方式

textDirection: ltr 或 rtl

textPadding: 文本距离边框的 padding

textStyle: 文本的样式

本文完整的 main.dart

  1import 'dart:async';
  2
  3import 'package:flutter/material.dart';
  4import 'package:oktoast/oktoast.dart';
  5
  6void main() => runApp(new MyApp());
  7
  8class MyApp extends StatelessWidget {
  9  // This widget is the root of your application.
 10  @override
 11  Widget build(BuildContext context) {
 12    return OKToast(
 13      dismissOtherOnShow: true,
 14      child: new MaterialApp(
 15        title: 'Flutter Demo',
 16        theme: new ThemeData(
 17          // This is the theme of your application.
 18          //
 19          // Try running your application with "flutter run". You'll see the
 20          // application has a blue toolbar. Then, without quitting the app, try
 21          // changing the primarySwatch below to Colors.green and then invoke
 22          // "hot reload" (press "r" in the console where you ran "flutter run",
 23          // or press Run > Flutter Hot Reload in IntelliJ). Notice that the
 24          // counter didn't reset back to zero; the application is not restarted.
 25          primarySwatch: Colors.blue,
 26        ),
 27        home: new MyHomePage(title: 'Flutter Demo Home Page'),
 28      ),
 29    );
 30  }
 31}
 32
 33class MyHomePage extends StatefulWidget {
 34  MyHomePage({Key key, this.title}) : super(key: key);
 35
 36  // This widget is the home page of your application. It is stateful, meaning
 37  // that it has a State object (defined below) that contains fields that affect
 38  // how it looks.
 39
 40  // This class is the configuration for the state. It holds the values (in this
 41  // case the title) provided by the parent (in this case the App widget) and
 42  // used by the build method of the State. Fields in a Widget subclass are
 43  // always marked "final".
 44
 45  final String title;
 46
 47  @override
 48  _MyHomePageState createState() => new _MyHomePageState();
 49}
 50
 51class _MyHomePageState extends State<MyHomePage> {
 52  int _counter = 0;
 53
 54  void _showToast() {
 55    showToast("msg");
 56  }
 57
 58  @override
 59  Widget build(BuildContext context) {
 60    return Scaffold(
 61      appBar: AppBar(
 62        title: Text("OKToast示例"),
 63      ),
 64      body: ListView(
 65        children: <Widget>[
 66          RaisedButton(
 67            child: Text('文字toast'),
 68            onPressed: _showToast,
 69          ),
 70          RaisedButton(
 71            child: Text('自定义Widget Toast'),
 72            onPressed: _showCustomWidgetToast,
 73          ),
 74          RaisedButton(
 75            child: Text('ToastHelper '),
 76            onPressed: () => ToastHelper.showToast(context, "toast helper"),
 77          ),
 78        ],
 79      ),
 80    );
 81  }
 82
 83  void _showCustomWidgetToast() {
 84    var w = Center(
 85      child: Container(
 86        padding: const EdgeInsets.all(5),
 87        color: Colors.black.withOpacity(0.7),
 88        child: Row(
 89          children: <Widget>[
 90            Icon(
 91              Icons.add,
 92              color: Colors.white,
 93            ),
 94            Text(
 95              '添加成功',
 96              style: TextStyle(color: Colors.white),
 97            ),
 98          ],
 99          mainAxisSize: MainAxisSize.min,
100        ),
101      ),
102    );
103    showToastWidget(w);
104  }
105}
106
107class ToastHelper {
108  static void showToast(BuildContext context, String text) {
109    const style = TextStyle(color: Colors.white, fontSize: 14.0);
110
111    Widget widget = Center(
112      child: Material(
113        child: Container(
114          color: Colors.black.withOpacity(0.5),
115          padding: const EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0),
116          child: Text(
117            text,
118            style: style,
119          ),
120        ),
121      ),
122    );
123    var entry = OverlayEntry(
124      builder: (_) => widget,
125    );
126
127    Overlay.of(context).insert(entry);
128
129    Timer(const Duration(seconds: 2), () {
130      entry?.remove();
131    });
132  }
133}

和 fluttertoast 的对比

为什么不使用 fluttertoast 呢, 我曾经也给 fluttertoast 提交过 PR

但是这个插件本身是依赖于原生的,android 端不可避免在默认样式上会受到 rom 的影响,并且各种属性会有兼容问题

我信奉的原则是,UI 层级的问题,直接在 flutter 端解决

后记

代码使用并不复杂, 如果对你有帮助解决了问题, 可以给我赞赏 ,请我喝咖啡(下方二维码)