Tooltip 提示

https://api.flutter.dev/flutter/material/Tooltip-class.html
一个文本提示工具,帮助解释一个按钮或其他用户界面,当widget长时间按下时(当用户采取其他适当操作时)显示一个提示标签。

  1. Tooltip({
  2. Key key,
  3. @required this.message,
  4. this.height, //高度
  5. this.padding,
  6. this.margin,
  7. this.verticalOffset, //垂直偏移
  8. this.preferBelow,
  9. this.excludeFromSemantics,
  10. this.decoration,
  11. this.textStyle,
  12. this.waitDuration,
  13. this.showDuration,
  14. this.child,
  15. })

示例

image.png

  1. Tooltip(
  2. message: '我是提示',
  3. child: RaisedButton(
  4. child: Text('按钮'),
  5. onPressed: () {},
  6. ),
  7. ),

某些Material组件(如IconButton)已包含工具提示,直接使用即可。

  1. IconButton(
  2. icon: Icon(Icons.access_alarm),
  3. onPressed: () {},
  4. tooltip: '提示文案',
  5. ),

showDialog

系统内置的dialog,默认会占满屏幕。返回一个Future对象。

  1. Future<T> showDialog<T>({
  2. @required BuildContext context,
  3. WidgetBuilder builder,
  4. bool barrierDismissible = true, //点击遮罩,是否退出对话框
  5. Color barrierColor,
  6. bool useSafeArea = true,
  7. bool useRootNavigator = true,
  8. RouteSettings routeSettings,
  9. })
  1. import "package:flutter/material.dart";
  2. class DialogDemo extends StatelessWidget {
  3. _alertDialog(context) {
  4. // print(context); //DialogDemo(state: _DialogDemoState#2b533)
  5. showDialog(
  6. context: context,
  7. builder: (context) => Container(
  8. height: 100,
  9. color: Colors.red,
  10. ),
  11. );
  12. }
  13. @override
  14. Widget build(BuildContext context) {
  15. return Container(
  16. child: Column(
  17. children: [
  18. RaisedButton(
  19. child: Text('alert弹出框-AlertDialog'),
  20. onPressed: _alertDialog,
  21. ),
  22. ],
  23. ),
  24. );
  25. }
  26. }

image.png

AlertDialog 确认框

https://docs.flutter.io/flutter/material/AlertDialog-class.html
一个会中断用户操作的对话款,需要用户确认。

  1. AlertDialog({
  2. Key key,
  3. this.title, //标题
  4. this.titlePadding,
  5. this.titleTextStyle,
  6. this.content, //内容
  7. this.contentPadding = const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0),
  8. this.contentTextStyle,
  9. this.actions, //底部按钮数组
  10. this.actionsPadding = EdgeInsets.zero,
  11. this.actionsOverflowDirection,
  12. this.actionsOverflowButtonSpacing,
  13. this.buttonPadding,
  14. this.backgroundColor, //背景色
  15. this.elevation,
  16. this.semanticLabel,
  17. this.insetPadding = _defaultInsetPadding,
  18. this.clipBehavior = Clip.none,
  19. this.shape, //可参考RaisedButton控件的shape参数
  20. this.scrollable = false,
  21. })

示例

image.png

写法1:
  1. _alertDialog(){
  2. showDialog(
  3. context: context,
  4. builder: (context) {
  5. return AlertDialog(
  6. title: Text('提示信息'),
  7. content: Text('你确定要删除吗?'),
  8. actions: [
  9. FlatButton(
  10. child: Text('取消'),
  11. onPressed: () {
  12. print('取消');
  13. Navigator.pop(context); //关闭确认框
  14. },
  15. ),
  16. FlatButton(
  17. child: Text('确定'),
  18. onPressed: () {
  19. print('确定');
  20. Navigator.pop(context);
  21. },
  22. ),
  23. ],
  24. );
  25. },
  26. );
  27. }

写法2:
  1. _alertDialog() async {
  2. var result = await showDialog(
  3. context: context,
  4. builder: (context) {
  5. return AlertDialog(
  6. title: Text('提示信息'),
  7. content: Text('你确定要删除吗?'),
  8. actions: [
  9. FlatButton(
  10. child: Text('取消'),
  11. onPressed: () {
  12. Navigator.pop(context, 'cancel');
  13. },
  14. ),
  15. FlatButton(
  16. child: Text('确定'),
  17. onPressed: () {
  18. Navigator.pop(context, 'ok');
  19. },
  20. ),
  21. ],
  22. );
  23. },
  24. );
  25. if (result == 'ok') {
  26. print('确定');
  27. } else {
  28. print('取消');
  29. }
  30. }

