Improve CupertinoPopupSurface appearance (#151430)
This PR makes the CupertinoPopupSurface more vibrant. Also, the gaussian kernel was switched to 30 from 20 based on comparisons. @dkwingsmt - Looking forward to your dialog and fixes! After is on bottom: <img width="939" alt="image" src="https://github.com/flutter/flutter/assets/59215665/bd020c9b-af87-4342-9a9f-c9f8f7693456"> Notably, because the borders are very transparent, the new version looks more colorful in the sample screencap than it actually is. As such, focus on the individual colors to get a feel for the change. | actual | old | new |--|--|--| | <img width="30" alt="image" src="https://github.com/flutter/flutter/assets/59215665/7de2801d-a2cc-44a4-a660-2692889fed63"> | <img width="28" alt="image" src="https://github.com/flutter/flutter/assets/59215665/48689d82-af15-4612-b4ab-75d584e9b094"> | <img width="30" alt="image" src="https://github.com/flutter/flutter/assets/59215665/7c1075ec-b815-47e0-b822-65a2b63497a0"> | | <img width="24" alt="image" src="https://github.com/flutter/flutter/assets/59215665/2eeefe25-2e1d-4a79-b748-4925d950b9a2"> | <img width="26" alt="image" src="https://github.com/flutter/flutter/assets/59215665/68a2694c-d943-4563-9b5e-9e86e2ee1d58"> | <img width="28" alt="image" src="https://github.com/flutter/flutter/assets/59215665/1932b90a-1719-40f5-828e-41ceafd59e26"> | <img width="22" alt="image" src="https://github.com/flutter/flutter/assets/59215665/0bd22c64-dd37-4262-a7e8-ed610151ab7a"> | <img width="28" alt="image" src="https://github.com/flutter/flutter/assets/59215665/e1738bd2-98d2-491b-9a4a-d2c7cbc5a080"> | <img width="25" alt="image" src="https://github.com/flutter/flutter/assets/59215665/c245d786-19aa-4a14-8df3-029591d1debd"> | Partially addresses https://github.com/flutter/flutter/issues/29483 This will need tests, which I will add once I know which tests break due to this commit. Blockers: * https://github.com/flutter/flutter/issues/152026
This commit is contained in:
parent
c56ab6b947
commit
35b0349294
@ -79,7 +79,6 @@ const TextStyle _kActionSheetContentStyle = TextStyle(
|
||||
);
|
||||
|
||||
// Generic constants shared between Dialog and ActionSheet.
|
||||
const double _kBlurAmount = 20.0;
|
||||
const double _kCornerRadius = 14.0;
|
||||
const double _kDividerThickness = 0.3;
|
||||
|
||||
@ -492,20 +491,34 @@ class _CupertinoAlertDialogState extends State<CupertinoAlertDialog> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Rounded rectangle surface that looks like an iOS popup surface, e.g., alert dialog
|
||||
/// and action sheet.
|
||||
/// An iOS-style component for creating modal overlays like dialogs and action
|
||||
/// sheets.
|
||||
///
|
||||
/// A [CupertinoPopupSurface] can be configured to paint or not paint a white
|
||||
/// color on top of its blurred area. Typical usage should paint white on top
|
||||
/// of the blur. However, the white paint can be disabled for the purpose of
|
||||
/// rendering divider gaps for a more complicated layout, e.g., [CupertinoAlertDialog].
|
||||
/// Additionally, the white paint can be disabled to render a blurred rounded
|
||||
/// rectangle without any color (similar to iOS's volume control popup).
|
||||
/// By default, [CupertinoPopupSurface] generates a rounded rectangle surface
|
||||
/// that applies two effects to the background content:
|
||||
///
|
||||
/// 1. Background filter: Saturates and then blurs content behind the surface.
|
||||
/// 2. Overlay color: Covers the filtered background with a transparent
|
||||
/// surface color. The color adapts to the CupertinoTheme's brightness:
|
||||
/// light gray when the ambient [CupertinoTheme] brightness is
|
||||
/// [Brightness.light], and dark gray when [Brightness.dark].
|
||||
///
|
||||
/// The blur strength can be changed by setting [blurSigma] to a positive value,
|
||||
/// or removed by setting the [blurSigma] to 0.
|
||||
///
|
||||
/// The saturation effect can be removed for debugging by setting
|
||||
/// [debugIsVibrancePainted] to false. The saturation effect is not supported on
|
||||
/// web with the skwasm renderer and will not be applied regardless of the value
|
||||
/// of [debugIsVibrancePainted].
|
||||
///
|
||||
/// The surface color can be disabled by setting [isSurfacePainted] to false,
|
||||
/// which is useful for more complicated layouts, such as rendering divider gaps
|
||||
/// in [CupertinoAlertDialog] or rendering custom surface colors.
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This sample shows how to use a [CupertinoPopupSurface]. The [CupertinoPopupSurface]
|
||||
/// shows a model popup from the bottom of the screen.
|
||||
/// Toggling the switch to configure its surface color.
|
||||
/// shows a modal popup from the bottom of the screen.
|
||||
/// Toggle the switch to configure its surface color.
|
||||
///
|
||||
/// ** See code in examples/api/lib/cupertino/dialog/cupertino_popup_surface.0.dart **
|
||||
/// {@end-tool}
|
||||
@ -519,9 +532,29 @@ class CupertinoPopupSurface extends StatelessWidget {
|
||||
/// Creates an iOS-style rounded rectangle popup surface.
|
||||
const CupertinoPopupSurface({
|
||||
super.key,
|
||||
this.blurSigma = defaultBlurSigma,
|
||||
this.isSurfacePainted = true,
|
||||
this.child,
|
||||
});
|
||||
this.debugIsVibrancePainted = true,
|
||||
required this.child,
|
||||
}) : assert(blurSigma >= 0, 'CupertinoPopupSurface requires a non-negative blur sigma.');
|
||||
|
||||
/// The strength of the gaussian blur applied to the area beneath this
|
||||
/// surface.
|
||||
///
|
||||
/// Defaults to [defaultBlurSigma]. Setting [blurSigma] to 0 will remove the
|
||||
/// blur filter.
|
||||
final double blurSigma;
|
||||
|
||||
/// Whether or not the area beneath this surface should be saturated with a
|
||||
/// [ColorFilter].
|
||||
///
|
||||
/// The appearance of the [ColorFilter] is determined by the [Brightness]
|
||||
/// value obtained from the ambient [CupertinoTheme].
|
||||
///
|
||||
/// The vibrance is always painted if asserts are disabled.
|
||||
///
|
||||
/// Defaults to true.
|
||||
final bool debugIsVibrancePainted;
|
||||
|
||||
/// Whether or not to paint a translucent white on top of this surface's
|
||||
/// blurred background. [isSurfacePainted] should be true for a typical popup
|
||||
@ -531,26 +564,148 @@ class CupertinoPopupSurface extends StatelessWidget {
|
||||
/// Some popups, like iOS's volume control popup, choose to render a blurred
|
||||
/// area without any white paint covering it. To achieve this effect,
|
||||
/// [isSurfacePainted] should be set to false.
|
||||
///
|
||||
/// Defaults to true.
|
||||
final bool isSurfacePainted;
|
||||
|
||||
/// The widget below this widget in the tree.
|
||||
final Widget? child;
|
||||
// Because [CupertinoPopupSurface] is composed of proxy boxes, which mimic
|
||||
// the size of their child, a [child] is required to ensure that this surface
|
||||
// has a size.
|
||||
final Widget child;
|
||||
|
||||
/// The default strength of the blur applied to widgets underlying a
|
||||
/// [CupertinoPopupSurface].
|
||||
///
|
||||
/// Eyeballed from the iOS 17 simulator.
|
||||
static const double defaultBlurSigma = 30.0;
|
||||
|
||||
/// The default corner radius of a [CupertinoPopupSurface].
|
||||
static const BorderRadius _clipper = BorderRadius.all(Radius.circular(14));
|
||||
|
||||
// The [ColorFilter] matrix used to saturate widgets underlying a
|
||||
// [CupertinoPopupSurface] when the ambient [CupertinoThemeData.brightness] is
|
||||
// [Brightness.light].
|
||||
//
|
||||
// To derive this matrix, the saturation matrix was taken from
|
||||
// https://docs.rainmeter.net/tips/colormatrix-guide/ and was tweaked to
|
||||
// resemble the iOS 17 simulator.
|
||||
//
|
||||
// The matrix can be derived from the following function:
|
||||
// static List<double> get _lightSaturationMatrix {
|
||||
// const double lightLumR = 0.26;
|
||||
// const double lightLumG = 0.4;
|
||||
// const double lightLumB = 0.17;
|
||||
// const double saturation = 2.0;
|
||||
// const double sr = (1 - saturation) * lightLumR;
|
||||
// const double sg = (1 - saturation) * lightLumG;
|
||||
// const double sb = (1 - saturation) * lightLumB;
|
||||
// return <double>[
|
||||
// sr + saturation, sg, sb, 0.0, 0.0,
|
||||
// sr, sg + saturation, sb, 0.0, 0.0,
|
||||
// sr, sg, sb + saturation, 0.0, 0.0,
|
||||
// 0.0, 0.0, 0.0, 1.0, 0.0,
|
||||
// ];
|
||||
// }
|
||||
static const List<double> _lightSaturationMatrix = <double>[
|
||||
1.74, -0.40, -0.17, 0.00, 0.00,
|
||||
-0.26, 1.60, -0.17, 0.00, 0.00,
|
||||
-0.26, -0.40, 1.83, 0.00, 0.00,
|
||||
0.00, 0.00, 0.00, 1.00, 0.00
|
||||
];
|
||||
|
||||
// The [ColorFilter] matrix used to saturate widgets underlying a
|
||||
// [CupertinoPopupSurface] when the ambient [CupertinoThemeData.brightness] is
|
||||
// [Brightness.dark].
|
||||
//
|
||||
// To derive this matrix, the saturation matrix was taken from
|
||||
// https://docs.rainmeter.net/tips/colormatrix-guide/ and was tweaked to
|
||||
// resemble the iOS 17 simulator.
|
||||
//
|
||||
// The matrix can be derived from the following function:
|
||||
// static List<double> get _darkSaturationMatrix {
|
||||
// const double additive = 0.3;
|
||||
// const double darkLumR = 0.45;
|
||||
// const double darkLumG = 0.8;
|
||||
// const double darkLumB = 0.16;
|
||||
// const double saturation = 1.7;
|
||||
// const double sr = (1 - saturation) * darkLumR;
|
||||
// const double sg = (1 - saturation) * darkLumG;
|
||||
// const double sb = (1 - saturation) * darkLumB;
|
||||
// return <double>[
|
||||
// sr + saturation, sg, sb, 0.0, additive,
|
||||
// sr, sg + saturation, sb, 0.0, additive,
|
||||
// sr, sg, sb + saturation, 0.0, additive,
|
||||
// 0.0, 0.0, 0.0, 1.0, 0.0,
|
||||
// ];
|
||||
// }
|
||||
static const List<double> _darkSaturationMatrix = <double>[
|
||||
1.39, -0.56, -0.11, 0.00, 0.30,
|
||||
-0.32, 1.14, -0.11, 0.00, 0.30,
|
||||
-0.32, -0.56, 1.59, 0.00, 0.30,
|
||||
0.00, 0.00, 0.00, 1.00, 0.00
|
||||
];
|
||||
|
||||
ImageFilter? _buildFilter(Brightness? brightness) {
|
||||
bool isVibrancePainted = true;
|
||||
assert(() {
|
||||
isVibrancePainted = debugIsVibrancePainted;
|
||||
return true;
|
||||
}());
|
||||
if ((kIsWeb && !isSkiaWeb) || !isVibrancePainted) {
|
||||
if (blurSigma == 0) {
|
||||
return null;
|
||||
}
|
||||
return ImageFilter.blur(
|
||||
sigmaX: blurSigma,
|
||||
sigmaY: blurSigma,
|
||||
);
|
||||
}
|
||||
|
||||
final ColorFilter colorFilter = switch (brightness) {
|
||||
Brightness.dark => const ColorFilter.matrix(_darkSaturationMatrix),
|
||||
Brightness.light || null => const ColorFilter.matrix(_lightSaturationMatrix)
|
||||
};
|
||||
|
||||
if (blurSigma == 0) {
|
||||
return colorFilter;
|
||||
}
|
||||
|
||||
return ImageFilter.compose(
|
||||
inner: colorFilter,
|
||||
outer: ImageFilter.blur(
|
||||
sigmaX: blurSigma,
|
||||
sigmaY: blurSigma,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget? contents = child;
|
||||
final ImageFilter? filter = _buildFilter(CupertinoTheme.maybeBrightnessOf(context));
|
||||
Widget contents = child;
|
||||
|
||||
if (isSurfacePainted) {
|
||||
contents = ColoredBox(
|
||||
color: CupertinoDynamicColor.resolve(_kDialogColor, context),
|
||||
child: contents,
|
||||
);
|
||||
}
|
||||
|
||||
if (filter != null) {
|
||||
return ClipRRect(
|
||||
borderRadius: _clipper,
|
||||
child: BackdropFilter(
|
||||
blendMode: BlendMode.src,
|
||||
filter: filter,
|
||||
child: contents,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(_kCornerRadius)),
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: _kBlurAmount, sigmaY: _kBlurAmount),
|
||||
child: contents,
|
||||
),
|
||||
borderRadius: _clipper,
|
||||
child: contents,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1125,7 +1280,10 @@ class _CupertinoActionSheetState extends State<CupertinoActionSheet> {
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12.0)),
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: _kBlurAmount, sigmaY: _kBlurAmount),
|
||||
filter: ImageFilter.blur(
|
||||
sigmaX: CupertinoPopupSurface.defaultBlurSigma,
|
||||
sigmaY: CupertinoPopupSurface.defaultBlurSigma,
|
||||
),
|
||||
child: _ActionSheetMainSheet(
|
||||
pressedIndex: _pressedIndex,
|
||||
onPressedUpdate: _onPressedUpdate,
|
||||
|
347
packages/flutter/test/cupertino/popup_surface_test.dart
Normal file
347
packages/flutter/test/cupertino/popup_surface_test.dart
Normal file
@ -0,0 +1,347 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// This file is run as part of a reduced test set in CI on Mac and Windows
|
||||
// machines.
|
||||
@Tags(<String>['reduced-test-set'])
|
||||
library;
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
class _FilterTest extends StatelessWidget {
|
||||
const _FilterTest(Widget child, {this.brightness = Brightness.light})
|
||||
: _child = child;
|
||||
final Brightness brightness;
|
||||
final Widget _child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
final double tileHeight = size.height / 4;
|
||||
final double tileWidth = size.width / 8;
|
||||
return CupertinoApp(
|
||||
home: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: <Widget>[
|
||||
// 512 color tiles
|
||||
// 4 alpha levels (0.416, 0.25, 0.5, 0.75)
|
||||
for (int a = 0; a < 4; a++)
|
||||
for (int h = 0; h < 8; h++) // 8 hues
|
||||
for (int s = 0; s < 4; s++) // 4 saturation levels
|
||||
for (int b = 0; b < 4; b++) // 4 brightness levels
|
||||
Positioned(
|
||||
left: h * tileWidth + b * tileWidth / 4,
|
||||
top: a * tileHeight + s * tileHeight / 4,
|
||||
height: tileHeight,
|
||||
width: tileWidth,
|
||||
child: ColoredBox(
|
||||
color: HSVColor.fromAHSV(
|
||||
0.5 + a / 8,
|
||||
h * 45,
|
||||
0.5 + s / 8,
|
||||
0.5 + b / 8,
|
||||
).toColor(),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: CupertinoTheme(
|
||||
data: CupertinoThemeData(brightness: brightness),
|
||||
child: _child,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Golden displays the color filter effect of the CupertinoPopupSurface
|
||||
// when the ambient brightness is light.
|
||||
testWidgets('Brightness.light color filter', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
blurSigma: 0,
|
||||
isSurfacePainted: false,
|
||||
child: SizedBox(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
matchesGoldenFile('cupertinoPopupSurface.color-filter.light.png'),
|
||||
);
|
||||
},
|
||||
skip: kIsWasm, // https://github.com/flutter/flutter/issues/152026
|
||||
);
|
||||
|
||||
// Golden displays the color filter effect of the CupertinoPopupSurface
|
||||
// when the ambient brightness is dark.
|
||||
testWidgets('Brightness.dark color filter', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
blurSigma: 0,
|
||||
isSurfacePainted: false,
|
||||
child: SizedBox(),
|
||||
),
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
matchesGoldenFile('cupertinoPopupSurface.color-filter.dark.png'),
|
||||
);
|
||||
},
|
||||
skip: kIsWasm, // https://github.com/flutter/flutter/issues/152026
|
||||
);
|
||||
|
||||
// Golden displays color tiles without CupertinoPopupSurface being
|
||||
// displayed.
|
||||
testWidgets('Setting debugIsVibrancePainted to false removes the color filter', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
blurSigma: 0,
|
||||
isSurfacePainted: false,
|
||||
debugIsVibrancePainted: false,
|
||||
child: SizedBox(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// The BackdropFilter widget should not be mounted when blurSigma is 0 and
|
||||
// CupertinoPopupSurface.debugIsVibrancePainted is false.
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(CupertinoPopupSurface),
|
||||
matching: find.byType(BackdropFilter),
|
||||
),
|
||||
findsNothing,
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
matchesGoldenFile('cupertinoPopupSurface.color-filter.removed.png'),
|
||||
);
|
||||
});
|
||||
|
||||
// Golden displays the surface color of the CupertinoPopupSurface
|
||||
// in light mode.
|
||||
testWidgets('Brightness.light surface color', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
blurSigma: 0,
|
||||
debugIsVibrancePainted: false,
|
||||
child: SizedBox(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
matchesGoldenFile('cupertinoPopupSurface.surface-color.light.png'),
|
||||
);
|
||||
});
|
||||
|
||||
// Golden displays the surface color of the CupertinoPopupSurface
|
||||
// in dark mode.
|
||||
testWidgets('Brightness.dark surface color', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
blurSigma: 0,
|
||||
debugIsVibrancePainted: false,
|
||||
child: SizedBox(),
|
||||
),
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
matchesGoldenFile('cupertinoPopupSurface.surface-color.dark.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// Golden displays a CupertinoPopupSurface with the color removed. The result
|
||||
// should only display color tiles.
|
||||
testWidgets('Setting isSurfacePainted to false removes the surface color', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
blurSigma: 0,
|
||||
isSurfacePainted: false,
|
||||
debugIsVibrancePainted: false,
|
||||
child: SizedBox(),
|
||||
),
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
matchesGoldenFile('cupertinoPopupSurface.surface-color.removed.png'),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// Goldens display a CupertinoPopupSurface with no vibrance or surface
|
||||
// color, with blur sigmas of 5 and 30 (default).
|
||||
testWidgets('Positive blurSigma applies blur', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
isSurfacePainted: false,
|
||||
debugIsVibrancePainted: false,
|
||||
blurSigma: 5,
|
||||
child: SizedBox(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
matchesGoldenFile('cupertinoPopupSurface.blur.5.png'),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
isSurfacePainted: false,
|
||||
debugIsVibrancePainted: false,
|
||||
child: SizedBox(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
// 30 is the default blur sigma
|
||||
matchesGoldenFile('cupertinoPopupSurface.blur.30.png'),
|
||||
);
|
||||
},
|
||||
skip: kIsWasm, // https://github.com/flutter/flutter/issues/152026
|
||||
);
|
||||
|
||||
// Golden displays a CupertinoPopupSurface with a blur sigma of 0. Because
|
||||
// the blur sigma is 0 and vibrance and surface are not painted, no popup
|
||||
// surface is displayed.
|
||||
testWidgets('Setting blurSigma to zero removes blur', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
isSurfacePainted: false,
|
||||
debugIsVibrancePainted: false,
|
||||
blurSigma: 0,
|
||||
child: SizedBox(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// The BackdropFilter widget should not be mounted when blurSigma is 0 and
|
||||
// CupertinoPopupSurface.isVibrancePainted is false.
|
||||
expect(
|
||||
find.descendant(
|
||||
of: find.byType(CupertinoPopupSurface),
|
||||
matching: find.byType(BackdropFilter),
|
||||
),
|
||||
findsNothing,
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
matchesGoldenFile('cupertinoPopupSurface.blur.0.png'),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
isSurfacePainted: false,
|
||||
debugIsVibrancePainted: false,
|
||||
blurSigma: 0,
|
||||
child: SizedBox(),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('Setting a blurSigma to a negative number throws', (WidgetTester tester) async {
|
||||
try {
|
||||
await tester.pumpWidget(
|
||||
_FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
isSurfacePainted: false,
|
||||
debugIsVibrancePainted: false,
|
||||
blurSigma: -1,
|
||||
child: const SizedBox(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
fail('CupertinoPopupSurface did not throw when provided a negative blur sigma.');
|
||||
} on AssertionError catch (error) {
|
||||
expect(
|
||||
error.toString(),
|
||||
contains('CupertinoPopupSurface requires a non-negative blur sigma.'),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Golden displays a CupertinoPopupSurface with all enabled features.
|
||||
//
|
||||
// CupertinoPopupSurface uses ImageFilter.compose, which applies an inner
|
||||
// filter first, followed by an outer filter (e.g. result =
|
||||
// outer(inner(source))).
|
||||
//
|
||||
// For CupertinoPopupSurface, this means that the pixels underlying the
|
||||
// surface are first saturated with a ColorFilter, and the resulting saturated
|
||||
// pixels are blurred with an ImageFilter.blur. This test verifies that this
|
||||
// order does not change.
|
||||
testWidgets('Saturation is applied before blur', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
CupertinoPopupSurface(
|
||||
child: SizedBox(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
matchesGoldenFile('cupertinoPopupSurface.composition.png'),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
const _FilterTest(
|
||||
Stack(
|
||||
fit: StackFit.expand,
|
||||
children: <Widget>[
|
||||
CupertinoPopupSurface(
|
||||
isSurfacePainted: false,
|
||||
blurSigma: 0,
|
||||
child: SizedBox(),
|
||||
),
|
||||
CupertinoPopupSurface(
|
||||
debugIsVibrancePainted: false,
|
||||
child: SizedBox(),
|
||||
)
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
find.byType(CupertinoApp),
|
||||
matchesGoldenFile('cupertinoPopupSurface.composition.png'),
|
||||
);
|
||||
});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user