Flutter实现Toast效果

fluttertoast

目前Flutter官方暂未提供toast工具类,可以利用第三方库fluttertoast

Github:https://github.com/PonnamKarthik/FlutterToast
DartHub: https://pub.dartlang.org/packages/fluttertoast

1
2
3
4
5
6
7
8
9
10
11
import 'package:fluttertoast/fluttertoast.dart';

Fluttertoast.showToast(
msg: "This is Center Short Toast",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIos: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0
);

Overlay实现

Draggable源码中有这么一段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class _DragAvatar<T> extends Drag {
_DragAvatar({
@required this.overlayState,
this.data,
this.axis,
Offset initialPosition,
this.dragStartPoint = Offset.zero,
this.feedback,
this.feedbackOffset = Offset.zero,
this.onDragEnd,
@required this.ignoringFeedbackSemantics,
}) : assert(overlayState != null),
assert(ignoringFeedbackSemantics != null),
assert(dragStartPoint != null),
assert(feedbackOffset != null) {
_entry = OverlayEntry(builder: _build); //在这里创建一个Entry
overlayState.insert(_entry); //将Entry添加到OverlayState中
_position = initialPosition;
updateDrag(initialPosition);
}
}

_DragAvatar是Draggable中的私有类,主要作用是当识别到拖拽事件的时候,在屏幕上绘制相应的Widget跟随手指移动。可以看到,绘制跟随手指移动的Widget的关键代码是创建一个OverlayEntry,然后将其添加到OverlayState中。

OverlayState事实上是有一个Overlay的Widget,是一个StatefullWidget,它的createState方法获取的就是OverlayState对象。
Overlay可以认为是一个UI上面的蒙版/浮空层,使用起来类似Stack,如何使用:通过Overlay.of获得OverlayState对象,调用OverlayState.insert添加OverlayEntry,当不需要的时候,通过OverlayEntry.remove移除OverlayEntry。

OverlayState使用示例:

1
2
3
4
5
6
7
8
9
//获取OverlayState
OverlayState overlayState = Overlay.of(context);
//创建OverlayEntry
OverlayEntry _overlayEntry = OverlayEntry(
builder: (BuildContext context) => Positioned(
child: Icon(Icons.android),
));
//显示到屏幕上
overlayState.insert(_overlayEntry);

这样就可以在屏幕上显示一个Icon。并且可以通过修改Positioned的left,top,right,bottom等值来修改Overlay在屏幕中的位置。最后,通过_overlayEntry.remove();进行移除,让Overlay在屏幕上消失。

例如我们做一个出现2秒后消失的Icon:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void addOverlayAutoHide() async {
//获取OverlayState
OverlayState overlayState = Overlay.of(context);
//创建OverlayEntry
OverlayEntry _overlayEntry = OverlayEntry(
builder: (BuildContext context) => Positioned(
child: Icon(Icons.android),
));
//显示到屏幕上。
overlayState.insert(_overlayEntry);
//等待2秒
await Future.delayed(Duration(seconds: 2));
//移除
_overlayEntry.remove();
}

做到这里,思路已经很清晰了。稍微修改一下OverlayEntry的build方法返回一个符合要求的toast,然后加个渐变透明的动画。基本上就能满足我们的需求啦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
class MyToast {
static OverlayEntry _overlayEntry; //toast靠它加到屏幕上
static bool _showing = false; //toast是否正在showing
static DateTime _startedTime; //开启一个新toast的当前时间,用于对比是否已经展示了足够时间
static String _msg;

static void toast(
BuildContext context,
String msg,
) async {
assert(msg != null);
_msg = msg;
_startedTime = DateTime.now();

//获取OverlayState
OverlayState overlayState = Overlay.of(context);
_showing = true;
if (_overlayEntry == null) {
_overlayEntry = OverlayEntry(
builder: (BuildContext context) => Positioned(
//top值,可以改变这个值来改变toast在屏幕中的位置
top: MediaQuery.of(context).size.height * 2 / 3,
child: Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 80.0),
child: AnimatedOpacity(
opacity: _showing ? 1.0 : 0.0, //目标透明度
duration: _showing
? Duration(milliseconds: 100)
: Duration(milliseconds: 400),
child: _buildToastWidget(),
),
)),
));
overlayState.insert(_overlayEntry);
} else {
//重新绘制UI,类似setState
_overlayEntry.markNeedsBuild();
}
await Future.delayed(Duration(milliseconds: 2000)); //等待两秒

//2秒后 到底消失不消失
if (DateTime.now().difference(_startedTime).inMilliseconds >= 2000) {
_showing = false;
_overlayEntry.markNeedsBuild();
}
}

//toast绘制
static _buildToastWidget() {
return Center(
child: Card(
color: Colors.black26,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
child: Text(
_msg,
style: TextStyle(
fontSize: 14.0,
color: Colors.white,
),
),
),
),
);
}
}

Flutter Toast

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :