GlassScaffold class

A one-stop-shop scaffold that replaces the manual assembly of GlassPage, Scaffold, GlassScrollEdgeEffect, and a Stack for proper z-ordering.

Why GlassScaffold?

When using glass surfaces (navigation bars, bottom bars, cards), the correct layout requires 4-5 nested widgets with manual padding calculations and scroll controller wiring. GlassScaffold handles all of this internally:

  • Z-ordering: App bar and bottom bar always render above body content, preventing glass cards in the body from overlapping navigation buttons.
  • Edge fading: Content fades smoothly as it approaches the bar areas, matching iOS 26's .scrollEdgeEffectStyle(.soft).
  • Auto padding: Calculates safe-area-aware top/bottom padding so content starts below the app bar and above the bottom bar automatically.
  • Background & glass layer: Wraps everything in GlassPage for the glass rendering context, background, and status bar styling.

Before (manual assembly)

GlassPage(
  background: Image.asset('assets/bg.jpg', fit: BoxFit.cover),
  settings: RecommendedGlassSettings.standard,
  statusBarStyle: GlassStatusBarStyle.light,
  child: Scaffold(
    extendBodyBehindAppBar: true,
    extendBody: true,
    appBar: GlassAppBar(
      title: Text('Messages'),
      scrollController: _ctrl,
      settings: RecommendedGlassSettings.surface,
    ),
    body: GlassScrollEdgeEffect(
      topFadeHeight: MediaQuery.paddingOf(context).top + 44 + 40,
      bottomFadeHeight: 60 + MediaQuery.paddingOf(context).bottom,
      child: CustomScrollView(
        controller: _ctrl,
        slivers: [
          SliverToBoxAdapter(
            child: SizedBox(
              height: MediaQuery.paddingOf(context).top + 44 + 16,
            ),
          ),
          // ... content
        ],
      ),
    ),
  ),
)

After (one widget)

GlassScaffold(
  background: Image.asset('assets/bg.jpg', fit: BoxFit.cover),
  settings: RecommendedGlassSettings.standard,
  statusBarStyle: GlassStatusBarStyle.light,
  appBar: GlassAppBar(
    title: Text('Messages'),
    scrollController: _ctrl,
    settings: RecommendedGlassSettings.surface,
  ),
  body: CustomScrollView(
    controller: _ctrl,
    slivers: [
      // No manual spacer needed — GlassScaffold handles it
      // ... content
    ],
  ),
)

How it works internally

GlassScaffold builds:

GlassPage(
  background: ...,
  child: CupertinoPageScaffold(
    child: Stack(
      children: [
        // 1. Body with edge fading (bottom of stack)
        // 2. Body overlays (between body and bars)
        // 3. App bar (top of stack — always above body)
        // 4. Bottom bar (top of stack — always above body)
      ],
    ),
  ),
)

The app bar and bottom bar are placed AFTER the body in the Stack's children list, guaranteeing they always paint on top regardless of BackdropFilter compositing from glass widgets in the body.

Inheritance
Available extensions

Constructors

GlassScaffold({Key? key, required Widget body, Widget? appBar, Widget? bottomBar, Widget? background, Color? backgroundColor, LiquidGlassSettings? settings, GlassStatusBarStyle statusBarStyle = GlassStatusBarStyle.none, bool edgeToEdge = false, GlassThemeData? themeOverride, bool? enableBackgroundSampling, bool edgeFade = true, bool? topEdgeFade, bool? bottomEdgeFade, bool edgeFadeAbsorbsPointers = false, double topEdgeFadeExtent = 20.0, double bottomEdgeFadeExtent = 20.0, GlassScrollEdgeStyle edgeStyle = GlassScrollEdgeStyle.soft, double maxSigma = 18.0, bool extendBody = true, double appBarHeight = 44.0, double? bottomBarHeight, bool? resizeToAvoidBottomInset, List<Widget>? bodyOverlays, Widget? header, ScrollController? headerScrollController, double headerFadeDistance = 60.0, bool contentAwareBrightness = false})
Creates a glass scaffold with automatic z-ordering, edge fading, and glass layer setup.
const

Properties

