问题描述
我正在尝试进行如下所示的覆盖: https://www.didierboelens.com/2018/06/how-to-create-a-toast-or-notifications-notion-of-overlay/使用 OverlayEntry
.
I am trying to make an overlay such as that shown here:https://www.didierboelens.com/2018/06/how-to-create-a-toast-or-notifications-notion-of-overlay/using 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);
但是,当我尝试导航到其他屏幕时,覆盖层仍保留在屏幕中.
However, when I try to navigate to other screens, the overlay remains in the screen.
如何仅在被调用的屏幕上显示叠加层,而在其他屏幕上不显示?
How do I show the overlay only in the screen it is being called and not in the others?
以防万一,这是我在有状态的小部件中尝试过的操作:
Just in case, this is what I had tried inside my stateful widget:
ShowNotificationIcon _icon = new ShowNotificationIcon();
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
_icon.show(context);
});
super.initState();
}
@override
void dispose() {
_icon.remove();
super.dispose();
}
推荐答案
通常使用RouteAware
+ RouteObserver
执行此操作.
This is typically performed using RouteAware
+RouteObserver
.
RouteObserver
是一个对象,通过该对象,实现RouteAware
的对象可以对与路由相关的某些更改做出反应,其中包括:
RouteObserver
is an object that lets objects that implements RouteAware
react to some changes related to routing, which includes:
- 一条路线已推到当前路线的顶部
- 路线又回到了第一个计划
然后您可以使用这两个事件来隐藏/显示叠加层
You can then use these two events to hide/show your overlay
首先,您需要一个RouteObserver
.
可以将其创建为全局变量,并且需要将其传递给您的Navigator
.在基于MaterialApp
的应用中,通常如下所示:
This can be created as a global variable and needs to be passed to your Navigator
. In a MaterialApp
based app, it'll typically look like this:
final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();
void main() {
runApp(MaterialApp(
home: Container(),
navigatorObservers: [routeObserver],
));
}
然后,拥有OverlayEntry
的窗口小部件现在可以像下面这样实现RouteAware
:
Then, your widget that owns the OverlayEntry
can now implement RouteAware
like so:
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:
At this point, you can use didPush
and didPopNext
to show/hide your OverlayEntry:
OverlayEntry myOverlay;
@override
void didPush() {
myOverlay.remove();
}
@override
void didPopNext() {
Overlay.of(context).insert(myOverlay);
}
这篇关于在Flutter中使用pushNamed导航后如何使OverlayEntry消失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!