Unverified Commit 8b32ac7a authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Revert "Update SnackBar to support Material 3" (#116199)

* Revert "Update SnackBar to support Material 3 (#115750)"

This reverts commit d58855c4.

* Kick ci.yaml
Co-authored-by: 's avatarJenn Magder <magder@google.com>
parent d58855c4
......@@ -44,7 +44,6 @@ import 'package:gen_defaults/progress_indicator_template.dart';
import 'package:gen_defaults/radio_template.dart';
import 'package:gen_defaults/segmented_button_template.dart';
import 'package:gen_defaults/slider_template.dart';
import 'package:gen_defaults/snackbar_template.dart';
import 'package:gen_defaults/surface_tint.dart';
import 'package:gen_defaults/switch_template.dart';
import 'package:gen_defaults/text_field_template.dart';
......@@ -162,7 +161,6 @@ Future<void> main(List<String> args) async {
ProgressIndicatorTemplate('ProgressIndicator', '$materialLib/progress_indicator.dart', tokens).updateFile();
RadioTemplate('Radio<T>', '$materialLib/radio.dart', tokens).updateFile();
SegmentedButtonTemplate('SegmentedButton', '$materialLib/segmented_button.dart', tokens).updateFile();
SnackbarTemplate('md.comp.snackbar', 'Snackbar', '$materialLib/snack_bar.dart', tokens).updateFile();
SliderTemplate('md.comp.slider', 'Slider', '$materialLib/slider.dart', tokens).updateFile();
SurfaceTintTemplate('SurfaceTint', '$materialLib/elevation_overlay.dart', tokens).updateFile();
SwitchTemplate('Switch', '$materialLib/switch.dart', tokens).updateFile();
......
// 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.
import 'template.dart';
class SnackbarTemplate extends TokenTemplate {
const SnackbarTemplate(
this.tokenGroup, super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.'
});
final String tokenGroup;
@override
String generate() => '''
class _${blockName}DefaultsM3 extends SnackBarThemeData {
_${blockName}DefaultsM3(this.context);
final BuildContext context;
late final ThemeData _theme = Theme.of(context);
late final ColorScheme _colors = _theme.colorScheme;
@override
Color get backgroundColor => ${componentColor("$tokenGroup.container")};
@override
Color get actionTextColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return ${componentColor("$tokenGroup.action.pressed.label-text")};
}
if (states.contains(MaterialState.pressed)) {
return ${componentColor("$tokenGroup.action.pressed.label-text")};
}
if (states.contains(MaterialState.hovered)) {
return ${componentColor("$tokenGroup.action.hover.label-text")};
}
if (states.contains(MaterialState.focused)) {
return ${componentColor("$tokenGroup.action.focus.label-text")};
}
return ${componentColor("$tokenGroup.action.label-text")};
});
@override
Color get disabledActionTextColor =>
${componentColor("$tokenGroup.action.pressed.label-text")};
@override
TextStyle get contentTextStyle =>
${textStyle("$tokenGroup.supporting-text")}!.copyWith
(color: ${componentColor("$tokenGroup.supporting-text")},
);
@override
double get elevation => ${elevation("$tokenGroup.container")};
@override
ShapeBorder get shape => ${shape("$tokenGroup.container")};
@override
SnackBarBehavior get behavior => SnackBarBehavior.fixed;
@override
EdgeInsets get insetPadding => const EdgeInsets.fromLTRB(15.0, 5.0, 15.0, 10.0);
@override
bool get showCloseIcon => false;
@override
Color get iconColor => _colors.onInverseSurface;
}
''';
}
// 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.
/// Flutter code sample for [SnackBar] with Material 3 specifications.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
// A Material 3 [SnackBar] demonstrating an optional icon, in either floating
// or fixed format.
class MyApp extends StatelessWidget {
const MyApp({super.key});
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
theme: ThemeData(useMaterial3: true),
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const Center(
child: SnackBarExample(),
),
),
);
}
}
class SnackBarExample extends StatefulWidget {
const SnackBarExample({super.key});
@override
State<SnackBarExample> createState() => _SnackBarExampleState();
}
class _SnackBarExampleState extends State<SnackBarExample> {
SnackBarBehavior? _snackBarBehavior = SnackBarBehavior.floating;
bool _withIcon = true;
bool _withAction = true;
bool _multiLine = false;
bool _longActionLabel = false;
Padding _configRow(List<Widget> children) => Padding(
padding: const EdgeInsets.all(8.0), child: Row(children: children));
@override
Widget build(BuildContext context) {
return Padding(padding: const EdgeInsets.only(left: 50.0), child: Column(
children: <Widget>[
_configRow(<Widget>[
Text('Snack Bar configuration',
style: Theme.of(context).textTheme.bodyLarge),
]),
_configRow(
<Widget>[
const Text('Fixed'),
Radio<SnackBarBehavior>(
value: SnackBarBehavior.fixed,
groupValue: _snackBarBehavior,
onChanged: (SnackBarBehavior? value) {
setState(() {
_snackBarBehavior = value;
});
},
),
const Text('Floating'),
Radio<SnackBarBehavior>(
value: SnackBarBehavior.floating,
groupValue: _snackBarBehavior,
onChanged: (SnackBarBehavior? value) {
setState(() {
_snackBarBehavior = value;
});
},
),
],
),
_configRow(
<Widget>[
const Text('Include Icon '),
Switch(
value: _withIcon,
onChanged: (bool value) {
setState(() {
_withIcon = !_withIcon;
});
},
),
],
),
_configRow(
<Widget>[
const Text('Include Action '),
Switch(
value: _withAction,
onChanged: (bool value) {
setState(() {
_withAction = !_withAction;
});
},
),
const SizedBox(width: 16.0),
const Text('Long Action Label '),
Switch(
value: _longActionLabel,
onChanged: !_withAction
? null
: (bool value) {
setState(() {
_longActionLabel = !_longActionLabel;
});
},
),
],
),
_configRow(
<Widget>[
const Text('Multi Line Text'),
Switch(
value: _multiLine,
onChanged: _snackBarBehavior == SnackBarBehavior.fixed ? null : (bool value) {
setState(() {
_multiLine = !_multiLine;
});
},
),
],
),
const SizedBox(height: 16.0),
ElevatedButton(
child: const Text('Show Snackbar'),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(_snackBar());
}
),
],
),
);
}
SnackBar _snackBar() {
final SnackBarAction? action = _withAction
? SnackBarAction(
label: _longActionLabel ? 'Long Action Text' : 'Action',
onPressed: () {
// Code to execute.
},
)
: null;
final double? width =
_snackBarBehavior == SnackBarBehavior.floating && _multiLine ? 400.0 : null;
final String label = _multiLine
? 'A Snack Bar with quite a lot of text which spans across multiple lines'
: 'Single Line Snack Bar';
return SnackBar(
content: Text(label),
showCloseIcon: _withIcon,
width: width,
behavior: _snackBarBehavior,
action: action,
duration: const Duration(seconds: 3),
);
}
}
......@@ -61,9 +61,6 @@ class SnackBarThemeData with Diagnosticable {
this.shape,
this.behavior,
this.width,
this.insetPadding,
this.showCloseIcon,
this.closeIconColor,
}) : assert(elevation == null || elevation >= 0.0),
assert(
width == null ||
......@@ -118,21 +115,6 @@ class SnackBarThemeData with Diagnosticable {
/// [SnackBarBehavior.floating].
final double? width;
/// Overrides the default value for [SnackBar.margin].
///
/// This value is only used when [behavior] is [SnackBarBehavior.floating].
final EdgeInsets? insetPadding;
/// Overrides the default value for [SnackBar.showCloseIcon].
///
/// Whether to show an optional "Close" icon.
final bool? showCloseIcon;
/// Overrides the default value for [SnackBar.closeIconColor].
///
/// This value is only used if [showCloseIcon] is true.
final Color? closeIconColor;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
SnackBarThemeData copyWith({
......@@ -144,9 +126,6 @@ class SnackBarThemeData with Diagnosticable {
ShapeBorder? shape,
SnackBarBehavior? behavior,
double? width,
EdgeInsets? insetPadding,
bool? showCloseIcon,
Color? closeIconColor,
}) {
return SnackBarThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
......@@ -157,9 +136,6 @@ class SnackBarThemeData with Diagnosticable {
shape: shape ?? this.shape,
behavior: behavior ?? this.behavior,
width: width ?? this.width,
insetPadding: insetPadding ?? this.insetPadding,
showCloseIcon: showCloseIcon ?? this.showCloseIcon,
closeIconColor: closeIconColor ?? this.closeIconColor,
);
}
......@@ -179,8 +155,6 @@ class SnackBarThemeData with Diagnosticable {
shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
behavior: t < 0.5 ? a?.behavior : b?.behavior,
width: lerpDouble(a?.width, b?.width, t),
insetPadding: EdgeInsets.lerp(a?.insetPadding, b?.insetPadding, t),
closeIconColor: Color.lerp(a?.closeIconColor, b?.closeIconColor, t),
);
}
......@@ -194,9 +168,6 @@ class SnackBarThemeData with Diagnosticable {
shape,
behavior,
width,
insetPadding,
showCloseIcon,
closeIconColor,
);
@override
......@@ -215,10 +186,7 @@ class SnackBarThemeData with Diagnosticable {
&& other.elevation == elevation
&& other.shape == shape
&& other.behavior == behavior
&& other.width == width
&& other.insetPadding == insetPadding
&& other.showCloseIcon == showCloseIcon
&& other.closeIconColor == closeIconColor;
&& other.width == width;
}
@override
......@@ -232,8 +200,5 @@ class SnackBarThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
properties.add(DiagnosticsProperty<SnackBarBehavior>('behavior', behavior, defaultValue: null));
properties.add(DoubleProperty('width', width, defaultValue: null));
properties.add(DiagnosticsProperty<EdgeInsets>('insetPadding', insetPadding, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('showCloseIcon', showCloseIcon, defaultValue: null));
properties.add(ColorProperty('closeIconColor', closeIconColor, defaultValue: null));
}
}
......@@ -1321,7 +1321,6 @@ class ThemeData with Diagnosticable {
/// * [Navigation rail](https://m3.material.io/components/navigation-rail): [NavigationRail]
/// * Progress indicators: [CircularProgressIndicator], [LinearProgressIndicator]
/// * Radio button: [Radio]
/// * Snack bar: [SnackBar]
/// * Switch: [Switch]
/// * Top app bar: [AppBar]
///
......
......@@ -316,7 +316,6 @@ void main() {
' TextButtonTheme\n'
' Padding\n'
' Row\n'
' Column\n'
' Padding\n'
' MediaQuery\n'
' Padding\n'
......
......@@ -2340,146 +2340,7 @@ void main() {
await expectLater(find.byType(MaterialApp), matchesGoldenFile('snack_bar.goldenTest.backdropFilter.png'));
});
testWidgets('Floating snackbar can display optional icon', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(
SnackBar(
content: const Text('Feeling snackish'),
duration: const Duration(seconds: 2),
action: SnackBarAction(label: 'ACTION', onPressed: () {}),
behavior: SnackBarBehavior.floating,
showCloseIcon: true,
),
);
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(
find.byType(MaterialApp),
matchesGoldenFile(
'snack_bar.goldenTest.floatingWithActionWithIcon.png'));
});
testWidgets('Fixed width snackbar can display optional icon', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(SnackBar(
content: const Text('Go get a snack'),
duration: const Duration(seconds: 2),
action: SnackBarAction(label: 'ACTION', onPressed: () {}),
showCloseIcon: true,
behavior: SnackBarBehavior.fixed,
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('snack_bar.goldenTest.fixedWithActionWithIcon.png'));
});
testWidgets('Fixed snackbar can display optional icon without action', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(
const SnackBar(
content: Text('I wonder if there are snacks nearby?'),
duration: Duration(seconds: 2),
behavior: SnackBarBehavior.fixed,
showCloseIcon: true,
),
);
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp), matchesGoldenFile('snack_bar.goldenTest.fixedWithIcon.png'));
});
testWidgets(
'Floating width snackbar can display optional icon without action', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(const SnackBar(
content: Text('Must go get a snack!'),
duration: Duration(seconds: 2),
showCloseIcon: true,
behavior: SnackBarBehavior.floating,
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp),
matchesGoldenFile('snack_bar.goldenTest.floatingWithIcon.png'));
});
testWidgets('Fixed multi-line snackbar with icon is aligned correctly', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(
bottomSheet: SizedBox(
width: 200,
height: 50,
child: ColoredBox(
color: Colors.pink,
),
),
),
));
final ScaffoldMessengerState scaffoldMessengerState = tester.state(find.byType(ScaffoldMessenger));
scaffoldMessengerState.showSnackBar(const SnackBar(
content: Text(
'This is a really long snackbar message. So long, it spans across more than one line!'),
duration: Duration(seconds: 2),
showCloseIcon: true,
behavior: SnackBarBehavior.floating,
));
await tester.pumpAndSettle(); // Have the SnackBar fully animate out.
await expectLater(find.byType(MaterialApp),
matchesGoldenFile('snack_bar.goldenTest.multiLineWithIcon.png'));
});
testWidgets(
'ScaffoldMessenger will alert for snackbars that cannot be presented', (WidgetTester tester) async {
testWidgets('ScaffoldMessenger will alert for snackbars that cannot be presented', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/103004
await tester.pumpWidget(const MaterialApp(
home: Center(),
......
......@@ -22,9 +22,6 @@ void main() {
expect(snackBarTheme.shape, null);
expect(snackBarTheme.behavior, null);
expect(snackBarTheme.width, null);
expect(snackBarTheme.insetPadding, null);
expect(snackBarTheme.showCloseIcon, null);
expect(snackBarTheme.closeIconColor, null);
});
test(
......@@ -62,9 +59,6 @@ void main() {
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))),
behavior: SnackBarBehavior.floating,
width: 400.0,
insetPadding: EdgeInsets.all(10.0),
showCloseIcon: false,
closeIconColor: Color(0xFF0000AA),
).debugFillProperties(builder);
final List<String> description = builder.properties
......@@ -81,9 +75,6 @@ void main() {
'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.circular(2.0))',
'behavior: SnackBarBehavior.floating',
'width: 400.0',
'insetPadding: EdgeInsets.all(10.0)',
'showCloseIcon: false',
'closeIconColor: Color(0xff0000aa)',
]);
});
......@@ -124,7 +115,7 @@ void main() {
testWidgets('SnackBar uses values from SnackBarThemeData', (WidgetTester tester) async {
const String text = 'I am a snack bar.';
const String action = 'ACTION';
final SnackBarThemeData snackBarTheme = _snackBarTheme(showCloseIcon: true);
final SnackBarThemeData snackBarTheme = _snackBarTheme();
await tester.pumpWidget(MaterialApp(
theme: ThemeData(snackBarTheme: snackBarTheme),
......@@ -153,14 +144,12 @@ void main() {
final Material material = _getSnackBarMaterial(tester);
final RenderParagraph button = _getSnackBarActionTextRenderObject(tester, action);
final RenderParagraph content = _getSnackBarTextRenderObject(tester, text);
final Icon icon = _getSnackBarIcon(tester);
expect(content.text.style, snackBarTheme.contentTextStyle);
expect(material.color, snackBarTheme.backgroundColor);
expect(material.elevation, snackBarTheme.elevation);
expect(material.shape, snackBarTheme.shape);
expect(button.text.style!.color, snackBarTheme.actionTextColor);
expect(icon.icon, Icons.close);
});
testWidgets('SnackBar widget properties take priority over theme', (WidgetTester tester) async {
......@@ -174,7 +163,7 @@ void main() {
const double snackBarWidth = 400.0;
await tester.pumpWidget(MaterialApp(
theme: ThemeData(snackBarTheme: _snackBarTheme(showCloseIcon: true)),
theme: ThemeData(snackBarTheme: _snackBarTheme()),
home: Scaffold(
body: Builder(
builder: (BuildContext context) {
......@@ -193,7 +182,6 @@ void main() {
label: action,
onPressed: () {},
),
showCloseIcon: false,
));
},
child: const Text('X'),
......@@ -216,7 +204,6 @@ void main() {
expect(material.elevation, elevation);
expect(material.shape, shape);
expect(button.text.style!.color, textColor);
expect(_getSnackBarIconFinder(tester), findsNothing);
// Assert width.
final Offset snackBarBottomLeft = tester.getBottomLeft(materialFinder.first);
final Offset snackBarBottomRight = tester.getBottomRight(materialFinder.first);
......@@ -227,7 +214,8 @@ void main() {
testWidgets('SnackBar theme behavior is correct for floating', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
snackBarTheme: const SnackBarThemeData(behavior: SnackBarBehavior.floating)),
snackBarTheme: const SnackBarThemeData(behavior: SnackBarBehavior.floating),
),
home: Scaffold(
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.send),
......@@ -401,14 +389,13 @@ void main() {
});
}
SnackBarThemeData _snackBarTheme({bool? showCloseIcon}) {
return SnackBarThemeData(
SnackBarThemeData _snackBarTheme() {
return const SnackBarThemeData(
backgroundColor: Colors.orange,
actionTextColor: Colors.green,
contentTextStyle: const TextStyle(color: Colors.blue),
contentTextStyle: TextStyle(color: Colors.blue),
elevation: 12.0,
showCloseIcon: showCloseIcon,
shape: const BeveledRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12))),
shape: BeveledRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12))),
);
}
......@@ -422,6 +409,7 @@ Finder _getSnackBarMaterialFinder(WidgetTester tester) {
return find.descendant(
of: find.byType(SnackBar),
matching: find.byType(Material),
);
}
......@@ -432,17 +420,6 @@ RenderParagraph _getSnackBarActionTextRenderObject(WidgetTester tester, String t
));
}
Icon _getSnackBarIcon(WidgetTester tester) {
return tester.widget<Icon>(_getSnackBarIconFinder(tester));
}
Finder _getSnackBarIconFinder(WidgetTester tester) {
return find.descendant(
of: find.byType(SnackBar),
matching: find.byIcon(Icons.close),
);
}
RenderParagraph _getSnackBarTextRenderObject(WidgetTester tester, String text) {
return tester.renderObject(find.descendant(
of: find.byType(SnackBar),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment