Update experimental M3 demo (#1692)

pull/1695/head
Qun Cheng 2 years ago committed by GitHub
parent 3ef54e495c
commit 1b195e5dcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -155,12 +155,12 @@ class Selection extends StatelessWidget {
return const ComponentGroupDecoration(label: 'Selection', children: [
Checkboxes(),
Chips(),
// TODO: Add Date pickers https://github.com/flutter/flutter/issues/101481
DatePickers(),
Menus(),
Radios(),
Sliders(),
Switches(),
// TODO: Add Time pickers https://github.com/flutter/flutter/issues/101480
TimePickers(),
]);
}
}
@ -187,7 +187,7 @@ class Buttons extends StatefulWidget {
class _ButtonsState extends State<Buttons> {
@override
Widget build(BuildContext context) {
return ComponentDecoration(
return const ComponentDecoration(
label: 'Common buttons',
tooltipMessage:
'Use ElevatedButton, FilledButton, FilledButton.tonal, OutlinedButton, or TextButton',
@ -195,7 +195,7 @@ class _ButtonsState extends State<Buttons> {
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const <Widget>[
children: <Widget>[
ButtonsWithoutIcon(isDisabled: false),
ButtonsWithIcon(),
ButtonsWithoutIcon(isDisabled: true),
@ -681,11 +681,11 @@ class Dividers extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ComponentDecoration(
return const ComponentDecoration(
label: 'Dividers',
tooltipMessage: 'Use Divider or VerticalDivider',
child: Column(
children: const <Widget>[
children: <Widget>[
Divider(key: Key('divider')),
],
),
@ -698,11 +698,11 @@ class Switches extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ComponentDecoration(
return const ComponentDecoration(
label: 'Switches',
tooltipMessage: 'Use SwitchListTile or Switch',
child: Column(
children: const <Widget>[
children: <Widget>[
SwitchRow(isEnabled: true),
SwitchRow(isEnabled: false),
],
@ -1091,73 +1091,105 @@ class IconToggleButtons extends StatefulWidget {
}
class _IconToggleButtonsState extends State<IconToggleButtons> {
bool standardSelected = false;
bool filledSelected = false;
bool tonalSelected = false;
bool outlinedSelected = false;
@override
Widget build(BuildContext context) {
return ComponentDecoration(
label: 'Icon buttons',
tooltipMessage: 'Use IconButton',
tooltipMessage:
'Use IconButton, IconButton.filled, IconButton.filledTonal, and IconButton.outlined',
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
// Standard IconButton
children: const <Widget>[
IconToggleButton(
isEnabled: true,
tooltip: 'Standard',
children: <Widget>[
IconButton(
isSelected: standardSelected,
icon: const Icon(Icons.settings_outlined),
selectedIcon: const Icon(Icons.settings),
onPressed: () {
setState(() {
standardSelected = !standardSelected;
});
},
),
colDivider,
IconToggleButton(
isEnabled: false,
tooltip: 'Standard (disabled)',
IconButton(
isSelected: standardSelected,
icon: const Icon(Icons.settings_outlined),
selectedIcon: const Icon(Icons.settings),
onPressed: null,
),
],
),
Column(
children: const <Widget>[
children: <Widget>[
// Filled IconButton
IconToggleButton(
isEnabled: true,
tooltip: 'Filled',
getDefaultStyle: enabledFilledButtonStyle,
IconButton.filled(
isSelected: filledSelected,
icon: const Icon(Icons.settings_outlined),
selectedIcon: const Icon(Icons.settings),
onPressed: () {
setState(() {
filledSelected = !filledSelected;
});
},
),
colDivider,
IconToggleButton(
isEnabled: false,
tooltip: 'Filled (disabled)',
getDefaultStyle: disabledFilledButtonStyle,
IconButton.filled(
isSelected: filledSelected,
icon: const Icon(Icons.settings_outlined),
selectedIcon: const Icon(Icons.settings),
onPressed: null,
),
],
),
Column(
children: const <Widget>[
children: <Widget>[
// Filled Tonal IconButton
IconToggleButton(
isEnabled: true,
tooltip: 'Filled tonal',
getDefaultStyle: enabledFilledTonalButtonStyle,
IconButton.filledTonal(
isSelected: tonalSelected,
icon: const Icon(Icons.settings_outlined),
selectedIcon: const Icon(Icons.settings),
onPressed: () {
setState(() {
tonalSelected = !tonalSelected;
});
},
),
colDivider,
IconToggleButton(
isEnabled: false,
tooltip: 'Filled tonal (disabled)',
getDefaultStyle: disabledFilledTonalButtonStyle,
IconButton.filledTonal(
isSelected: tonalSelected,
icon: const Icon(Icons.settings_outlined),
selectedIcon: const Icon(Icons.settings),
onPressed: null,
),
],
),
Column(
children: const <Widget>[
children: <Widget>[
// Outlined IconButton
IconToggleButton(
isEnabled: true,
tooltip: 'Outlined',
getDefaultStyle: enabledOutlinedButtonStyle,
IconButton.outlined(
isSelected: outlinedSelected,
icon: const Icon(Icons.settings_outlined),
selectedIcon: const Icon(Icons.settings),
onPressed: () {
setState(() {
outlinedSelected = !outlinedSelected;
});
},
),
colDivider,
IconToggleButton(
isEnabled: false,
tooltip: 'Outlined (disabled)',
getDefaultStyle: disabledOutlinedButtonStyle,
IconButton.outlined(
isSelected: outlinedSelected,
icon: const Icon(Icons.settings_outlined),
selectedIcon: const Icon(Icons.settings),
onPressed: null,
),
],
),
@ -1167,134 +1199,6 @@ class _IconToggleButtonsState extends State<IconToggleButtons> {
}
}
class IconToggleButton extends StatefulWidget {
const IconToggleButton({
required this.isEnabled,
required this.tooltip,
this.getDefaultStyle,
super.key,
});
final bool isEnabled;
final String tooltip;
final ButtonStyle? Function(bool, ColorScheme)? getDefaultStyle;
@override
State<IconToggleButton> createState() => _IconToggleButtonState();
}
class _IconToggleButtonState extends State<IconToggleButton> {
bool selected = false;
@override
Widget build(BuildContext context) {
final ColorScheme colors = Theme.of(context).colorScheme;
final VoidCallback? onPressed = widget.isEnabled
? () {
setState(() {
selected = !selected;
});
}
: null;
ButtonStyle? style = widget.getDefaultStyle?.call(selected, colors);
return IconButton(
visualDensity: VisualDensity.standard,
isSelected: selected,
tooltip: widget.tooltip,
icon: const Icon(Icons.settings_outlined),
selectedIcon: const Icon(Icons.settings),
onPressed: onPressed,
style: style,
);
}
}
ButtonStyle enabledFilledButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
foregroundColor: selected ? colors.onPrimary : colors.primary,
backgroundColor: selected ? colors.primary : colors.surfaceVariant,
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
hoverColor: selected
? colors.onPrimary.withOpacity(0.08)
: colors.primary.withOpacity(0.08),
focusColor: selected
? colors.onPrimary.withOpacity(0.12)
: colors.primary.withOpacity(0.12),
highlightColor: selected
? colors.onPrimary.withOpacity(0.12)
: colors.primary.withOpacity(0.12),
);
}
ButtonStyle disabledFilledButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
);
}
ButtonStyle enabledFilledTonalButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
foregroundColor:
selected ? colors.onSecondaryContainer : colors.onSurfaceVariant,
backgroundColor:
selected ? colors.secondaryContainer : colors.surfaceVariant,
hoverColor: selected
? colors.onSecondaryContainer.withOpacity(0.08)
: colors.onSurfaceVariant.withOpacity(0.08),
focusColor: selected
? colors.onSecondaryContainer.withOpacity(0.12)
: colors.onSurfaceVariant.withOpacity(0.12),
highlightColor: selected
? colors.onSecondaryContainer.withOpacity(0.12)
: colors.onSurfaceVariant.withOpacity(0.12),
);
}
ButtonStyle disabledFilledTonalButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor: colors.onSurface.withOpacity(0.12),
);
}
ButtonStyle enabledOutlinedButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
backgroundColor: selected ? colors.inverseSurface : null,
hoverColor: selected
? colors.onInverseSurface.withOpacity(0.08)
: colors.onSurfaceVariant.withOpacity(0.08),
focusColor: selected
? colors.onInverseSurface.withOpacity(0.12)
: colors.onSurfaceVariant.withOpacity(0.12),
highlightColor: selected
? colors.onInverseSurface.withOpacity(0.12)
: colors.onSurface.withOpacity(0.12),
side: BorderSide(color: colors.outline),
).copyWith(
foregroundColor: MaterialStateProperty.resolveWith((states) {
if (states.contains(MaterialState.selected)) {
return colors.onInverseSurface;
}
if (states.contains(MaterialState.pressed)) {
return colors.onSurface;
}
return null;
}),
);
}
ButtonStyle disabledOutlinedButtonStyle(bool selected, ColorScheme colors) {
return IconButton.styleFrom(
disabledForegroundColor: colors.onSurface.withOpacity(0.38),
disabledBackgroundColor:
selected ? colors.onSurface.withOpacity(0.12) : null,
side: selected ? null : BorderSide(color: colors.outline.withOpacity(0.12)),
);
}
class Chips extends StatefulWidget {
const Chips({super.key});
@ -1371,16 +1275,97 @@ class _ChipsState extends State<Chips> {
}
}
class DatePickers extends StatefulWidget {
const DatePickers({super.key});
@override
State<DatePickers> createState() => _DatePickersState();
}
class _DatePickersState extends State<DatePickers> {
DateTime? selectedDate;
final DateTime _firstDate = DateTime(DateTime.now().year - 2);
final DateTime _lastDate = DateTime(DateTime.now().year + 1);
@override
Widget build(BuildContext context) {
return ComponentDecoration(
label: 'Date picker',
tooltipMessage: 'Use showDatePicker',
child: TextButton(
onPressed: () async {
DateTime? date = await showDatePicker(
context: context,
initialDate: selectedDate ?? DateTime.now(),
firstDate: _firstDate,
lastDate: _lastDate,
);
setState(() {
selectedDate = date;
if (selectedDate != null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(
'Selected Date: ${selectedDate!.day}/${selectedDate!.month}/${selectedDate!.year}'),
));
}
});
},
child: const Text(
'Show date picker',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
);
}
}
class TimePickers extends StatefulWidget {
const TimePickers({super.key});
@override
State<TimePickers> createState() => _TimePickersState();
}
class _TimePickersState extends State<TimePickers> {
TimeOfDay? selectedTime;
@override
Widget build(BuildContext context) {
return ComponentDecoration(
label: 'Time picker',
tooltipMessage: 'Use showTimePicker',
child: TextButton(
onPressed: () async {
final TimeOfDay? time = await showTimePicker(
context: context,
initialTime: selectedTime ?? TimeOfDay.now(),
);
setState(() {
selectedTime = time;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Selected time: ${selectedTime!.format(context)}'),
));
});
},
child: const Text(
'Show time picker',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
);
}
}
class SegmentedButtons extends StatelessWidget {
const SegmentedButtons({super.key});
@override
Widget build(BuildContext context) {
return ComponentDecoration(
return const ComponentDecoration(
label: 'Segmented buttons',
tooltipMessage: 'Use SegmentedButton<T>',
child: Column(
children: const <Widget>[
children: <Widget>[
SingleChoice(),
colDivider,
MultipleChoice(),
@ -2075,9 +2060,9 @@ class _MenusState extends State<Menus> {
tooltipMessage: 'Use MenuAnchor or DropdownMenu<T>',
child: Column(
children: [
Row(
const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
children: <Widget>[
ButtonAnchorExample(),
rowDivider,
IconButtonAnchorExample(),

@ -37,7 +37,7 @@ void main() {
expect(find.widgetWithText(FloatingActionButton, 'Create'), findsOneWidget);
// Icon buttons
expect(find.byType(IconToggleButton), findsNWidgets(8));
expect(find.widgetWithIcon(IconButton, Icons.settings_outlined), findsNWidgets(8));
// Segmented buttons
expect(find.byType(SegmentedButton<Calendar>), findsOneWidget);
@ -106,6 +106,9 @@ void main() {
expect(find.byType(FilterChip), findsNWidgets(2));
expect(find.byType(InputChip), findsNWidgets(2));
// Date pickers
expect(find.widgetWithText(TextButton, 'Show date picker'), findsOneWidget);
// Menus
expect(find.byType(MenuAnchor), findsNWidgets(5));
expect(find.byType(DropdownMenu<ColorLabel>), findsOneWidget);
@ -121,6 +124,9 @@ void main() {
// Switches
expect(find.byType(Switch), findsNWidgets(4));
// Time pickers
expect(find.widgetWithText(TextButton, 'Show time picker'), findsOneWidget);
// TextFields
expect(find.widgetWithText(TextField, 'Disabled'), findsNWidgets(2));
expect(find.widgetWithText(TextField, 'Filled'), findsNWidgets(2));

@ -31,7 +31,8 @@ declare -ar PROJECT_NAMES=(
"experimental/federated_plugin/federated_plugin_web"
"experimental/federated_plugin/federated_plugin_windows"
"experimental/linting_tool"
"experimental/material_3_demo"
# TODO(DomesticMouse): uncomment on next Flutter stable increment
# "experimental/material_3_demo"
"experimental/pedometer"
"experimental/varfont_shader_puzzle"
"experimental/web_dashboard"

Loading…
Cancel
Save