CupertinoAlertDialog ios风格确认框

showDialogAlertDialog配合使用展示Material风格对话框。
showCupertinoDialogCupertinoAlertDialog配合使用展示iOS风格对话框。

showCupertinoDialog点击空白处是无法退出对话框的,而showDialog点击空白处默认退出对话框。

image.png

  1. showCupertinoDialog(
  2. context: context,
  3. builder: (context) {
  4. return CupertinoAlertDialog(
  5. title: Text('提示'),
  6. content: Text('确认删除吗?'),
  7. actions: [
  8. CupertinoDialogAction(
  9. child: Text('取消'),
  10. onPressed: () {},
  11. ),
  12. CupertinoDialogAction(
  13. child: Text('确认'),
  14. onPressed: () {},
  15. ),
  16. ],
  17. );
  18. },
  19. );

bug: The getter ‘modalBarrierDismissLabel’ was called on null.

问题描述:如果在MaterialApp里调用showCupertinoDialog显示弹出框,可能会遇到这个错误。
原因分析:就是Material主题下Context没有这个Cupertine主题的属性

方法1:

  1. localizationsDelegates: [
  2. ...
  3. GlobalCupertinoLocalizations.delegate, //添加这行即可解决问题
  4. ],
  5. 注意:需要在pubspec.yaml添加localizations依赖,如下:
  6. dependencies:
  7. flutter_localizations:
  8. sdk: flutter

方法2:
在 main.dart 文件中加入 localizationsDelegates 这个属性,并在其中加入FallbackCupertinoLocalisationsDelegate(),不需要的不要加。并且在该文件下生成对应的类:

  1. localizationsDelegates: [
  2. ...
  3. FallbackCupertinoLocalisationsDelegate(),
  4. ],
  5. class FallbackCupertinoLocalisationsDelegate extends LocalizationsDelegate<CupertinoLocalizations> {
  6. const FallbackCupertinoLocalisationsDelegate();
  7. @override
  8. bool isSupported(Locale locale) => true;
  9. @override
  10. Future<CupertinoLocalizations> load(Locale locale) => DefaultCupertinoLocalizations.load(locale);
  11. @override
  12. bool shouldReload(FallbackCupertinoLocalisationsDelegate old) => false;
  13. }

SimpleDialog 选择框

https://api.flutter.dev/flutter/material/SimpleDialog-class.html
简单对话框可以显示附加的提示或操作。
image.png

  1. void _simpleDialog() async {
  2. showDialog(
  3. context: context,
  4. builder: (context) {
  5. return SimpleDialog(
  6. title: Text('选择内容'),
  7. children: [
  8. SimpleDialogOption(child: Text('Option A'), onPressed: () {}),
  9. Divider(),
  10. SimpleDialogOption(child: Text('Option B'), onPressed: () {}),
  11. Divider(),
  12. SimpleDialogOption(child: Text('Option C'), onPressed: () {}),
  13. ],
  14. );
  15. },
  16. );
  17. }
  18. //...
  19. RaisedButton(
  20. child: Text('select弹出框-SimpleDialog'),
  21. onPressed: _simpleDialog,
  22. ),

BottomSheet 底部滑框

https://api.flutter.dev/flutter/material/BottomSheet-class.html
BottomSheet是一个从屏幕底部滑起的列表(以显示更多的内容)。你可以调用showBottomSheet()或showModalBottomSheet弹出。
image.png

  1. void _modalBottomSheet() async {
  2. // showBottomSheet() 占全屏
  3. // showModalBottomSheet() 默认占底部半屏左右,可以设置高度
  4. var result = await showModalBottomSheet(
  5. context: context,
  6. builder: (context) {
  7. return Container(
  8. height: 200,
  9. child: Column(
  10. children: [
  11. ListTile(
  12. title: Text('分享 A'),
  13. onTap: () {
  14. Navigator.pop(context, 'a');
  15. },
  16. ),
  17. ListTile(
  18. title: Text('分享 B'),
  19. onTap: () {
  20. Navigator.pop(context, 'b');
  21. },
  22. ),
  23. ListTile(
  24. title: Text('分享 C'),
  25. onTap: () {
  26. Navigator.pop(context, 'c');
  27. },
  28. ),
  29. ],
  30. ),
  31. );
  32. },
  33. );
  34. print(result);
  35. }
  36. //...
  37. aisedButton(
  38. child: Text('ActionSheet底部弹出框-showModalBottomSheet'),
  39. onPressed: _modalBottomSheet,
  40. ),

SnackBar 底部轻提示

https://api.flutter.dev/flutter/material/SnackBar-class.html
带有可选操作的轻量级消息,在屏幕底部短暂显示,SnackBar一般不单独使用,而是配合Scaffold.of(context).showSnackBar进行弹出展示。

定义
  1. SnackBar({
  2. Key key,
  3. @required this.content,
  4. this.backgroundColor, //背景色
  5. this.elevation, //阴影
  6. this.margin,
  7. this.padding,
  8. this.width, //需搭配 behavior: SnackBarBehavior.floating, 模式
  9. this.shape, //形状
  10. this.behavior, //弹出形式。fixed floating
  11. this.action, //搭配 SnackBarAction 使用
  12. this.duration = _snackBarDisplayDuration, //设置显示时间,默认是4秒。duration: Duration(seconds: 1),
  13. this.animation,
  14. this.onVisible, //在显示的时候调用
  15. })

简单使用

image.png

  1. Builder(
  2. builder: (context) {
  3. return RaisedButton(
  4. child: Text('click me'),
  5. onPressed: () {
  6. // 查找父级最近的Scaffold对应的ScaffoldState对象
  7. // ScaffoldState _state = context.findAncestorStateOfType<ScaffoldState>();
  8. ScaffoldState _state = Scaffold.of(context);
  9. //调用ScaffoldState的showSnackBar来弹出SnackBar
  10. _state.showSnackBar(
  11. SnackBar(
  12. content: Text('hello world'),
  13. ),
  14. );
  15. },
  16. );
  17. },
  18. ),

设置样式

image.png

  1. SnackBar(
  2. backgroundColor: Colors.red,
  3. elevation: 8,
  4. width: 200,
  5. behavior: SnackBarBehavior.floating,
  6. action: SnackBarAction(
  7. label: 'click me',
  8. onPressed: () {},
  9. ),
  10. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(100)),
  11. content: Text('hello world'),
  12. ),

瞬间多个弹出延迟问题

当短时间内多次调用SnackBar方法时,SnackBar消息将会以队列的形式一个一个的弹出,比如下面的代码:

  1. RaisedButton(
  2. child: Text(
  3. '点我,弹出SnackBar',
  4. ),
  5. onPressed: () {
  6. List.generate(10, (index){
  7. Scaffold.of(context).showSnackBar(SnackBar(
  8. content: Text('我是消息:$index'),
  9. ));
  10. });
  11. },
  12. )

默认情况下每个显示4秒,如果有10个,那么40秒内会一直弹消息,体验明显不友好,我们希望的效果是如果有新的消息时,旧的都消息立刻消失,显示新的消息,只需在弹出新的SnackBar时移除现在的SnackBar,

  1. Scaffold.of(context).removeCurrentSnackBar();
  2. Scaffold.of(context).showSnackBar(...);

ExpansionPanel 扩展框

https://api.flutter.dev/flutter/material/ExpansionPanel-class.html

ExpansionPanel

一个material 扩展面板。它有一个 header 和一个 body ,可以展开或折叠。面板的 body 仅在展开时可见。 扩展面板仅用作于 ExpansionPanelList。

  1. ExpansionPanel({
  2. @required this.headerBuilder,
  3. @required this.body,
  4. this.isExpanded = false, //是否展开
  5. this.canTapOnHeader = false, //header是否可以点击
  6. })

ExpansionPanelList

material 展开面板列表,用于设置其子项并为展开设置动画。

  1. const ExpansionPanelList({
  2. Key key,
  3. this.children = const <ExpansionPanel>[], //就是 ExpansionPanel
  4. this.expansionCallback, //展开回调,expansionCallback: (int index, bool isExpanded){}
  5. this.animationDuration = kThemeAnimationDuration, //动画的时间
  6. this.expandedHeaderPadding = _kPanelHeaderExpandedDefaultPadding,
  7. this.dividerColor,
  8. this.elevation = 2,
  9. })

