restingRect static method
- required GlassSheetState state,
- required SheetGeometry geometry,
- required Size screenSize,
- required double horizontalMargin,
- required double bottomMargin,
- required double bottomInset,
- required double bottomRadius,
- double? peekHorizontalMargin,
- double? peekBottomMargin,
- double? peekWidth,
- GlassSheetPlacement? stripPlacement,
- bool regularWidth = false,
- TextDirection textDirection = TextDirection.ltr,
The frame the sheet comes to rest in for state, in global coordinates.
Mirrors the resting output of the sheet's own per-frame metrics (see
_calculateMetrics in glass_modal_sheet_state.dart) for the case that
matters here: no drag in flight, no frozen pivot, no interaction pulse.
The vertical position comes from SheetGeometry.positionForState rather
than a re-derivation, so the droplet and the sheet cannot disagree about
where the sheet is.
The sheet's top edge is always (1 - pos) * screenSize.height; only the
horizontal inset and the bottom overhang differ per detent:
• GlassSheetState.full — edge to edge, sunk past the bottom by
bottomInset + bottomRadius so its lower corners leave the screen.
• GlassSheetState.half — inset by horizontalMargin / bottomMargin.
• GlassSheetState.peek — inset by the peek* overrides, falling back
to the base margins; peekWidth centres a fixed-width floor.
• GlassSheetState.hidden — collapses to a zero-height line at the
bottom edge; never a morph destination, but kept total for callers.
stripPlacement is the sheet's placement in iPhone Duo's vertical bar
strip layout, and null elsewhere. There the large detent keeps its
margins, and in a regularWidth every detent is a card placed as the
sheet places itself.
Implementation
static Rect restingRect({
required GlassSheetState state,
required SheetGeometry geometry,
required Size screenSize,
required double horizontalMargin,
required double bottomMargin,
required double bottomInset,
required double bottomRadius,
double? peekHorizontalMargin,
double? peekBottomMargin,
double? peekWidth,
GlassSheetPlacement? stripPlacement,
bool regularWidth = false,
TextDirection textDirection = TextDirection.ltr,
}) {
final screenHeight = screenSize.height;
final screenWidth = screenSize.width;
final pos = geometry.positionForState(state, screenHeight);
// Every detent parks its top edge at the same place: the visual height is
// measured down from the top, so `bottom`/`height` only redistribute the
// remainder below it.
final top = (1.0 - pos) * screenHeight;
late final double hPad;
late final double bottom;
switch (state) {
case GlassSheetState.full:
// Expanded: margins are gone and the sheet sinks by `extraHeight` so
// its bottom corners run off screen instead of floating.
hPad = stripPlacement == null ? 0.0 : horizontalMargin;
bottom = -(bottomInset + bottomRadius);
break;
case GlassSheetState.peek:
hPad = _peekHorizontalPad(
screenWidth: screenWidth,
horizontalMargin: horizontalMargin,
peekHorizontalMargin: peekHorizontalMargin,
peekWidth: peekWidth,
);
bottom = peekBottomMargin ?? bottomMargin;
break;
case GlassSheetState.half:
case GlassSheetState.hidden:
hPad = horizontalMargin;
bottom = bottomMargin;
break;
}
// A sheet narrower than its own margins (tiny test surfaces, extreme
// margins) would invert the rect; clamp so the frame stays well-formed.
final safeHPad = hPad.clamp(0.0, screenWidth / 2.0);
final insets = stripPlacement == null
? EdgeInsets.symmetric(horizontal: safeHPad)
: _stripSheetInsets(
screenSize: screenSize,
regularWidth: regularWidth,
margin: safeHPad,
placement: stripPlacement,
textDirection: textDirection,
);
return Rect.fromLTRB(
insets.left,
top,
screenWidth - insets.right,
math.max(top, screenHeight - bottom),
);
}