OKToast 是一款 在 flutter 上 使用的 toast 插件
使用简单, 可定制性强, 纯 flutter, 调用不用 context
查看文档: https://pub.dartlang.org/packages/oktoast#-installing-tab-
在 pubspec 引入
dependencies:
oktoast: ^2.1.7
获取包:
$ flutter packages get
引入:
import 'package:oktoast/oktoast.dart';
包裹你的 MaterialApp,不是包裹你的 Scaffold
包裹你的 MaterialApp,不是包裹你的 Scaffold
包裹你的 MaterialApp,不是包裹你的 Scaffold
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return OKToast( // 这一步
child: new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
),
);
}
}
这一步解释一下,因为一般情况下,一个 flutter 应用应该只有一个 MaterialApp(或是 WidgetsApp/CupertinoApp), 这里包裹后,可以缓存 Context 到 内存中,后续在调用显示时,不用传入 BuildContext
这样能满足一部分用户在无 context 的情况下调用 showToast
方法
showToast("hello world"); // 可选属性看自己需求
Widget widget = Center(
child:Container(
color:Colors.white,
child:Icon(Icons.add),
),
);
showToastWidget(widget);
使用如下代码的效果
void _showCustomWidgetToast() {
var w = Center(
child: Container(
padding: const EdgeInsets.all(5),
color: Colors.black.withOpacity(0.7),
child: Row(
children: [
Icon(
Icons.add,
color: Colors.white,
),
Text(
'添加成功',
style: TextStyle(color: Colors.white),
),
],
mainAxisSize: MainAxisSize.min,
),
),
);
showToastWidget(w);
}
其实简单的方案,直接使用 Overlay 就可以了,不需要插件只需要一个简单的工具类,而且代码量并不大
class ToastHelper {
static void showToast(BuildContext context, String text) {
const style = TextStyle(color: Colors.white, fontSize: 14.0);
Widget widget = Center(
child: Container(
color: Colors.black.withOpacity(0.5),
padding: const EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0),
child: Text(
text,
style: style,
),
),
);
var entry = OverlayEntry(
builder: (_) => widget,
);
Overlay.of(context).insert(entry);
Timer(const Duration(seconds: 2), () {
entry?.remove();
});
}
}
那么为什么要用 OKToast 呢?
有如下的方式可以隐藏
手动隐藏:调用这个方法就可以关闭所有的 toast 了
dismissAllToast();
在显示 toast 时隐藏之前显示的所有 toast,其实是根据这个参数在方法内调用dismissAllToast
showToast("msg", dismissOtherToast: true);
全局设置隐藏之前的属性,这里设置后,每次当你显示新的 toast 时,旧的就会被关闭
OKToast(
dismissOtherOnShow: true,
...
)
每一个 showToast/showToastWidget 方法会有一个返回值,类型是 ToastFuture
var future = showToast("msg");
future.dismiss(); // 隐藏指定的toast
OKToast 组件有丰富的自定义属性
backgroundColor: 背景颜色
duration: 延迟隐藏时间
onDismiss: 隐藏时的回调
position: toast 的位置
radius: 圆角的尺寸
textAlign: 文字在内部的对齐方式
textDirection: ltr 或 rtl
textPadding: 文本距离边框的 padding
textStyle: 文本的样式
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:oktoast/oktoast.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return OKToast(
dismissOtherOnShow: true,
child: new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or press Run > Flutter Hot Reload in IntelliJ). Notice that the
// counter didn't reset back to zero; the application is not restarted.
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State {
int _counter = 0;
void _showToast() {
showToast("msg");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("OKToast示例"),
),
body: ListView(
children: [
RaisedButton(
child: Text('文字toast'),
onPressed: _showToast,
),
RaisedButton(
child: Text('自定义Widget Toast'),
onPressed: _showCustomWidgetToast,
),
RaisedButton(
child: Text('ToastHelper '),
onPressed: () => ToastHelper.showToast(context, "toast helper"),
),
],
),
);
}
void _showCustomWidgetToast() {
var w = Center(
child: Container(
padding: const EdgeInsets.all(5),
color: Colors.black.withOpacity(0.7),
child: Row(
children: [
Icon(
Icons.add,
color: Colors.white,
),
Text(
'添加成功',
style: TextStyle(color: Colors.white),
),
],
mainAxisSize: MainAxisSize.min,
),
),
);
showToastWidget(w);
}
}
class ToastHelper {
static void showToast(BuildContext context, String text) {
const style = TextStyle(color: Colors.white, fontSize: 14.0);
Widget widget = Center(
child: Material(
child: Container(
color: Colors.black.withOpacity(0.5),
padding: const EdgeInsets.symmetric(vertical: 5.0, horizontal: 10.0),
child: Text(
text,
style: style,
),
),
),
);
var entry = OverlayEntry(
builder: (_) => widget,
);
Overlay.of(context).insert(entry);
Timer(const Duration(seconds: 2), () {
entry?.remove();
});
}
}
为什么不使用 fluttertoast 呢, 我曾经也给 fluttertoast 提交过 PR
但是这个插件本身是依赖于原生的,android 端不可避免在默认样式上会受到 rom 的影响,并且各种属性会有兼容问题
我信奉的原则是,UI 层级的问题,直接在 flutter 端解决