示例
f381t36hba.gif

  1. import 'package:flutter/material.dart';
  2. class Item {
  3. Item({
  4. this.expandedValue,
  5. this.headerValue,
  6. this.isExpanded = false,
  7. });
  8. String expandedValue; //展开的title值
  9. String headerValue; //header的值
  10. bool isExpanded; //是否已经展开
  11. }
  12. // 生成指定数量的List
  13. List<Item> generateItems(int counter) {
  14. return List.generate(counter, (int index) {
  15. return Item(
  16. headerValue: 'Panel $index',
  17. expandedValue: 'This is item number $index',
  18. );
  19. });
  20. }
  21. class ExpansionPanelPage extends StatefulWidget {
  22. ExpansionPanelPage({Key key}) : super(key: key);
  23. @override
  24. _ExpansionPanelPageState createState() => _ExpansionPanelPageState();
  25. }
  26. class _ExpansionPanelPageState extends State<ExpansionPanelPage> {
  27. List<Item> _data = generateItems(8);
  28. @override
  29. Widget build(BuildContext context) {
  30. return Scaffold(
  31. appBar: AppBar(title: Text('ExpansionPanelPage demo')),
  32. body: SingleChildScrollView(
  33. child: Container(
  34. child: _buildPanel(),
  35. ),
  36. ),
  37. );
  38. }
  39. Widget _buildPanel() {
  40. return ExpansionPanelList(
  41. expansionCallback: (int index, bool isExpanded) {
  42. setState(() {
  43. _data[index].isExpanded = !isExpanded;
  44. });
  45. },
  46. children: _data.map<ExpansionPanel>((Item item) {
  47. return ExpansionPanel(
  48. headerBuilder: (BuildContext context, bool isExpanded) {
  49. return ListTile(title: Text(item.headerValue));
  50. },
  51. body: ListTile(
  52. title: Text(item.expandedValue),
  53. subtitle: Text('To delete this panel, tap the trash can icon'),
  54. trailing: Icon(Icons.delete),
  55. onTap: () {
  56. setState(() {
  57. _data.removeWhere((currentItem) => item == currentItem);
  58. });
  59. }),
  60. isExpanded: item.isExpanded,
  61. );
  62. }).toList(),
  63. );
  64. }
  65. }

什么要用 SingleChildScrollView 包起来?

我们先把 SingleChildScrollView 去掉来看一下效果:
image.png
发现什么都没有了,看一下log:

flutter: The following assertion was thrown during performLayout(): flutter: RenderListBody must have unlimited space along its main axis. flutter: RenderListBody does not clip or resize its children, so it must be placed in a parent that does not flutter: constrain the main axis. You probably want to put the RenderListBody inside a RenderViewport with a matching main axis.

大致意思就是说:
RenderListBody所在的主轴必须要有无线的空间,因为RenderListBody 要不断的调整children 的大小,所以必须把它放在不约束主轴的 parent 中。

body is ListView

在我们实际业务中,可能最多的业务为展开是一个列表,那需要 body 是ListView。
其实和官方Demo差不多,需要注意的一点就是 shrinkWrap & physics 这两个字段:

  1. return ListView.builder(
  2. shrinkWrap: true,
  3. physics: NeverScrollableScrollPhysics(),
  4. );

q8oycmg9jw.gif

只能展开一个

有时我们也会遇到只能展开一个,点击其他的时候要关闭已经展开的。
zg5ljea63y.gif
代码如下,需使用 ExpansionPanelList.radio
ExpansionPanelList.radio 的 children 也需要改变为: ExpansionPanelRadio
ExpansionPanelRadioExpansionPanel 的区别就是一个 value。
ExpansionPanelRadio 是用 value 来区分的,所以每一个要是唯一的。

  1. Widget _buildPanel() {
  2. return ExpansionPanelList.radio(
  3. expansionCallback: (int index, bool isExpanded) {
  4. setState(() {
  5. _data[index].isExpanded = !isExpanded;
  6. });
  7. },
  8. children: _data.map<ExpansionPanel>((Item item) {
  9. return ExpansionPanelRadio(
  10. canTapOnHeader: true,
  11. headerBuilder: (BuildContext context, bool isExpanded) {
  12. return ListTile(
  13. title: Text(item.headerValue),
  14. );
  15. },
  16. body: ListTile(
  17. title: Text(item.expandedValue),
  18. subtitle: Text('To delete this panel, tap the trash can icon'),
  19. trailing: Icon(Icons.delete),
  20. onTap: () {
  21. setState(() {
  22. _data.removeWhere((currentItem) => item == currentItem);
  23. });
  24. }),
  25. value: item.headerValue,
  26. );
  27. }).toList(),
  28. );
  29. }

自定义Dialog

自定义 Dialog 对象,需要继承 Dialog 类,尽管 Dialog 提供了child 参数可以用来写视图界面,但是往往达不到想要的效果,因为默认的 Dialog 背景框是满屏的。如果我们想完全定义界面,就需要重写 build 函数。

示例:简单对话框

image.png

  1. import 'package:app1/coms/dialogs/MyDialog.dart';
  2. //...
  3. RaisedButton(
  4. child: Text('自定义Dialog'),
  5. onPressed: () {
  6. showDialog(
  7. context: context,
  8. builder: (context) {
  9. return MyDialog(
  10. title: '我是标题',
  11. content: '我是内容',
  12. );
  13. },
  14. );
  15. },
  16. ),
  1. import 'package:flutter/material.dart';
  2. class MyDialog extends StatelessWidget {
  3. String title;
  4. String content;
  5. MyDialog({
  6. key,
  7. this.title = null,
  8. this.content = null,
  9. }) : super(key: key);
  10. @override
  11. Widget build(BuildContext context) {
  12. return Material(
  13. type: MaterialType.transparency, //背景透明
  14. child: Center(
  15. child: Container(
  16. width: 300,
  17. constraints: BoxConstraints(minHeight: 200),
  18. color: Colors.white,
  19. child: Column(
  20. mainAxisSize: MainAxisSize.min,
  21. children: [
  22. Padding(
  23. padding: EdgeInsets.all(10),
  24. child: Stack(
  25. children: [
  26. Align(
  27. alignment: Alignment.bottomCenter,
  28. child: Text(this.title),
  29. ),
  30. Align(
  31. alignment: Alignment.centerRight,
  32. child: InkWell(
  33. child: Icon(Icons.close),
  34. onTap: () {
  35. Navigator.pop(context);
  36. },
  37. ),
  38. ),
  39. ],
  40. ),
  41. ),
  42. Divider(),
  43. Container(
  44. width: double.infinity,
  45. padding: EdgeInsets.all(10),
  46. child: Text(this.content),
  47. ),
  48. ],
  49. ),
  50. ),
  51. ),
  52. );
  53. }
  54. }

示例:loading对话框

image.png

  1. showDialog(
  2. context: context,
  3. builder: (context) {
  4. return MyDialog(
  5. title: '数据请求中',
  6. );
  7. },
  8. );
  1. import 'dart:async';
  2. import 'package:flutter/material.dart';
  3. class MyDialog extends StatelessWidget {
  4. String title;
  5. MyDialog({
  6. key,
  7. this.title = null,
  8. }) : super(key: key);
  9. _showTimer(context) {
  10. var timer = null;
  11. timer = Timer.periodic(Duration(milliseconds: 3000), (t) {
  12. Navigator.pop(context);
  13. t.cancel(); //取消定时器
  14. });
  15. }
  16. @override
  17. Widget build(BuildContext context) {
  18. _showTimer(context);
  19. return Material(
  20. type: MaterialType.transparency,
  21. child: Center(
  22. child: Container(
  23. width: 200,
  24. padding: EdgeInsets.all(20),
  25. color: Colors.white,
  26. child: Column(
  27. mainAxisSize: MainAxisSize.min,
  28. children: [
  29. Container(
  30. width: 70,
  31. height: 70,
  32. child: CircularProgressIndicator(
  33. backgroundColor: Colors.grey,
  34. valueColor: AlwaysStoppedAnimation(Colors.green),
  35. strokeWidth: 6.0,
  36. ),
  37. ),
  38. Container(
  39. padding: EdgeInsets.only(top: 20, bottom: 10),
  40. child: Text(this.title),
  41. ),
  42. ],
  43. ),
  44. ),
  45. ),
  46. );
  47. }
  48. }

库 fluttertoast

https://pub.dev/packages/fluttertoast

