You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter:如何在不同类中通过超时移除Overlay?

问题原因与解决方案

问题根源

你每次调用Notify()都会生成一个全新的实例:

  • 点击按钮时调用Notify().show(context),创建的是实例A,这个实例里的_overlayEntry指向了插入的Overlay;
  • 超时后调用Notify().dismiss(),创建的是实例B,这个实例的_overlayEntry是null,自然无法移除Overlay。
    而Overlay内部点击时调用的是实例A自己的_overlayEntry?.remove(),所以能正常生效。

解决方案

方案1:在调用类中持有同一个Notify实例

修改Fd类,创建一个固定的Notify成员变量,确保show和dismiss调用的是同一个实例:

class Fd extends StatelessWidget{
  late Timer rtime;
  int _start=4;
  int _dstart=4;
  // 持有同一个Notify实例
  final Notify _notify = Notify();

  Timer timeItOut() {
    const oneSec = const Duration(seconds: 1);
    rtime = Timer.periodic(
      oneSec,
      (Timer timer) {
        if (_start == 1) {
          _start = _dstart;
          rtime.cancel();
          _notify.dismiss(); // 调用同一个实例的dismiss方法
        } else {
          _start = _start - 1;
          print('still counting down $_start');
        }
      }
    );
    return rtime;
  }

  @override
  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(title: const Text('Feeding the nation'),),
      body: Container(
        child:IconButton(
          icon: const Icon(Icons.food_bank),
          onPressed: (){
            timeItOut(); 
            _notify.show(context); // 调用同一个实例的show方法
          },
        )
      ),
    );
  }
}

方案2:将Notify改为普通工具类(更合理)

因为Notify本质是管理Overlay的逻辑,不需要作为Widget存在,可以去掉StatelessWidget继承,改成普通类:

class Notify {
  OverlayEntry? _overlayEntry;

  void _insertOverlay(BuildContext context) {
    _overlayEntry = OverlayEntry(builder: (context) {
      return Positioned(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        top: 0,
        left: 0,
        child: Material(
          color: const Color(0xFF0E3311).withOpacity(0.2),
          child: GestureDetector(
            onTap: () => _overlayEntry?.remove(),
            child: const Icon(Icons.home, size: 100,),
          )
        ),
      );
    });
    Overlay.of(context).insert(_overlayEntry!);
  }

  void show(BuildContext context){
    _insertOverlay(context); 
  }

  void dismiss(){
    _overlayEntry?.remove();
    // 移除后置空,避免重复调用导致异常
    _overlayEntry = null;
  }
}

搭配方案1的Fd类修改,就能正常实现超时移除Overlay的功能。

内容的提问来源于stack exchange,提问作者ubakasi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:11:06