Skip to content

Commit 52df034

Browse files
authored
Reland: [CupertinoActionSheet] Match colors to native (#149568) (#150015)
Relands #149568, which was reverted in flutter/flutter#149998 due to unverified golden tests post-commit. (Honestly I don't know what happened but I guess resubmitting should resolve it.) No code is changed. ## Pre-launch Checklist - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ ] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [ ] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [Features we expect every widget to implement]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat [Data Driven Fixes]: https://github.com/flutter/flutter/wiki/Data-driven-Fixes
1 parent fa30ecf commit 52df034

File tree

2 files changed

+128
-21
lines changed

2 files changed

+128
-21
lines changed

packages/flutter/lib/src/cupertino/dialog.dart

+21-21
Original file line numberDiff line numberDiff line change
@@ -104,35 +104,35 @@ const Color _kDialogColor = CupertinoDynamicColor.withBrightness(
104104
// Translucent light gray that is painted on top of the blurred backdrop as the
105105
// background color of a pressed button.
106106
// Eyeballed from iOS 13 beta simulator.
107-
const Color _kPressedColor = CupertinoDynamicColor.withBrightness(
107+
const Color _kDialogPressedColor = CupertinoDynamicColor.withBrightness(
108108
color: Color(0xFFE1E1E1),
109109
darkColor: Color(0xFF2E2E2E),
110110
);
111111

112-
const Color _kActionSheetCancelPressedColor = CupertinoDynamicColor.withBrightness(
113-
color: Color(0xFFECECEC),
114-
darkColor: Color(0xFF49494B),
115-
);
112+
// Translucent light gray that is painted on top of the blurred backdrop as the
113+
// background color of a pressed button.
114+
// Eyeballed from iOS 17 simulator.
115+
const Color _kActionSheetPressedColor = Color(0xCAE0E0E0);
116+
117+
const Color _kActionSheetCancelColor = Color(0xFFFFFFFF);
118+
const Color _kActionSheetCancelPressedColor = Color(0xFFECECEC);
116119

117120
// Translucent, very light gray that is painted on top of the blurred backdrop
118121
// as the action sheet's background color.
119122
// TODO(LongCatIsLooong): https://github.com/flutter/flutter/issues/39272. Use
120123
// System Materials once we have them.
121-
// Extracted from https://developer.apple.com/design/resources/.
122-
const Color _kActionSheetBackgroundColor = CupertinoDynamicColor.withBrightness(
123-
color: Color(0xC7F9F9F9),
124-
darkColor: Color(0xC7252525),
125-
);
124+
// Eyeballed from iOS 17 simulator.
125+
const Color _kActionSheetBackgroundColor = Color(0xC8FCFCFC);
126126

127127
// The gray color used for text that appears in the title area.
128-
// Extracted from https://developer.apple.com/design/resources/.
129-
const Color _kActionSheetContentTextColor = Color(0xFF8F8F8F);
128+
// Eyeballed from iOS 17 simulator.
129+
const Color _kActionSheetContentTextColor = Color(0x851D1D1D);
130130

131131
// Translucent gray that is painted on top of the blurred backdrop in the gap
132132
// areas between the content section and actions section, as well as between
133133
// buttons.
134-
// Eye-balled from iOS 13 beta simulator.
135-
const Color _kActionSheetButtonDividerColor = _kActionSheetContentTextColor;
134+
// Eyeballed from iOS 17 simulator.
135+
const Color _kActionSheetButtonDividerColor = Color(0xD4C9C9C9);
136136

137137
// The alert dialog layout policy changes depending on whether the user is using
138138
// a "regular" font size vs a "large" font size. This is a spectrum. There are
@@ -1115,19 +1115,19 @@ class _ActionSheetButtonBackgroundState extends State<_ActionSheetButtonBackgrou
11151115
BorderRadius? borderRadius;
11161116
if (!widget.isCancel) {
11171117
backgroundColor = isBeingPressed
1118-
? _kPressedColor
1119-
: CupertinoDynamicColor.resolve(_kActionSheetBackgroundColor, context);
1118+
? _kActionSheetPressedColor
1119+
: _kActionSheetBackgroundColor;
11201120
} else {
11211121
backgroundColor = isBeingPressed
1122-
? _kActionSheetCancelPressedColor
1123-
: CupertinoColors.secondarySystemGroupedBackground;
1122+
? _kActionSheetCancelPressedColor
1123+
: _kActionSheetCancelColor;
11241124
borderRadius = const BorderRadius.all(Radius.circular(_kCornerRadius));
11251125
}
11261126
return MetaData(
11271127
metaData: this,
11281128
child: Container(
11291129
decoration: BoxDecoration(
1130-
color: backgroundColor,
1130+
color: CupertinoDynamicColor.resolve(backgroundColor, context),
11311131
borderRadius: borderRadius,
11321132
),
11331133
child: widget.child,
@@ -2269,7 +2269,7 @@ class _CupertinoDialogActionsRenderWidget extends MultiChildRenderObjectWidget {
22692269
: _kCupertinoDialogWidth,
22702270
dividerThickness: _dividerThickness,
22712271
dialogColor: CupertinoDynamicColor.resolve(_kDialogColor, context),
2272-
dialogPressedColor: CupertinoDynamicColor.resolve(_kPressedColor, context),
2272+
dialogPressedColor: CupertinoDynamicColor.resolve(_kDialogPressedColor, context),
22732273
dividerColor: CupertinoDynamicColor.resolve(CupertinoColors.separator, context),
22742274
hasCancelButton: _hasCancelButton,
22752275
);
@@ -2283,7 +2283,7 @@ class _CupertinoDialogActionsRenderWidget extends MultiChildRenderObjectWidget {
22832283
: _kCupertinoDialogWidth
22842284
..dividerThickness = _dividerThickness
22852285
..dialogColor = CupertinoDynamicColor.resolve(_kDialogColor, context)
2286-
..dialogPressedColor = CupertinoDynamicColor.resolve(_kPressedColor, context)
2286+
..dialogPressedColor = CupertinoDynamicColor.resolve(_kDialogPressedColor, context)
22872287
..dividerColor = CupertinoDynamicColor.resolve(CupertinoColors.separator, context)
22882288
..hasCancelButton = _hasCancelButton;
22892289
}

packages/flutter/test/cupertino/action_sheet_test.dart

+107
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,69 @@ import 'package:flutter_test/flutter_test.dart';
1818
import '../widgets/semantics_tester.dart';
1919

2020
void main() {
21+
testWidgets('Overall looks correctly under light theme', (WidgetTester tester) async {
22+
await tester.pumpWidget(
23+
TestScaffoldApp(
24+
theme: const CupertinoThemeData(brightness: Brightness.light),
25+
actionSheet: CupertinoActionSheet(
26+
message: const Text('The title'),
27+
actions: <Widget>[
28+
CupertinoActionSheetAction(child: const Text('One'), onPressed: () {}),
29+
CupertinoActionSheetAction(child: const Text('Two'), onPressed: () {}),
30+
],
31+
cancelButton: CupertinoActionSheetAction(child: const Text('Cancel'), onPressed: () {}),
32+
),
33+
),
34+
);
35+
36+
await tester.tap(find.text('Go'));
37+
await tester.pumpAndSettle();
38+
39+
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('One')));
40+
// This golden file also verifies the structure of an action sheet that
41+
// has a message, no title, and no overscroll for any sections (in contrast
42+
// to cupertinoActionSheet.dark-theme.png).
43+
await expectLater(
44+
find.byType(CupertinoApp),
45+
matchesGoldenFile('cupertinoActionSheet.overall-light-theme.png'),
46+
);
47+
48+
await gesture.up();
49+
});
50+
51+
testWidgets('Overall looks correctly under dark theme', (WidgetTester tester) async {
52+
await tester.pumpWidget(
53+
TestScaffoldApp(
54+
theme: const CupertinoThemeData(brightness: Brightness.dark),
55+
actionSheet: CupertinoActionSheet(
56+
title: const Text('The title'),
57+
message: const Text('The message'),
58+
actions: List<Widget>.generate(20, (int i) =>
59+
CupertinoActionSheetAction(
60+
onPressed: () {},
61+
child: Text('Button $i'),
62+
),
63+
),
64+
cancelButton: CupertinoActionSheetAction(child: const Text('Cancel'), onPressed: () {}),
65+
),
66+
),
67+
);
68+
69+
await tester.tap(find.text('Go'));
70+
await tester.pumpAndSettle();
71+
72+
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.text('Button 0')));
73+
// This golden file also verifies the structure of an action sheet that
74+
// has both a message and a title, and an overscrolled action section (in
75+
// contrast to cupertinoActionSheet.light-theme.png).
76+
await expectLater(
77+
find.byType(CupertinoApp),
78+
matchesGoldenFile('cupertinoActionSheet.overall-dark-theme.png'),
79+
);
80+
81+
await gesture.up();
82+
});
83+
2184
testWidgets('Verify that a tap on modal barrier dismisses an action sheet', (WidgetTester tester) async {
2285
await tester.pumpWidget(
2386
createAppWithButtonThatLaunchesActionSheet(
@@ -1675,6 +1738,50 @@ Widget createAppWithButtonThatLaunchesActionSheet(Widget actionSheet) {
16751738
);
16761739
}
16771740

1741+
// Shows an app that has a button with text "Go", and clicking this button
1742+
// displays the `actionSheet` and hides the button.
1743+
//
1744+
// The `theme` will be applied to the app and determines the background.
1745+
class TestScaffoldApp extends StatefulWidget {
1746+
const TestScaffoldApp({super.key, required this.theme, required this.actionSheet});
1747+
final CupertinoThemeData theme;
1748+
final Widget actionSheet;
1749+
1750+
@override
1751+
TestScaffoldAppState createState() => TestScaffoldAppState();
1752+
}
1753+
1754+
class TestScaffoldAppState extends State<TestScaffoldApp> {
1755+
bool _pressedButton = false;
1756+
1757+
@override
1758+
Widget build(BuildContext context) {
1759+
return CupertinoApp(
1760+
theme: widget.theme,
1761+
home: Builder(builder: (BuildContext context) =>
1762+
CupertinoPageScaffold(
1763+
child: Center(
1764+
child: _pressedButton ? Container() : CupertinoButton(
1765+
onPressed: () {
1766+
setState(() {
1767+
_pressedButton = true;
1768+
});
1769+
showCupertinoModalPopup<void>(
1770+
context: context,
1771+
builder: (BuildContext context) {
1772+
return widget.actionSheet;
1773+
},
1774+
);
1775+
},
1776+
child: const Text('Go'),
1777+
),
1778+
),
1779+
),
1780+
),
1781+
);
1782+
}
1783+
}
1784+
16781785
Widget boilerplate(Widget child) {
16791786
return Directionality(
16801787
textDirection: TextDirection.ltr,

0 commit comments

Comments
 (0)