image.png

  1. import "package:flutter/material.dart";
  2. import 'package:fluttertoast/fluttertoast.dart';
  3. class DialogDemo extends StatelessWidget {
  4. void _toast() {
  5. Fluttertoast.showToast(
  6. msg: "This is Center Short Toast",
  7. toastLength: Toast.LENGTH_SHORT, //LENGTH_SHORT LENGTH_LONG
  8. gravity: ToastGravity.CENTER, //位置 TOP BOTTOM CENTER
  9. timeInSecForIosWeb: 1, //只在ios上有效果
  10. backgroundColor: Colors.blue,
  11. textColor: Colors.white,
  12. fontSize: 16.0,
  13. );
  14. }
  15. @override
  16. Widget build(BuildContext context) {
  17. return Container(
  18. child: Column(
  19. children: [
  20. RaisedButton(
  21. child: Text('toast-fluttertoast第三方库'),
  22. onPressed: _toast,
  23. ),
  24. ],
  25. ),
  26. );
  27. }
  28. }

属性
property description default
msg String (Not Null)(required) required
toastLength Toast.LENGTH_SHORT or Toast.LENGTH_LONG (optional) Toast.LENGTH_SHORT
gravity ToastGravity.TOP (or) ToastGravity.CENTER (or) ToastGravity.BOTTOM (Web Only supports top, bottom) ToastGravity.BOTTOM
timeInSecForIosWeb int (for ios & web) 1 (sec)
backgroundColor Colors.red null
textcolor Colors.white null
fontSize 16.0 (float) null
webShowClose false (bool) false
webBgColor String (hex Color) linear-gradient(to right, #00b09b, #96c93d)
webPosition String (left, center or right) right

To cancel all the toasts call
  1. Fluttertoast.cancel()

库 flutter_easyloading

https://pub.dev/packages/flutter_easyloading
中文说明:https://github.com/kokohuang/flutter_easyloading/blob/master/README-zh_CN.md

安装依赖
  1. dependencies:
  2. flutter_easyloading: ^2.2.1

导入
  1. import 'package:flutter_easyloading/flutter_easyloading.dart';

使用

首先, 在MaterialApp/CupertinoApp中初始化FlutterEasyLoading:

  1. class MyApp extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return MaterialApp(
  5. title: 'Flutter EasyLoading',
  6. theme: ThemeData(
  7. primarySwatch: Colors.blue,
  8. ),
  9. home: MyHomePage(title: 'Flutter EasyLoading'),
  10. builder: EasyLoading.init(),
  11. );
  12. }
  13. }

调用
image.png image.png image.png image.png image.png image.png

  1. EasyLoading.show(status: 'loading...');
  2. EasyLoading.showProgress(0.3, status: 'downloading...');
  3. EasyLoading.showSuccess('Great Success!');
  4. EasyLoading.showError('Failed with Error');
  5. EasyLoading.showInfo('Useful Information.');
  6. EasyLoading.showToast('Toast');
  7. //关闭
  8. EasyLoading.dismiss();

添加 Loading 状态回调

  1. EasyLoading.show(status: 'loading...');
  2. Timer(Duration(milliseconds: 1000), () {
  3. EasyLoading.dismiss();
  4. });
  5. EasyLoading.addStatusCallback((status) {
  6. print('EasyLoading Status: $status');
  7. //EasyLoading Status: EasyLoadingStatus.show
  8. // 1秒后输出:EasyLoading Status: EasyLoadingStatus.dismiss
  9. });

移除 Loading 状态回调

  1. EasyLoading.removeCallback(statusCallback);
  2. EasyLoading.removeAllCallbacks();

