showStreamSheet<T> function
- required BuildContext context,
- required StreamSheetScrollableWidgetBuilder builder,
- Color? backgroundColor,
- Color? barrierColor,
- String? barrierLabel,
- String? barrierOnTapHint,
- ShapeBorder? shape,
- BorderRadiusGeometry? borderRadius,
- BoxConstraints? constraints,
- double? elevation,
- Clip? clipBehavior,
- bool enableDrag = true,
- bool isDismissible = false,
- bool? showDragHandle,
- bool? requestFocus,
- Offset? anchorPoint,
- StreamSheetDragStartCallback? onDragStart,
- StreamSheetDragEndCallback? onDragEnd,
- RouteSettings? settings,
Shows a Stream-styled modal sheet that slides up from the bottom of the screen.
The builder receives a ScrollController that should be attached to
the topmost scrollable inside the sheet so dragging it past its top
edge dismisses the sheet (scroll-aware drag-to-dismiss). Non-
scrollable regions can also be dragged down to dismiss.
When useNestedNavigation is true, the sheet hosts its own
Navigator. Routes pushed from inside the sheet stay within it, and a
pop from the first nested route dismisses the entire sheet. The whole
sheet can also be popped at once via StreamSheetRoute.popSheet.
Pushing a sheet from within another sheet stacks it: the underlying sheet scales down slightly while the new one rests on top, and the auto-implied StreamSheetHeader leading icon flips from cross to back-chevron.
The sheet honours system insets — its top is clamped to a minimum of MediaQueryData.viewPadding top so the header / drag handle clear the status bar, and horizontal insets are honoured for landscape and notched displays. The bottom inset is never applied, so the sheet visually meets the bottom edge of the screen.
Style:
Each visual property follows the same resolution chain — the per-call argument wins, then the ambient StreamSheetThemeData (from StreamTheme.sheetTheme / StreamSheetTheme), then the built-in fallback below.
shapetakes precedence overborderRadiuswhen provided. When both are null, the sheet's top corners are rounded with StreamRadius.xxxxl and the bottom corners are square.backgroundColordefaults to StreamColorScheme.backgroundElevation1.elevationdrives the shadow cast around the sheet. Defaults to1.clipBehaviorclips content against the border radius (defaults to Clip.none).constraintscaps the sheet's size — most useful on tablet / desktop. The sheet is bottom-aligned within the constraints. Defaults toBoxConstraints(maxWidth: 640).
Dismissal:
enableDrag(defaults totrue) lets users pop the sheet by dragging it down. The drag handle stays draggable even whenenableDragisfalse, so the affordance never lies.isDismissible(defaults tofalse) lets users pop the sheet by tapping the modal barrier. Pair with a non-nullbarrierColorto give users a visible target.showDragHandle(defaults totrue) reserves a drag handle at the top of the sheet content.onDragStart/onDragEndfire when the user starts / stops a drag gesture;isClosingononDragEndindicates whether the gesture will pop the sheet.
Routing:
useRootNavigator(defaults tofalse) selects which Navigator the sheet is pushed onto. Passtrueto escape any nested navigators and push to the root.requestFocuscontrols whether the sheet's first focusable descendant requests focus when the route activates.anchorPointis forwarded to a DisplayFeatureSubScreen so the sheet avoids display features like foldable hinges.settingssets the RouteSettings of the underlying PageRoute.
Returns a Future that resolves to the value (if any) passed to Navigator.pop when the sheet is closed.
{@tool snippet}
A simple sheet with a title and a confirm action:
final result = await showStreamSheet<String>(
context: context,
builder: (sheetContext, scrollController) => Column(
mainAxisSize: MainAxisSize.min,
children: [
StreamSheetHeader(
title: const Text('Edit profile'),
trailing: StreamButton.icon(
icon: Icon(context.streamIcons.checkmark),
onPressed: () => Navigator.of(sheetContext).pop('saved'),
),
),
// ... sheet contents
],
),
);
{@end-tool}
See also:
- StreamSheetRoute, the underlying route.
- StreamSheetHeader, the auto-aware header component.
Implementation
Future<T?> showStreamSheet<T>({
required BuildContext context,
required StreamSheetScrollableWidgetBuilder builder,
Color? backgroundColor,
Color? barrierColor,
String? barrierLabel,
String? barrierOnTapHint,
ShapeBorder? shape,
BorderRadiusGeometry? borderRadius,
BoxConstraints? constraints,
double? elevation,
Clip? clipBehavior,
bool enableDrag = true,
bool isDismissible = false,
bool? showDragHandle,
bool useNestedNavigation = false,
bool useRootNavigator = false,
bool? requestFocus,
Offset? anchorPoint,
StreamSheetDragStartCallback? onDragStart,
StreamSheetDragEndCallback? onDragEnd,
RouteSettings? settings,
}) {
assert(debugCheckHasMaterialLocalizations(context));
final localizations = MaterialLocalizations.of(context);
final sheetTheme = StreamSheetTheme.of(context);
final defaults = _StreamSheetDefaults(context);
final effectiveBuilder = useNestedNavigation ? _wrapWithNestedNavigator<T>(builder) : builder;
// The nearest StreamSheetRoute above the current context, if any. We keep
// the reference around so the new sheet can identify itself as a stacked
// sheet (used by the auto-imply leading icon in [StreamSheetHeader] and
// by [StreamSheetRoute.isStacked]).
final parentSheet = _StreamSheetScope.maybeOf(context)?.route;
final navigator = Navigator.of(context, rootNavigator: useRootNavigator);
// Capture the calling context's [InheritedTheme]s (StreamTheme, Theme,
// Directionality, MediaQuery overrides, etc.) and re-apply them inside
// the route. The sheet is pushed onto the navigator's overlay, which
// is typically *outside* any local theme overrides — without this
// wrap, sheets pushed from a sub-tree with a custom theme would render
// with the root theme.
final capturedThemes = InheritedTheme.capture(from: context, to: navigator.context);
return navigator.push<T>(
StreamSheetRoute<T>(
settings: settings,
requestFocus: requestFocus,
builder: effectiveBuilder,
backgroundColor: backgroundColor,
barrierColor: barrierColor ?? sheetTheme.barrierColor ?? defaults.barrierColor,
barrierLabel: barrierLabel ?? localizations.scrimLabel,
barrierOnTapHint: barrierOnTapHint ?? localizations.scrimOnTapHint(localizations.bottomSheetLabel),
shape: shape,
borderRadius: borderRadius,
constraints: constraints,
elevation: elevation,
clipBehavior: clipBehavior,
enableDrag: enableDrag,
isDismissible: isDismissible,
showDragHandle: showDragHandle,
anchorPoint: anchorPoint,
onDragStart: onDragStart,
onDragEnd: onDragEnd,
parentSheet: parentSheet,
capturedThemes: capturedThemes,
),
);
}