ModalHideMixin<T extends StatefulWidget> mixin

Position-aware destroy-on-modal helper for PlatformView-based CN-widgets.

The bug. Flutter's iOS hybrid composition inserts every UiKitView from every Flutter route into a single shared PlatformView container under the one FlutterView. Modal sheets are Flutter overlay layers (not UIKit presentations), so when a CN-widget sits on the host page AND another CN-widget lives inside a modal sheet, Flutter's per-frame overlay-quad recomputation can desync with iOS's layer-tree mutations during the sheet's drag, leaking host-page PlatformView pixels through the sheet's scrim (Issue #53).

The fix. Remove host-page PlatformViews while a sheet is up. To avoid pointlessly destroying widgets that are nowhere near the sheet (e.g. an AppBar button while a 30%-tall sheet is open), this mixin is position-aware when the sheet publishes its geometric rect via CNTabBarRouteObserver.topModalRect.

How geometry is published. Sheets opened with CNBottomSheet.show inject a small probe widget into the sheet builder; the probe writes the sheet's live global rect to topModalRect every frame (covers drag-to-dismiss correctly). For sheets opened with raw showModalBottomSheet / showCupertinoSheet (no probe), the rect stays null and the mixin falls back to "destroy everything" — the safe behavior that still kills the bleed.

Mount-depth gate. Widgets that are themselves rendered INSIDE a sheet (e.g. a CNSwitch in the sheet's body) must not self-destroy. The mixin captures anyModalDepth at mount time as _mountDepth and only considers hiding when the live depth has grown PAST that snapshot.

Usage. Override autoHideOnModal to expose the widget's flag. At the top of build() (right before constructing the UiKitView):

final hidden = maybeHiddenPlaceholder(height: h, width: w);
if (hidden != null) return hidden;
Superclass constraints

Properties

autoHideOnModal bool
Override to expose the widget's autoHideOnModal flag.
no setter
context BuildContext
The location in the tree where this widget builds.
no setterinherited
hashCode int
The hash code for this object.
no setterinherited
isAnyModalAbove bool
True iff a modal is currently presented above this widget's host route. Independent of geometry — covers widgets that stay visible (above the sheet) but should NOT be interactive while a sheet is up. Flutter's modal scrim doesn't block touches to native iOS PlatformView widgets, so we have to suppress interaction ourselves.
no setter
isHiddenForModal bool
True iff this widget should currently render its hide placeholder (because a modal/sheet is covering its rect AND autoHideOnModal is true).
no setter
mounted bool
Whether this State object is currently in a tree.
no setterinherited
platformViewChannel MethodChannel?
Override to expose the per-instance MethodChannel for the underlying PlatformView so the mixin can call setInteractive on it when a modal opens/closes. Return null if no channel exists yet — the mixin then skips the native call (no harm; the AbsorbPointer wrap still runs as a no-op).
no setter
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
widget → T
The current configuration.
no setterinherited

Methods

activate() → void
Called when this object is reinserted into the tree after having been removed via deactivate.
inherited
build(BuildContext context) Widget
Describes the part of the user interface represented by this widget.
inherited
deactivate() → void
Called when this object is removed from the tree.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
didChangeDependencies() → void
Called when a dependency of this State object changes.
inherited
didUpdateWidget(covariant T oldWidget) → void
Called whenever the widget configuration changes.
inherited
dispose() → void
Called when this object is removed from the tree permanently.
override
initState() → void
Called when this object is inserted into the tree.
override
maybeHiddenPlaceholder({double? height, double? width}) Widget?
Returns a same-sized SizedBox placeholder when isHiddenForModal is true, else null. Use as an early return at the top of build() so the live UiKitView/AppKitView is never constructed while a modal is up — that's what removes the PlatformView from the iOS shared container and fixes the bleed.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
reassemble() → void
Called whenever the application is reassembled during debugging, for example during hot reload.
inherited
setState(VoidCallback fn) → void
Notify the framework that the internal state of this object has changed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) String
A string representation of this object.
inherited
toStringShort() String
A brief description of this object, usually just the runtimeType and the hashCode.
inherited
wrapWithModalInteractionGuard(Widget liveChild) Widget
Wraps liveChild in a Stack with a transparent opaque Listener on top while any modal is above the host route. The Listener actively CLAIMS pointer events via Flutter's gesture arena, which is the only reliable Dart-side way to keep a tap from being forwarded to the native iOS PlatformView's gesture recognizers.

Operators

operator ==(Object other) bool
The equality operator.
inherited