自定义
  • textColorindicatorColorprogressColorbackgroundColor 仅对 EasyLoadingStyle.custom有效。
  • maskColor 仅对 EasyLoadingMaskType.custom有效。
  1. //使用示例
  2. EasyLoading.instance.loadingStyle = EasyLoadingStyle.light;
  3. EasyLoading.instance.indicatorType = EasyLoadingIndicatorType.threeBounce;
  4. EasyLoading.show(status: 'loading...');
  5. loadingStyle //loading的样式,默认[EasyLoadingStyle.dark] light
  6. indicatorType //loading的指示器类型, 默认[EasyLoadingIndicatorType.fadingCircle]
  7. maskType //loading的遮罩类型,默认[EasyLoadingMaskType.none]
  8. toastPosition //toast的位置,默认[EasyLoadingToastPosition.center]
  9. animationStyle //动画类型, 默认[EasyLoadingAnimationStyle.opacity]
  10. EasyLoadingAnimation customAnimation; // 自定义动画, 默认 null.
  11. TextAlign textAlign // 文本的对齐方式, 默认[TextAlign.center]
  12. TextStyle textStyle // 文本的样式, 默认 null
  13. EdgeInsets contentPadding // loading内容区域的内边距.
  14. EdgeInsets textPadding // 文本的内边距.
  15. double indicatorSize; // 指示器的大小, 默认40.0.
  16. double radius; // loading的圆角大小, 默认5.0.
  17. double fontSize; // 文本大小, 默认15.0.
  18. double progressWidth; // 进度条指示器的宽度, 默认2.0.
  19. double lineWidth; // 指示器的宽度, 默认4.0,
  20. //仅对[EasyLoadingIndicatorType.ring, EasyLoadingIndicatorType.dualRing]有效.
  21. Duration displayDuration; // [showSuccess] [showError] [showInfo]的展示时间, 默认2000ms.
  22. Duration animationDuration; // 动画时间, 默认200ms.
  23. Color textColor; // 文本的颜色, 仅对[EasyLoadingStyle.custom]有效.
  24. Color indicatorColor; // 指示器的颜色, 仅对[EasyLoadingStyle.custom]有效.
  25. Color progressColor; // 进度条指示器的颜色, 仅对[EasyLoadingStyle.custom]有效.
  26. Color backgroundColor; // loading的背景色, 仅对[EasyLoadingStyle.custom]有效.
  27. Color maskColor; // 遮罩的背景色, 仅对[EasyLoadingMaskType.custom]有效.
  28. bool userInteractions; // 当loading展示的时候,是否允许用户操作.
  29. bool dismissOnTap; // 点击背景是否关闭.
  30. Widget indicatorWidget; // 指示器自定义组件
  31. Widget successWidget; // 展示成功状态的自定义组件
  32. Widget errorWidget; // 展示失败状态的自定义组件
  33. Widget infoWidget; // 展示信息状态的自定义组件

因为 EasyLoading 是一个全局单例, 所以你可以在任意一个地方自定义它的样式:

  1. EasyLoading.instance
  2. ..displayDuration = const Duration(milliseconds: 2000)
  3. ..indicatorType = EasyLoadingIndicatorType.fadingCircle
  4. ..loadingStyle = EasyLoadingStyle.dark
  5. ..indicatorSize = 45.0
  6. ..radius = 10.0
  7. ..progressColor = Colors.yellow
  8. ..backgroundColor = Colors.green
  9. ..indicatorColor = Colors.yellow
  10. ..textColor = Colors.yellow
  11. ..maskColor = Colors.blue.withOpacity(0.5)
  12. ..userInteractions = true
  13. ..dismissOnTap = false
  14. ..customAnimation = CustomAnimation();

更多的指示器类型可查看 👉 flutter_spinkit showcase

自定义动画

例子: 👉 Custom Animation

loading 封装

ELoading.dart

  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_easyloading/flutter_easyloading.dart';
  3. class ELoading {
  4. // 卸载
  5. static destroy() {
  6. EasyLoading.dismiss();
  7. }
  8. // 加载框
  9. static show({String status = 'Loading...'}) {
  10. EasyLoading.instance
  11. ..indicatorType = EasyLoadingIndicatorType.threeBounce
  12. ..indicatorSize = 30.0;
  13. EasyLoading.show(status: status);
  14. }
  15. // 进度加载框
  16. static showProgress({
  17. @required double progress,
  18. String status,
  19. }) {
  20. EasyLoading.instance.indicatorSize = 45.0;
  21. EasyLoading.showProgress(progress, status: status);
  22. }
  23. // 成功信息框
  24. static showSuccess({String status}) {
  25. EasyLoading.instance.indicatorSize = 45.0;
  26. EasyLoading.showSuccess(status);
  27. }
  28. // 失败信息框
  29. static showError({String status}) {
  30. EasyLoading.instance.indicatorSize = 45.0;
  31. EasyLoading.showError(status);
  32. }
  33. // 普通信息框
  34. static showInfo({String status}) {
  35. EasyLoading.showInfo(status);
  36. }
  37. // toast轻提示
  38. static showToast({String status}) {
  39. EasyLoading.showToast(status);
  40. }
  41. }