@@ -79,6 +79,7 @@ const TextStyle _kActionSheetContentStyle = TextStyle(
7979);
8080
8181// Generic constants shared between Dialog and ActionSheet.
82+ const double _kBlurAmount = 20.0 ;
8283const double _kCornerRadius = 14.0 ;
8384const double _kDividerThickness = 0.3 ;
8485
@@ -491,34 +492,20 @@ class _CupertinoAlertDialogState extends State<CupertinoAlertDialog> {
491492 }
492493}
493494
494- /// An iOS-style component for creating modal overlays like dialogs and action
495- /// sheets .
495+ /// Rounded rectangle surface that looks like an iOS popup surface, e.g., alert dialog
496+ /// and action sheet .
496497///
497- /// By default, [CupertinoPopupSurface] generates a rounded rectangle surface
498- /// that applies two effects to the background content:
499- ///
500- /// 1. Background filter: Saturates and then blurs content behind the surface.
501- /// 2. Overlay color: Covers the filtered background with a transparent
502- /// surface color. The color adapts to the CupertinoTheme's brightness:
503- /// light gray when the ambient [CupertinoTheme] brightness is
504- /// [Brightness.light], and dark gray when [Brightness.dark].
505- ///
506- /// The blur strength can be changed by setting [blurSigma] to a positive value,
507- /// or removed by setting the [blurSigma] to 0.
508- ///
509- /// The saturation effect can be removed for debugging by setting
510- /// [debugIsVibrancePainted] to false. The saturation effect is not supported on
511- /// web with the skwasm renderer and will not be applied regardless of the value
512- /// of [debugIsVibrancePainted] .
513- ///
514- /// The surface color can be disabled by setting [isSurfacePainted] to false,
515- /// which is useful for more complicated layouts, such as rendering divider gaps
516- /// in [CupertinoAlertDialog] or rendering custom surface colors.
498+ /// A [CupertinoPopupSurface] can be configured to paint or not paint a white
499+ /// color on top of its blurred area. Typical usage should paint white on top
500+ /// of the blur. However, the white paint can be disabled for the purpose of
501+ /// rendering divider gaps for a more complicated layout, e.g., [CupertinoAlertDialog] .
502+ /// Additionally, the white paint can be disabled to render a blurred rounded
503+ /// rectangle without any color (similar to iOS's volume control popup).
517504///
518505/// {@tool dartpad}
519506/// This sample shows how to use a [CupertinoPopupSurface] . The [CupertinoPopupSurface]
520- /// shows a modal popup from the bottom of the screen.
521- /// Toggle the switch to configure its surface color.
507+ /// shows a model popup from the bottom of the screen.
508+ /// Toggling the switch to configure its surface color.
522509///
523510/// ** See code in examples/api/lib/cupertino/dialog/cupertino_popup_surface.0.dart **
524511/// {@end-tool}
@@ -532,29 +519,9 @@ class CupertinoPopupSurface extends StatelessWidget {
532519 /// Creates an iOS-style rounded rectangle popup surface.
533520 const CupertinoPopupSurface ({
534521 super .key,
535- this .blurSigma = defaultBlurSigma,
536522 this .isSurfacePainted = true ,
537- this .debugIsVibrancePainted = true ,
538- required this .child,
539- }) : assert (blurSigma >= 0 , 'CupertinoPopupSurface requires a non-negative blur sigma.' );
540-
541- /// The strength of the gaussian blur applied to the area beneath this
542- /// surface.
543- ///
544- /// Defaults to [defaultBlurSigma] . Setting [blurSigma] to 0 will remove the
545- /// blur filter.
546- final double blurSigma;
547-
548- /// Whether or not the area beneath this surface should be saturated with a
549- /// [ColorFilter] .
550- ///
551- /// The appearance of the [ColorFilter] is determined by the [Brightness]
552- /// value obtained from the ambient [CupertinoTheme] .
553- ///
554- /// The vibrance is always painted if asserts are disabled.
555- ///
556- /// Defaults to true.
557- final bool debugIsVibrancePainted;
523+ this .child,
524+ });
558525
559526 /// Whether or not to paint a translucent white on top of this surface's
560527 /// blurred background. [isSurfacePainted] should be true for a typical popup
@@ -564,148 +531,26 @@ class CupertinoPopupSurface extends StatelessWidget {
564531 /// Some popups, like iOS's volume control popup, choose to render a blurred
565532 /// area without any white paint covering it. To achieve this effect,
566533 /// [isSurfacePainted] should be set to false.
567- ///
568- /// Defaults to true.
569534 final bool isSurfacePainted;
570535
571536 /// The widget below this widget in the tree.
572- // Because [CupertinoPopupSurface] is composed of proxy boxes, which mimic
573- // the size of their child, a [child] is required to ensure that this surface
574- // has a size.
575- final Widget child;
576-
577- /// The default strength of the blur applied to widgets underlying a
578- /// [CupertinoPopupSurface] .
579- ///
580- /// Eyeballed from the iOS 17 simulator.
581- static const double defaultBlurSigma = 30.0 ;
582-
583- /// The default corner radius of a [CupertinoPopupSurface] .
584- static const BorderRadius _clipper = BorderRadius .all (Radius .circular (14 ));
585-
586- // The [ColorFilter] matrix used to saturate widgets underlying a
587- // [CupertinoPopupSurface] when the ambient [CupertinoThemeData.brightness] is
588- // [Brightness.light].
589- //
590- // To derive this matrix, the saturation matrix was taken from
591- // https://docs.rainmeter.net/tips/colormatrix-guide/ and was tweaked to
592- // resemble the iOS 17 simulator.
593- //
594- // The matrix can be derived from the following function:
595- // static List<double> get _lightSaturationMatrix {
596- // const double lightLumR = 0.26;
597- // const double lightLumG = 0.4;
598- // const double lightLumB = 0.17;
599- // const double saturation = 2.0;
600- // const double sr = (1 - saturation) * lightLumR;
601- // const double sg = (1 - saturation) * lightLumG;
602- // const double sb = (1 - saturation) * lightLumB;
603- // return <double>[
604- // sr + saturation, sg, sb, 0.0, 0.0,
605- // sr, sg + saturation, sb, 0.0, 0.0,
606- // sr, sg, sb + saturation, 0.0, 0.0,
607- // 0.0, 0.0, 0.0, 1.0, 0.0,
608- // ];
609- // }
610- static const List <double > _lightSaturationMatrix = < double > [
611- 1.74 , - 0.40 , - 0.17 , 0.00 , 0.00 ,
612- - 0.26 , 1.60 , - 0.17 , 0.00 , 0.00 ,
613- - 0.26 , - 0.40 , 1.83 , 0.00 , 0.00 ,
614- 0.00 , 0.00 , 0.00 , 1.00 , 0.00
615- ];
616-
617- // The [ColorFilter] matrix used to saturate widgets underlying a
618- // [CupertinoPopupSurface] when the ambient [CupertinoThemeData.brightness] is
619- // [Brightness.dark].
620- //
621- // To derive this matrix, the saturation matrix was taken from
622- // https://docs.rainmeter.net/tips/colormatrix-guide/ and was tweaked to
623- // resemble the iOS 17 simulator.
624- //
625- // The matrix can be derived from the following function:
626- // static List<double> get _darkSaturationMatrix {
627- // const double additive = 0.3;
628- // const double darkLumR = 0.45;
629- // const double darkLumG = 0.8;
630- // const double darkLumB = 0.16;
631- // const double saturation = 1.7;
632- // const double sr = (1 - saturation) * darkLumR;
633- // const double sg = (1 - saturation) * darkLumG;
634- // const double sb = (1 - saturation) * darkLumB;
635- // return <double>[
636- // sr + saturation, sg, sb, 0.0, additive,
637- // sr, sg + saturation, sb, 0.0, additive,
638- // sr, sg, sb + saturation, 0.0, additive,
639- // 0.0, 0.0, 0.0, 1.0, 0.0,
640- // ];
641- // }
642- static const List <double > _darkSaturationMatrix = < double > [
643- 1.39 , - 0.56 , - 0.11 , 0.00 , 0.30 ,
644- - 0.32 , 1.14 , - 0.11 , 0.00 , 0.30 ,
645- - 0.32 , - 0.56 , 1.59 , 0.00 , 0.30 ,
646- 0.00 , 0.00 , 0.00 , 1.00 , 0.00
647- ];
648-
649- ImageFilter ? _buildFilter (Brightness ? brightness) {
650- bool isVibrancePainted = true ;
651- assert (() {
652- isVibrancePainted = debugIsVibrancePainted;
653- return true ;
654- }());
655- if ((kIsWeb && ! isSkiaWeb) || ! isVibrancePainted) {
656- if (blurSigma == 0 ) {
657- return null ;
658- }
659- return ImageFilter .blur (
660- sigmaX: blurSigma,
661- sigmaY: blurSigma,
662- );
663- }
664-
665- final ColorFilter colorFilter = switch (brightness) {
666- Brightness .dark => const ColorFilter .matrix (_darkSaturationMatrix),
667- Brightness .light || null => const ColorFilter .matrix (_lightSaturationMatrix)
668- };
669-
670- if (blurSigma == 0 ) {
671- return colorFilter;
672- }
673-
674- return ImageFilter .compose (
675- inner: colorFilter,
676- outer: ImageFilter .blur (
677- sigmaX: blurSigma,
678- sigmaY: blurSigma,
679- ),
680- );
681- }
537+ final Widget ? child;
682538
683539 @override
684540 Widget build (BuildContext context) {
685- final ImageFilter ? filter = _buildFilter (CupertinoTheme .maybeBrightnessOf (context));
686- Widget contents = child;
687-
541+ Widget ? contents = child;
688542 if (isSurfacePainted) {
689543 contents = ColoredBox (
690544 color: CupertinoDynamicColor .resolve (_kDialogColor, context),
691545 child: contents,
692546 );
693547 }
694-
695- if (filter != null ) {
696- return ClipRRect (
697- borderRadius: _clipper,
698- child: BackdropFilter (
699- blendMode: BlendMode .src,
700- filter: filter,
701- child: contents,
702- ),
703- );
704- }
705-
706548 return ClipRRect (
707- borderRadius: _clipper,
708- child: contents,
549+ borderRadius: const BorderRadius .all (Radius .circular (_kCornerRadius)),
550+ child: BackdropFilter (
551+ filter: ImageFilter .blur (sigmaX: _kBlurAmount, sigmaY: _kBlurAmount),
552+ child: contents,
553+ ),
709554 );
710555 }
711556}
@@ -1280,10 +1125,7 @@ class _CupertinoActionSheetState extends State<CupertinoActionSheet> {
12801125 child: ClipRRect (
12811126 borderRadius: const BorderRadius .all (Radius .circular (12.0 )),
12821127 child: BackdropFilter (
1283- filter: ImageFilter .blur (
1284- sigmaX: CupertinoPopupSurface .defaultBlurSigma,
1285- sigmaY: CupertinoPopupSurface .defaultBlurSigma,
1286- ),
1128+ filter: ImageFilter .blur (sigmaX: _kBlurAmount, sigmaY: _kBlurAmount),
12871129 child: _ActionSheetMainSheet (
12881130 pressedIndex: _pressedIndex,
12891131 onPressedUpdate: _onPressedUpdate,
0 commit comments