showMorphRoute<T> function
- BuildContext context, {
- Object? from,
- required MorphContentBuilder builder,
- MorphTargetSpec? target,
- MorphMotion? motion,
- bool barrierDismissible = true,
- double? maxScrimOpacity,
- Color? scrimColor,
- Color? shadowColor,
- String? semanticLabel,
A real Navigator route whose visual transition is a morph flight.
The route is pushed IMMEDIATELY, so the Navigator owns the truth from the first frame: back button, predictive back, deep links and further pushes all behave normally. The flight plays in the overlay while the route page stays empty; once the open spring settles, the second latch fires - ownership of the target content transfers from the shuttle to the route page. Both sides rebuild in the same frame and the content subtree carries a shared GlobalKey, so it reparents with its live state (scroll positions, text fields, counters survive). A pop hands the content back to the shuttle the same way and plays the ordinary close flight; a close launched from the flight side (a button calling flight.close) retires the route automatically.
The scrim swaps between the two owners at full opacity on both
latches, so the handovers are invisible.
from may be omitted when called inside the source tag's subtree,
mirroring showMorph.
The route pushes into the NEAREST enclosing navigator: a page
belongs to the navigator that owns its context, so a morph route
launched inside a nested navigator (a tab, an embedded flow) stays
there. Pass useRootNavigator to push above everything instead.
Implementation
Future<T?> showMorphRoute<T>(
BuildContext context, {
Object? from,
required MorphContentBuilder builder,
MorphTargetSpec? target,
MorphMotion? motion,
bool barrierDismissible = true,
bool useRootNavigator = false,
double? maxScrimOpacity,
Color? scrimColor,
Color? shadowColor,
String? semanticLabel,
}) {
final MorphTheme? theme = MorphTheme.maybeOf(context);
return Navigator.of(context, rootNavigator: useRootNavigator).push(
MorphPageRoute<T>(
from: from ?? MorphTag.idOf(context),
builder: builder,
target: target ?? MorphTargetSpec.dialog(),
motion: motion ?? theme?.motion,
barrierDismissible: barrierDismissible,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
maxScrimOpacity: maxScrimOpacity ?? theme?.maxScrimOpacity ?? 0.45,
scrimColor: scrimColor ?? theme?.scrimColor ?? Colors.black,
shadowColor: shadowColor ?? theme?.shadowColor ?? const Color(0x99000000),
semanticLabel: semanticLabel,
),
);
}