我正在尝试进行如下所示的覆盖:
https://www.didierboelens.com/2018/06/how-to-create-a-toast-or-notifications-notion-of-overlay/
使用OverlayEntry
。
import 'package:flutter/material.dart';
import 'dart:async';
class ShowNotificationIcon {
void show(BuildContext context) async {
OverlayState overlayState = Overlay.of(context);
OverlayEntry overlayEntry = new OverlayEntry(builder: _build);
overlayState.insert(overlayEntry);
}
Widget _build(BuildContext context){
return new Positioned(
top: 50.0,
left: 50.0,
child: new Material(
color: Colors.transparent,
child: new Icon(Icons.warning, color: Colors.purple),
),
);
}
}
调用者:
ShowNotificationIcon _icon = new ShowNotificationIcon();
_icon.show(context);
但是,当我尝试导航到其他屏幕时,覆盖层仍保留在屏幕中。
如何仅在被调用的屏幕上显示叠加层,而不在其他屏幕上显示?
以防万一,这是我在状态小部件中尝试过的操作:
ShowNotificationIcon _icon = new ShowNotificationIcon();
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
_icon.show(context);
});
super.initState();
}
@override
void dispose() {
_icon.remove();
super.dispose();
}
答案 0 :(得分:1)
通常使用RouteAware
+ RouteObserver
执行此操作。
RouteObserver
是一个对象,可使实现RouteAware
的对象对与路由相关的某些更改做出反应,其中包括:
然后您可以使用这两个事件来隐藏/显示叠加层
首先,您需要一个RouteObserver
。
可以将其创建为全局变量,并需要将其传递到您的Navigator
。在基于MaterialApp
的应用中,通常如下所示:
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
void main() {
runApp(MaterialApp(
home: Container(),
navigatorObservers: [routeObserver],
));
}
然后,您拥有OverlayEntry
的小部件现在可以像这样实现RouteAware
:
class RouteAwareWidget extends StatefulWidget {
State<RouteAwareWidget> createState() => RouteAwareWidgetState();
}
// Implement RouteAware in a widget's state and subscribe it to the RouteObserver.
class RouteAwareWidgetState extends State<RouteAwareWidget> with RouteAware {
@override
void didChangeDependencies() {
super.didChangeDependencies();
// routeObserver is the global variable we created before
routeObserver.subscribe(this, ModalRoute.of(context));
}
@override
void dispose() {
routeObserver.unsubscribe(this);
super.dispose();
}
@override
void didPush() {
// Route was pushed onto navigator and is now topmost route.
}
@override
void didPopNext() {
// Covering route was popped off the navigator.
}
@override
Widget build(BuildContext context) => Container();
}
此时,您可以使用didPush
和didPopNext
显示/隐藏您的OverlayEntry:
OverlayEntry myOverlay;
@override
void didPush() {
myOverlay.remove();
}
@override
void didPopNext() {
Overlay.of(context).insert(myOverlay);
}
答案 1 :(得分:0)
我建议使用软件包flushbar。 https://github.com/AndreHaueisen/flushbar
就像软件包中所说的那样:如果在通知用户时需要更多自定义,请使用此软件包。对于Android开发人员而言,它可以替代烤面包和小吃店。
您还可以将flushbarPosition设置为TOP或BOTTOM
Flushbar(
title: "Hey Ninja",
message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
flushbarPosition: FlushbarPosition.TOP,
flushbarStyle: FlushbarStyle.FLOATING,
reverseAnimationCurve: Curves.decelerate,
forwardAnimationCurve: Curves.elasticOut,
backgroundColor: Colors.red,
boxShadows: [BoxShadow(color: Colors.blue[800], offset: Offset(0.0, 2.0), blurRadius: 3.0)],
backgroundGradient: LinearGradient(colors: [Colors.blueGrey, Colors.black]),
isDismissible: false,
duration: Duration(seconds: 4),
icon: Icon(
Icons.check,
color: Colors.greenAccent,
),
mainButton: FlatButton(
onPressed: () {},
child: Text(
"CLAP",
style: TextStyle(color: Colors.amber),
),
),
showProgressIndicator: true,
progressIndicatorBackgroundColor: Colors.blueGrey,
titleText: Text(
"Hello Hero",
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 20.0, color: Colors.yellow[600], fontFamily: "ShadowsIntoLightTwo"),
),
messageText: Text(
"You killed that giant monster in the city. Congratulations!",
style: TextStyle(fontSize: 18.0, color: Colors.green, fontFamily: "ShadowsIntoLightTwo"),
),
)..show(context);