delegateTransition static method

Widget delegateTransition(
  1. BuildContext context,
  2. Animation<double> animation,
  3. Animation<double> secondaryAnimation,
  4. bool allowSnapshotting,
  5. Widget? child,
)

The primary delegated transition. Will slide a non CupertinoSheetRoute page down.

Provided to the previous route to coordinate transitions between routes.

If a CupertinoSheetRoute already exists in the stack, then it will slide the previous sheet upwards instead.

Implementation

static Widget delegateTransition(
  BuildContext context,
  Animation<double> animation,
  Animation<double> secondaryAnimation,
  bool allowSnapshotting,
  Widget? child,
) {
  if (CupertinoSheetRoute.hasParentSheet(context)) {
    return _delegatedCoverSheetSecondaryTransition(secondaryAnimation, child);
  }
  final bool linear = Navigator.of(context).userGestureInProgress;

  final Curve curve = linear ? Curves.linear : Curves.linearToEaseOut;
  final Curve reverseCurve = linear ? Curves.linear : Curves.easeInToLinear;
  final CurvedAnimation curvedAnimation = CurvedAnimation(
    curve: curve,
    reverseCurve: reverseCurve,
    parent: secondaryAnimation,
  );

  final double deviceCornerRadius =
      (MediaQuery.maybeViewPaddingOf(context)?.top ?? 0) * _kDeviceCornerRadiusSmoothingFactor;
  final bool roundedDeviceCorners = deviceCornerRadius > _kRoundedDeviceCornersThreshold;

  final Animatable<BorderRadiusGeometry> decorationTween = Tween<BorderRadiusGeometry>(
    begin: BorderRadius.vertical(
      top: Radius.circular(roundedDeviceCorners ? deviceCornerRadius : 0),
    ),
    end: BorderRadius.circular(12),
  );

  final Animation<BorderRadiusGeometry> radiusAnimation = curvedAnimation.drive(decorationTween);
  final Animation<double> opacityAnimation = curvedAnimation.drive(_kOpacityTween);
  final Animation<Offset> slideAnimation = curvedAnimation.drive(_kTopDownTween);
  final Animation<double> scaleAnimation = curvedAnimation.drive(_kScaleTween);
  curvedAnimation.dispose();

  final bool isDarkMode = CupertinoTheme.brightnessOf(context) == Brightness.dark;
  final Color overlayColor = isDarkMode ? const Color(0xFFc8c8c8) : const Color(0xFF000000);

  final Widget? contrastedChild = child != null && !secondaryAnimation.isDismissed
      ? Stack(
          children: <Widget>[
            child,
            FadeTransition(
              opacity: opacityAnimation,
              child: ColoredBox(color: overlayColor, child: const SizedBox.expand()),
            ),
          ],
        )
      : child;

  final double topGapHeight = MediaQuery.sizeOf(context).height * _kTopGapRatio;

  return Stack(
    children: <Widget>[
      AnnotatedRegion<SystemUiOverlayStyle>(
        value: const SystemUiOverlayStyle(
          statusBarBrightness: Brightness.dark,
          statusBarIconBrightness: Brightness.light,
        ),
        child: SizedBox(height: topGapHeight, width: double.infinity),
      ),
      SlideTransition(
        position: slideAnimation,
        child: ScaleTransition(
          scale: scaleAnimation,
          filterQuality: FilterQuality.medium,
          alignment: Alignment.topCenter,
          child: AnimatedBuilder(
            animation: radiusAnimation,
            child: child,
            builder: (BuildContext context, Widget? child) {
              return ClipRSuperellipse(
                borderRadius: !secondaryAnimation.isDismissed
                    ? radiusAnimation.value
                    : BorderRadius.circular(0),
                child: contrastedChild,
              );
            },
          ),
        ),
      ),
    ],
  );
}