在Flutter中使用pushNamed导航后如何使OverlayEntry消失

时间:2019-07-26 10:16:19

标签: flutter overlay

我正在尝试进行如下所示的覆盖: 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();
  }

2 个答案:

答案 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();

}

此时,您可以使用didPushdidPopNext显示/隐藏您的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);

enter image description here