I'm trying to have the drawer persisted, meaning it stays open when navigating through the screens. For this I have a custom scaffold that takes GlobalKey parameter. The implementation of this is like so:
MyScaffold(
...
late GlobalKey<ScaffoldState> _scaffoldKey;
@override
void initState() {
super.initState();
_scaffoldKey = widget.scaffoldKey;
}
Scaffold(
key: _scaffoldKey,
drawer: MouseRegion(
onExit: (_) {
_scaffoldKey.currentState?.closeDrawer();
},
child: Drawer(...),
),
),
body: ...,
)
)
...
)
As you can see, basically what I want to accomplish is that when the drawer is hovered it remains open regardless of the navigating screens, and when the mouse leaves it closes. The functionality works as intended, however, when the drawer closes I get this exception:
2024-03-11 14:05:17.401891: 'package:flutter/src/widgets/overlay.dart': Failed assertion: line 190 pos 12: '!_disposedByOwner': is not true.
2024-03-11 14:05:17.402279: #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:51:61)
#1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5)
#2 OverlayEntry.markNeedsBuild (package:flutter/src/widgets/overlay.dart:190:12)
#3 ModalRoute.changedInternalState (package:flutter/src/widgets/routes.dart:1711:19)
#4 LocalHistoryRoute.removeLocalHistoryEntry (package:flutter/src/widgets/routes.dart:715:9)
#5 LocalHistoryEntry.remove (package:flutter/src/widgets/routes.dart:519:13)
#6 DrawerControllerState._animationStatusChanged (package:flutter/src/material/drawer.dart:527:24)
#7 AnimationLocalStatusListenersMixin.notifyStatusListeners (package:flutter/src/animation/listener_helpers.dart:240:19)
#8 AnimationController._checkStatusChanged (package:flutter/src/animation/animation_controller.dart:815:7)
#9 AnimationController._startSimulation (package:flutter/src/animation/animation_controller.dart:749:5)
#10 AnimationController.fling (package:flutter/src/animation/animation_controller.dart:712:12)
#11 DrawerControllerState.close (package:flutter/src/material/drawer.dart:630:17)
#12 ScaffoldState.closeDrawer (package:flutter/src/material/scaffold.dart:2271:31)
#13 TigerScaffoldState.build.<anonymous closure>.<anonymous closure> (package:tigerui/widgets/tiger_scaffold.dart:157:50)
#14 MouseTracker._handleDeviceUpdateMouseEvents.<anonymous closure> (package:flutter/src/rendering/mouse_tracker.dart:417:29)
#15 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:633:13)
#16 MouseTracker._handleDeviceUpdateMouseEvents (package:flutter/src/rendering/mouse_tracker.dart:414:21)
#17 MouseTracker._handleDeviceUpdate (package:flutter/src/rendering/mouse_tracker.dart:282:5)
#18 MouseTracker.updateWithEvent.<anonymous closure>.<anonymous closure> (package:flutter/src/rendering/mouse_tracker.dart:351:9)
#19 MouseTracker._deviceUpdatePhase (package:flutter/src/rendering/mouse_tracker.dart:210:9)
#20 MouseTracker.updateWithEvent.<anonymous closure> (package:flutter/src/rendering/mouse_tracker.dart:328:7)
#21 MouseTracker._monitorMouseConnection (package:flutter/src/rendering/mouse_tracker.dart:193:9)
#22 MouseTracker.updateWithEvent (package:flutter/src/rendering/mouse_tracker.dart:327:5)
#23 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:432:20)
#24 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:413:7)
#25 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:376:5)
#26 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:323:7)
#27 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:292:9)
#28 _invoke1 (dart:ui/hooks.dart:328:13)
#29 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:410:7)
#30 _dispatchPointerDataPacket (dart:ui/hooks.dart:262:31)
Is there anyway I could prevent this exception?
I have tried:
- Adding WidgetsBinding.instance.postFrameCall
- Using mounted attribute
- Adding a delayed future
I believe you get this error because your
Drawerwidget is built using the first page's builder. When navigating to a new page, it disposes all previous widget trees and re-build new widgets, hence the error because it failed to dispose theDrawerwidget properly.I suggest wrapping your
Drawerwith anOverlaywidget and placing it in the global (app level) area outside your class to make it independent of route changes, then create a function to show/hide the drawer.So step 1: Instead of using the drawer parameter, use the leading parameter so you can have a button to call the Overlay Drawer:
Step 2: Create the
OverlayDrawerclass. This here is just an example (see full working demo at https://dartpad.dev/?id=612b6b178e2396081c3b6b55beb7a31f)You can find a similar topic for persisting a Dialog between navigation here: is there any way in flutter to persist dialog when moving from one screen to another?