forked from flutter/plugins
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update SnackBar to support Material 3 (#115750)
* Add M2 defaults and template skeleton * add MaterialStateColor functionality to ActionTextColor (issue #110402) * Add M2 defaults and template skeleton * updated material 3 tokens * Updated snackbar demo * add theme tests * add gen defaults * formatting * more whitespace fixes * add widget type * update docs * code review changes * Add line overflow functionality * whitespace fixes * update M3 animation * whitespace fixes * add insetPadding param * Modifed icon parameter to showCloseIcon * white space fixes * test fixes * rename iconColor to closeIconColor * debug test fix * de-britishification
- Loading branch information
Showing
9 changed files
with
781 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// 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; | ||
} | ||
'''; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// 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), | ||
); | ||
} | ||
} |
Oops, something went wrong.