mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 22:09:06 +00:00
Added M3 demo app (#1189)
* Added M3 demo app * Changed to use the centralized lint configuration. * Moved the app at the root level * Added to CI * Added app to beta CI and commented app on stable CI file * Update README.md * Addressed comments * fixed comments * Reverted app name in CI files. * Added project to the Pub Dependabot config * Linting pass for current beta channel standards Co-authored-by: Qun Cheng <quncheng@google.com> Co-authored-by: Craig Labenz <craig.labenz@gmail.com>
This commit is contained in:
509
material_3_demo/lib/component_screen.dart
Normal file
509
material_3_demo/lib/component_screen.dart
Normal file
@@ -0,0 +1,509 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ComponentScreen extends StatelessWidget {
|
||||
const ComponentScreen({Key? key, required this.showNavBottomBar})
|
||||
: super(key: key);
|
||||
|
||||
final bool showNavBottomBar;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
_colDivider,
|
||||
_colDivider,
|
||||
const Buttons(),
|
||||
_colDivider,
|
||||
const FloatingActionButtons(),
|
||||
_colDivider,
|
||||
const Cards(),
|
||||
_colDivider,
|
||||
const Dialogs(),
|
||||
_colDivider,
|
||||
showNavBottomBar
|
||||
? const NavigationBars(
|
||||
selectedIndex: 0,
|
||||
isExampleBar: true,
|
||||
)
|
||||
: Container(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const _rowDivider = SizedBox(width: 10);
|
||||
const _colDivider = SizedBox(height: 10);
|
||||
const double _cardWidth = 115;
|
||||
|
||||
void Function()? handlePressed(BuildContext context, bool isDisabled, String buttonName) {
|
||||
return isDisabled
|
||||
? null
|
||||
: () {
|
||||
final snackBar = SnackBar(
|
||||
content: Text(
|
||||
'Yay! $buttonName is clicked!',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.surface),
|
||||
),
|
||||
action: SnackBarAction(
|
||||
textColor: Theme.of(context).colorScheme.surface,
|
||||
label: 'Close',
|
||||
onPressed: () {},
|
||||
),
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
};
|
||||
}
|
||||
|
||||
class Buttons extends StatefulWidget {
|
||||
const Buttons({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Buttons> createState() => _ButtonsState();
|
||||
}
|
||||
|
||||
class _ButtonsState extends State<Buttons> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Wrap(
|
||||
alignment: WrapAlignment.spaceEvenly,
|
||||
children: const <Widget>[
|
||||
ButtonsWithoutIcon(isDisabled: false),
|
||||
_rowDivider,
|
||||
ButtonsWithIcon(),
|
||||
_rowDivider,
|
||||
ButtonsWithoutIcon(isDisabled: true),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ButtonsWithoutIcon extends StatelessWidget {
|
||||
final bool isDisabled;
|
||||
|
||||
const ButtonsWithoutIcon({Key? key, required this.isDisabled})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IntrinsicWidth(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
ElevatedButton(
|
||||
onPressed: handlePressed(context, isDisabled, "ElevatedButton"),
|
||||
child: const Text("Elevated"),
|
||||
),
|
||||
_colDivider,
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
// Foreground color
|
||||
onPrimary: Theme.of(context).colorScheme.onPrimary,
|
||||
// Background color
|
||||
primary: Theme.of(context).colorScheme.primary,
|
||||
).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)),
|
||||
onPressed: handlePressed(context, isDisabled, "FilledButton"),
|
||||
child: const Text('Filled'),
|
||||
),
|
||||
_colDivider,
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
// Foreground color
|
||||
onPrimary: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
// Background color
|
||||
primary: Theme.of(context).colorScheme.secondaryContainer,
|
||||
).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)),
|
||||
onPressed: handlePressed(context, isDisabled, "FilledTonalButton"),
|
||||
child: const Text('Filled Tonal'),
|
||||
),
|
||||
_colDivider,
|
||||
OutlinedButton(
|
||||
onPressed: handlePressed(context, isDisabled, "OutlinedButton"),
|
||||
child: const Text("Outlined"),
|
||||
),
|
||||
_colDivider,
|
||||
TextButton(
|
||||
onPressed: handlePressed(context, isDisabled, "TextButton"),
|
||||
child: const Text("Text")),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ButtonsWithIcon extends StatelessWidget {
|
||||
const ButtonsWithIcon({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IntrinsicWidth(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
ElevatedButton.icon(
|
||||
onPressed:
|
||||
handlePressed(context, false, "ElevatedButton with Icon"),
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text("Icon"),
|
||||
),
|
||||
_colDivider,
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
// Foreground color
|
||||
onPrimary: Theme.of(context).colorScheme.onPrimary,
|
||||
// Background color
|
||||
primary: Theme.of(context).colorScheme.primary,
|
||||
).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)),
|
||||
onPressed: handlePressed(context, false, "FilledButton with Icon"),
|
||||
label: const Text('Icon'),
|
||||
icon: const Icon(Icons.add),
|
||||
),
|
||||
_colDivider,
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
// Foreground color
|
||||
onPrimary: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||
// Background color
|
||||
primary: Theme.of(context).colorScheme.secondaryContainer,
|
||||
).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)),
|
||||
onPressed:
|
||||
handlePressed(context, false, "FilledTonalButton with Icon"),
|
||||
label: const Text('Icon'),
|
||||
icon: const Icon(Icons.add),
|
||||
),
|
||||
_colDivider,
|
||||
OutlinedButton.icon(
|
||||
onPressed:
|
||||
handlePressed(context, false, "OutlinedButton with Icon"),
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text("Icon"),
|
||||
),
|
||||
_colDivider,
|
||||
TextButton.icon(
|
||||
onPressed: handlePressed(context, false, "TextButton with Icon"),
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text("Icon"),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FloatingActionButtons extends StatelessWidget {
|
||||
const FloatingActionButtons({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceEvenly,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
FloatingActionButton.small(
|
||||
onPressed: () {},
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
_rowDivider,
|
||||
FloatingActionButton(
|
||||
onPressed: () {},
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
_rowDivider,
|
||||
FloatingActionButton.extended(
|
||||
onPressed: () {},
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text("Create"),
|
||||
),
|
||||
_rowDivider,
|
||||
FloatingActionButton.large(
|
||||
onPressed: () {},
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Cards extends StatelessWidget {
|
||||
const Cards({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceEvenly,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: _cardWidth,
|
||||
child: Card(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: const [
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Icon(Icons.more_vert),
|
||||
),
|
||||
_colDivider,
|
||||
_colDivider,
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text("Elevated"),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: _cardWidth,
|
||||
child: Card(
|
||||
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||
elevation: 0,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: const [
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Icon(Icons.more_vert),
|
||||
),
|
||||
_colDivider,
|
||||
_colDivider,
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text("Filled"),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: _cardWidth,
|
||||
child: Card(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
color: Theme.of(context).colorScheme.outline,
|
||||
),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: const [
|
||||
Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Icon(Icons.more_vert),
|
||||
),
|
||||
_colDivider,
|
||||
_colDivider,
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text("Outlined"),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Dialogs extends StatefulWidget {
|
||||
const Dialogs({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<Dialogs> createState() => _DialogsState();
|
||||
}
|
||||
|
||||
class _DialogsState extends State<Dialogs> {
|
||||
void openDialog(BuildContext context) {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text("Basic Dialog Title"),
|
||||
content: const Text(
|
||||
"A dialog is a type of modal window that appears in front of app content to provide critical information, or prompt for a decision to be made."),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('Dismiss'),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('Action'),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: TextButton(
|
||||
child: const Text(
|
||||
"Open Dialog",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
onPressed: () => openDialog(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const List<NavigationDestination> appBarDestinations = [
|
||||
NavigationDestination(
|
||||
tooltip: "",
|
||||
icon: Icon(Icons.widgets_outlined),
|
||||
label: 'Components',
|
||||
selectedIcon: Icon(Icons.widgets),
|
||||
),
|
||||
NavigationDestination(
|
||||
tooltip: "",
|
||||
icon: Icon(Icons.format_paint_outlined),
|
||||
label: 'Color',
|
||||
selectedIcon: Icon(Icons.format_paint),
|
||||
),
|
||||
NavigationDestination(
|
||||
tooltip: "",
|
||||
icon: Icon(Icons.text_snippet_outlined),
|
||||
label: 'Typography',
|
||||
selectedIcon: Icon(Icons.text_snippet),
|
||||
),
|
||||
NavigationDestination(
|
||||
tooltip: "",
|
||||
icon: Icon(Icons.invert_colors_on_outlined),
|
||||
label: 'Elevation',
|
||||
selectedIcon: Icon(Icons.opacity),
|
||||
)
|
||||
];
|
||||
|
||||
final List<NavigationRailDestination> navRailDestinations = appBarDestinations
|
||||
.map((destination) => NavigationRailDestination(
|
||||
icon: Tooltip(
|
||||
message: destination.label,
|
||||
child: destination.icon,
|
||||
),
|
||||
selectedIcon: Tooltip(
|
||||
message: destination.label,
|
||||
child: destination.selectedIcon,
|
||||
),
|
||||
label: Text(destination.label)
|
||||
))
|
||||
.toList();
|
||||
|
||||
const List<Widget> exampleBarDestinations = [
|
||||
NavigationDestination(
|
||||
tooltip: "",
|
||||
icon: Icon(Icons.explore_outlined),
|
||||
label: 'Explore',
|
||||
selectedIcon: Icon(Icons.explore),
|
||||
),
|
||||
NavigationDestination(
|
||||
tooltip: "",
|
||||
icon: Icon(Icons.pets_outlined),
|
||||
label: 'Pets',
|
||||
selectedIcon: Icon(Icons.pets),
|
||||
),
|
||||
NavigationDestination(
|
||||
tooltip: "",
|
||||
icon: Icon(Icons.account_box_outlined),
|
||||
label: 'Account',
|
||||
selectedIcon: Icon(Icons.account_box),
|
||||
)
|
||||
];
|
||||
|
||||
class NavigationBars extends StatefulWidget {
|
||||
final void Function(int)? onSelectItem;
|
||||
final int selectedIndex;
|
||||
final bool isExampleBar;
|
||||
|
||||
const NavigationBars(
|
||||
{Key? key,
|
||||
this.onSelectItem,
|
||||
required this.selectedIndex,
|
||||
required this.isExampleBar})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<NavigationBars> createState() => _NavigationBarsState();
|
||||
}
|
||||
|
||||
class _NavigationBarsState extends State<NavigationBars> {
|
||||
int _selectedIndex = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_selectedIndex = widget.selectedIndex;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return NavigationBar(
|
||||
selectedIndex: _selectedIndex,
|
||||
onDestinationSelected: (index) {
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
});
|
||||
if (!widget.isExampleBar) widget.onSelectItem!(index);
|
||||
},
|
||||
destinations:
|
||||
widget.isExampleBar ? exampleBarDestinations : appBarDestinations,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NavigationRailSection extends StatefulWidget {
|
||||
final void Function(int) onSelectItem;
|
||||
final int selectedIndex;
|
||||
|
||||
const NavigationRailSection(
|
||||
{Key? key, required this.onSelectItem, required this.selectedIndex})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<NavigationRailSection> createState() => _NavigationRailSectionState();
|
||||
}
|
||||
|
||||
class _NavigationRailSectionState extends State<NavigationRailSection> {
|
||||
int _selectedIndex = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_selectedIndex = widget.selectedIndex;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return NavigationRail(
|
||||
minWidth: 50,
|
||||
destinations: navRailDestinations,
|
||||
selectedIndex: _selectedIndex,
|
||||
useIndicator: true,
|
||||
onDestinationSelected: (index) {
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
});
|
||||
widget.onSelectItem(index);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user