appBar → Widget?
An optional app bar placed at the top, always above the body.
final
appBarHeight → double
The preferred height of the app bar, used for padding calculations.
final
background → Widget?
Background widget rendered behind everything. See GlassPage.background.
final
backgroundColor → Color?
A solid background colour rendered behind everything when no background widget is provided.
final
body → Widget
The main content of the scaffold.
final
bodyOverlays → List<Widget>?
Optional overlay widgets placed between the body and the bars in the z-order Stack.
final
bottomBar → Widget?
An optional bottom bar placed at the bottom, always above the body.
final
bottomBarHeight → double?
The height of the bottom bar, used for padding calculations.
final
bottomEdgeFade → bool?
Whether to fade content at the bottom edge. When null, follows edgeFade. Automatically set to true when bottomBar is provided.
final
bottomEdgeFadeExtent → double
Extra fade height beyond the auto-calculated bottom bar area.
final
contentAwareBrightness → bool
Whether to install a GlassContentAwareScope around the scaffold's body and bars.
final
edgeFade → bool
Master toggle for edge fading. Defaults to true.
final
edgeFadeAbsorbsPointers → bool
Whether the edge fades absorb pointer events. Defaults to false.
final
edgeStyle → GlassScrollEdgeStyle
The edge fade style applied at the top and bottom of the scroll body. See GlassScrollEdgeStyle.
final
edgeToEdge → bool
Whether to enable edge-to-edge rendering. See GlassPage.edgeToEdge.
final
enableBackgroundSampling → bool?
Whether to capture the background as a GPU texture for glass colour absorption. See GlassPage.enableBackgroundSampling.
final
extendBody → bool
Whether the body extends behind the app bar and bottom bar.
final
hashCode → int
The hash code for this object.
no setterinherited
A fixed header widget positioned below the status bar that fades out as the user scrolls.
final
headerFadeDistance → double
The scroll distance (in pixels) over which the header fades from fully opaque to fully transparent. Defaults to 60.0.
final
headerScrollController → ScrollController?
The scroll controller that drives the header fade animation.
final
key → Key?
Controls how one widget replaces another widget in the tree.
finalinherited
maxSigma → double
Maximum blur sigma for GlassScrollEdgeStyle.blur.
final
resizeToAvoidBottomInset → bool?
Whether the body should resize when the keyboard appears.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
settings → LiquidGlassSettings?
Glass settings for the page's rendering layer. See GlassPage.settings.
final
statusBarStyle → GlassStatusBarStyle
Status bar icon style. See GlassPage.statusBarStyle.
final
themeOverride → GlassThemeData?
Optional per-page glass theme override. See GlassPage.themeOverride.
final
topEdgeFade → bool?
Whether to fade content at the top edge. When null, follows edgeFade.
final
topEdgeFadeExtent → double
Extra fade height beyond the auto-calculated app bar area.
final

Methods

build(BuildContext context) → Widget
Describes the part of the user interface represented by this widget.
override
createElement() → StatelessElement
Creates a StatelessElement to manage this widget's location in the tree.
inherited
debugDescribeChildren() → List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
glassContextMenu({Key? key, required List<Widget> actions, WidgetBuilder? previewBuilder, bool enabled = true, bool enableHaptics = true, double borderRadius = 32.0, double? previewBorderRadius, double rowBorderRadius = 16.0, BorderRadius? rowCorners, Color? originSlotColor, Color? backgroundColor, LiquidGlassSettings? settings, GlassQuality? quality, double backdropBlur = 0.0, Color? barrierColor, double menuWidth = 250.0, VoidCallback? onOpened, VoidCallback? onDismissed, Duration longPressDuration = const Duration(milliseconds: 700)}) → Widget

Available on Widget, provided by the GlassContextMenuExtension extension

Wraps this widget in a GlassContextMenu displaying actions on long-press or right-click.
glassFullScreenCover({required bool isPresented, VoidCallback? onDismiss, required WidgetBuilder content, bool enableSwipeToDismiss = true, double dismissThreshold = 140.0, LiquidGlassSettings? settings, GlassQuality? quality}) → Widget

Available on Widget, provided by the GlassFullScreenCoverExtension extension

Presents a full-viewport modal cover whenever isPresented is true.

Available on Widget, provided by the GlassNavigationTitleExtension extension

Annotates this widget with a navigation title that drives enclosing or descendant GlassAppBar / GlassAppBar.pinned bars (when their explicit title is null) as well as header accessibility semantics.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
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
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String
Returns a one-line detailed description of the object.
inherited
toStringShort() → String
A short, textual description of this widget.
inherited

Operators

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