restingRect static method

Rect restingRect({
  1. required GlassSheetState state,
  2. required SheetGeometry geometry,
  3. required Size screenSize,
  4. required double horizontalMargin,
  5. required double bottomMargin,
  6. required double bottomInset,
  7. required double bottomRadius,
  8. double? peekHorizontalMargin,
  9. double? peekBottomMargin,
  10. double? peekWidth,
  11. GlassSheetPlacement? stripPlacement,
  12. bool regularWidth = false,
  13. 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),
  );
}