mirror of
https://github.com/flutter/samples.git
synced 2025-11-08 13:58:47 +00:00
Improvements to M3 demo app (#1630)
This commit is contained in:
@@ -26,25 +26,28 @@ class FirstComponentList extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView(
|
// Fully traverse this list before moving on.
|
||||||
padding: showSecondList
|
return FocusTraversalGroup(
|
||||||
? const EdgeInsetsDirectional.only(end: smallSpacing)
|
child: ListView(
|
||||||
: EdgeInsets.zero,
|
padding: showSecondList
|
||||||
children: [
|
? const EdgeInsetsDirectional.only(end: smallSpacing)
|
||||||
const Actions(),
|
: EdgeInsets.zero,
|
||||||
colDivider,
|
children: [
|
||||||
const Communication(),
|
const Actions(),
|
||||||
colDivider,
|
|
||||||
const Containment(),
|
|
||||||
if (!showSecondList) ...[
|
|
||||||
colDivider,
|
colDivider,
|
||||||
Navigation(scaffoldKey: scaffoldKey),
|
const Communication(),
|
||||||
colDivider,
|
colDivider,
|
||||||
const Selection(),
|
const Containment(),
|
||||||
colDivider,
|
if (!showSecondList) ...[
|
||||||
const TextInputs()
|
colDivider,
|
||||||
|
Navigation(scaffoldKey: scaffoldKey),
|
||||||
|
colDivider,
|
||||||
|
const Selection(),
|
||||||
|
colDivider,
|
||||||
|
const TextInputs()
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,15 +62,18 @@ class SecondComponentList extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView(
|
// Fully traverse this list before moving on.
|
||||||
padding: const EdgeInsetsDirectional.only(end: smallSpacing),
|
return FocusTraversalGroup(
|
||||||
children: <Widget>[
|
child: ListView(
|
||||||
Navigation(scaffoldKey: scaffoldKey),
|
padding: const EdgeInsetsDirectional.only(end: smallSpacing),
|
||||||
colDivider,
|
children: <Widget>[
|
||||||
const Selection(),
|
Navigation(scaffoldKey: scaffoldKey),
|
||||||
colDivider,
|
colDivider,
|
||||||
const TextInputs(),
|
const Selection(),
|
||||||
],
|
colDivider,
|
||||||
|
const TextInputs(),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1011,13 +1017,13 @@ class NavigationBars extends StatefulWidget {
|
|||||||
this.onSelectItem,
|
this.onSelectItem,
|
||||||
required this.selectedIndex,
|
required this.selectedIndex,
|
||||||
required this.isExampleBar,
|
required this.isExampleBar,
|
||||||
this.isBadgeExample,
|
this.isBadgeExample = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
final void Function(int)? onSelectItem;
|
final void Function(int)? onSelectItem;
|
||||||
final int selectedIndex;
|
final int selectedIndex;
|
||||||
final bool isExampleBar;
|
final bool isExampleBar;
|
||||||
final bool? isBadgeExample;
|
final bool isBadgeExample;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<NavigationBars> createState() => _NavigationBarsState();
|
State<NavigationBars> createState() => _NavigationBarsState();
|
||||||
@@ -1042,23 +1048,26 @@ class _NavigationBarsState extends State<NavigationBars> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool isBadgeExample = widget.isBadgeExample ?? false;
|
// App NavigationBar should get first focus.
|
||||||
Widget navigationBar = NavigationBar(
|
Widget navigationBar = Focus(
|
||||||
selectedIndex: selectedIndex,
|
autofocus: !widget.isBadgeExample,
|
||||||
onDestinationSelected: (index) {
|
child: NavigationBar(
|
||||||
setState(() {
|
selectedIndex: selectedIndex,
|
||||||
selectedIndex = index;
|
onDestinationSelected: (index) {
|
||||||
});
|
setState(() {
|
||||||
if (!widget.isExampleBar) widget.onSelectItem!(index);
|
selectedIndex = index;
|
||||||
},
|
});
|
||||||
destinations: widget.isExampleBar && isBadgeExample
|
if (!widget.isExampleBar) widget.onSelectItem!(index);
|
||||||
? barWithBadgeDestinations
|
},
|
||||||
: widget.isExampleBar
|
destinations: widget.isExampleBar && widget.isBadgeExample
|
||||||
? exampleBarDestinations
|
? barWithBadgeDestinations
|
||||||
: appBarDestinations,
|
: widget.isExampleBar
|
||||||
|
? exampleBarDestinations
|
||||||
|
: appBarDestinations,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (widget.isExampleBar && isBadgeExample) {
|
if (widget.isExampleBar && widget.isBadgeExample) {
|
||||||
navigationBar = ComponentDecoration(
|
navigationBar = ComponentDecoration(
|
||||||
label: 'Badges',
|
label: 'Badges',
|
||||||
tooltipMessage: 'Use Badge or Badge.count',
|
tooltipMessage: 'Use Badge or Badge.count',
|
||||||
@@ -1553,8 +1562,6 @@ class _BottomSheetSectionState extends State<BottomSheetSection> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
showModalBottomSheet<void>(
|
showModalBottomSheet<void>(
|
||||||
context: context,
|
context: context,
|
||||||
// TODO: Remove when this is in the framework https://github.com/flutter/flutter/issues/118619
|
|
||||||
constraints: const BoxConstraints(maxWidth: 640),
|
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 150,
|
height: 150,
|
||||||
@@ -1594,8 +1601,6 @@ class _BottomSheetSectionState extends State<BottomSheetSection> {
|
|||||||
_nonModalBottomSheetController = showBottomSheet<void>(
|
_nonModalBottomSheetController = showBottomSheet<void>(
|
||||||
elevation: 8.0,
|
elevation: 8.0,
|
||||||
context: context,
|
context: context,
|
||||||
// TODO: Remove when this is in the framework https://github.com/flutter/flutter/issues/118619
|
|
||||||
constraints: const BoxConstraints(maxWidth: 640),
|
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 150,
|
height: 150,
|
||||||
@@ -2188,7 +2193,7 @@ class _SlidersState extends State<Sliders> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComponentDecoration extends StatelessWidget {
|
class ComponentDecoration extends StatefulWidget {
|
||||||
const ComponentDecoration({
|
const ComponentDecoration({
|
||||||
super.key,
|
super.key,
|
||||||
required this.label,
|
required this.label,
|
||||||
@@ -2200,6 +2205,13 @@ class ComponentDecoration extends StatelessWidget {
|
|||||||
final Widget child;
|
final Widget child;
|
||||||
final String? tooltipMessage;
|
final String? tooltipMessage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ComponentDecoration> createState() => _ComponentDecorationState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ComponentDecorationState extends State<ComponentDecoration> {
|
||||||
|
final focusNode = FocusNode();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return RepaintBoundary(
|
return RepaintBoundary(
|
||||||
@@ -2210,9 +2222,10 @@ class ComponentDecoration extends StatelessWidget {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(label, style: Theme.of(context).textTheme.titleSmall),
|
Text(widget.label,
|
||||||
|
style: Theme.of(context).textTheme.titleSmall),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: tooltipMessage,
|
message: widget.tooltipMessage,
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 5.0),
|
padding: EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
child: Icon(Icons.info_outline, size: 16)),
|
child: Icon(Icons.info_outline, size: 16)),
|
||||||
@@ -2222,18 +2235,32 @@ class ComponentDecoration extends StatelessWidget {
|
|||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints:
|
constraints:
|
||||||
const BoxConstraints.tightFor(width: widthConstraint),
|
const BoxConstraints.tightFor(width: widthConstraint),
|
||||||
child: Card(
|
// Tapping within the a component card should request focus
|
||||||
elevation: 0,
|
// for that component's children.
|
||||||
shape: RoundedRectangleBorder(
|
child: Focus(
|
||||||
side: BorderSide(
|
focusNode: focusNode,
|
||||||
color: Theme.of(context).colorScheme.outlineVariant,
|
canRequestFocus: true,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTapDown: (_) {
|
||||||
|
focusNode.requestFocus();
|
||||||
|
},
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
child: Card(
|
||||||
|
elevation: 0,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
side: BorderSide(
|
||||||
|
color: Theme.of(context).colorScheme.outlineVariant,
|
||||||
|
),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 5.0, vertical: 20.0),
|
||||||
|
child: Center(
|
||||||
|
child: widget.child,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 5.0, vertical: 20.0),
|
|
||||||
child: Center(child: child),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -2253,19 +2280,22 @@ class ComponentGroupDecoration extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Card(
|
// Fully traverse this component group before moving on
|
||||||
margin: EdgeInsets.zero,
|
return FocusTraversalGroup(
|
||||||
elevation: 0,
|
child: Card(
|
||||||
color: Theme.of(context).colorScheme.surfaceVariant.withOpacity(0.3),
|
margin: EdgeInsets.zero,
|
||||||
child: Padding(
|
elevation: 0,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 20.0),
|
color: Theme.of(context).colorScheme.surfaceVariant.withOpacity(0.3),
|
||||||
child: Center(
|
child: Padding(
|
||||||
child: Column(
|
padding: const EdgeInsets.symmetric(vertical: 20.0),
|
||||||
children: [
|
child: Center(
|
||||||
Text(label, style: Theme.of(context).textTheme.titleLarge),
|
child: Column(
|
||||||
colDivider,
|
children: [
|
||||||
...children
|
Text(label, style: Theme.of(context).textTheme.titleLarge),
|
||||||
],
|
colDivider,
|
||||||
|
...children
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -12,24 +12,17 @@ import 'typography_screen.dart';
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(
|
runApp(
|
||||||
const MaterialApp(
|
const Material3Demo(),
|
||||||
debugShowCheckedModeBanner: false,
|
|
||||||
home: Material3Demo(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Material3Demo extends StatefulWidget {
|
|
||||||
const Material3Demo({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<Material3Demo> createState() => _Material3DemoState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// NavigationRail shows if the screen width is greater or equal to
|
// NavigationRail shows if the screen width is greater or equal to
|
||||||
// screenWidthThreshold; otherwise, NavigationBar is used for navigation.
|
// narrowScreenWidthThreshold; otherwise, NavigationBar is used for navigation.
|
||||||
const double narrowScreenWidthThreshold = 450;
|
const double narrowScreenWidthThreshold = 450;
|
||||||
|
|
||||||
|
const double mediumWidthBreakpoint = 1000;
|
||||||
|
const double largeWidthBreakpoint = 5000;
|
||||||
|
|
||||||
const double transitionLength = 500;
|
const double transitionLength = 500;
|
||||||
|
|
||||||
enum ColorSeed {
|
enum ColorSeed {
|
||||||
@@ -58,6 +51,13 @@ enum ScreenSelected {
|
|||||||
final int value;
|
final int value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Material3Demo extends StatefulWidget {
|
||||||
|
const Material3Demo({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<Material3Demo> createState() => _Material3DemoState();
|
||||||
|
}
|
||||||
|
|
||||||
class _Material3DemoState extends State<Material3Demo>
|
class _Material3DemoState extends State<Material3Demo>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
@@ -109,8 +109,8 @@ class _Material3DemoState extends State<Material3Demo>
|
|||||||
|
|
||||||
final double width = MediaQuery.of(context).size.width;
|
final double width = MediaQuery.of(context).size.width;
|
||||||
final AnimationStatus status = controller.status;
|
final AnimationStatus status = controller.status;
|
||||||
if (width > 1000) {
|
if (width > mediumWidthBreakpoint) {
|
||||||
if (width > 1500) {
|
if (width > largeWidthBreakpoint) {
|
||||||
showMediumSizeLayout = false;
|
showMediumSizeLayout = false;
|
||||||
showLargeSizeLayout = true;
|
showLargeSizeLayout = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -131,7 +131,7 @@ class _Material3DemoState extends State<Material3Demo>
|
|||||||
}
|
}
|
||||||
if (!controllerInitialized) {
|
if (!controllerInitialized) {
|
||||||
controllerInitialized = true;
|
controllerInitialized = true;
|
||||||
controller.value = width > 1000 ? 1 : 0;
|
controller.value = width > mediumWidthBreakpoint ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,7 +710,7 @@ class _OneTwoTransitionState extends State<OneTwoTransition> {
|
|||||||
|
|
||||||
widthAnimation = Tween<double>(
|
widthAnimation = Tween<double>(
|
||||||
begin: 0,
|
begin: 0,
|
||||||
end: 1000,
|
end: mediumWidthBreakpoint,
|
||||||
).animate(SizeAnimation(widget.animation));
|
).animate(SizeAnimation(widget.animation));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,7 +719,7 @@ class _OneTwoTransitionState extends State<OneTwoTransition> {
|
|||||||
return Row(
|
return Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Flexible(
|
Flexible(
|
||||||
flex: 1000,
|
flex: mediumWidthBreakpoint.toInt(),
|
||||||
child: widget.one,
|
child: widget.one,
|
||||||
),
|
),
|
||||||
if (widthAnimation.value.toInt() > 0) ...[
|
if (widthAnimation.value.toInt() > 0) ...[
|
||||||
|
|||||||
@@ -26,25 +26,28 @@ class FirstComponentList extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView(
|
// Fully traverse this list before moving on.
|
||||||
padding: showSecondList
|
return FocusTraversalGroup(
|
||||||
? const EdgeInsetsDirectional.only(end: smallSpacing)
|
child: ListView(
|
||||||
: EdgeInsets.zero,
|
padding: showSecondList
|
||||||
children: [
|
? const EdgeInsetsDirectional.only(end: smallSpacing)
|
||||||
const Actions(),
|
: EdgeInsets.zero,
|
||||||
colDivider,
|
children: [
|
||||||
const Communication(),
|
const Actions(),
|
||||||
colDivider,
|
|
||||||
const Containment(),
|
|
||||||
if (!showSecondList) ...[
|
|
||||||
colDivider,
|
colDivider,
|
||||||
Navigation(scaffoldKey: scaffoldKey),
|
const Communication(),
|
||||||
colDivider,
|
colDivider,
|
||||||
const Selection(),
|
const Containment(),
|
||||||
colDivider,
|
if (!showSecondList) ...[
|
||||||
const TextInputs()
|
colDivider,
|
||||||
|
Navigation(scaffoldKey: scaffoldKey),
|
||||||
|
colDivider,
|
||||||
|
const Selection(),
|
||||||
|
colDivider,
|
||||||
|
const TextInputs()
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,15 +62,18 @@ class SecondComponentList extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView(
|
// Fully traverse this list before moving on.
|
||||||
padding: const EdgeInsetsDirectional.only(end: smallSpacing),
|
return FocusTraversalGroup(
|
||||||
children: <Widget>[
|
child: ListView(
|
||||||
Navigation(scaffoldKey: scaffoldKey),
|
padding: const EdgeInsetsDirectional.only(end: smallSpacing),
|
||||||
colDivider,
|
children: <Widget>[
|
||||||
const Selection(),
|
Navigation(scaffoldKey: scaffoldKey),
|
||||||
colDivider,
|
colDivider,
|
||||||
const TextInputs(),
|
const Selection(),
|
||||||
],
|
colDivider,
|
||||||
|
const TextInputs(),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1011,13 +1017,13 @@ class NavigationBars extends StatefulWidget {
|
|||||||
this.onSelectItem,
|
this.onSelectItem,
|
||||||
required this.selectedIndex,
|
required this.selectedIndex,
|
||||||
required this.isExampleBar,
|
required this.isExampleBar,
|
||||||
this.isBadgeExample,
|
this.isBadgeExample = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
final void Function(int)? onSelectItem;
|
final void Function(int)? onSelectItem;
|
||||||
final int selectedIndex;
|
final int selectedIndex;
|
||||||
final bool isExampleBar;
|
final bool isExampleBar;
|
||||||
final bool? isBadgeExample;
|
final bool isBadgeExample;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<NavigationBars> createState() => _NavigationBarsState();
|
State<NavigationBars> createState() => _NavigationBarsState();
|
||||||
@@ -1042,23 +1048,26 @@ class _NavigationBarsState extends State<NavigationBars> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool isBadgeExample = widget.isBadgeExample ?? false;
|
// App NavigationBar should get first focus.
|
||||||
Widget navigationBar = NavigationBar(
|
Widget navigationBar = Focus(
|
||||||
selectedIndex: selectedIndex,
|
autofocus: !widget.isBadgeExample,
|
||||||
onDestinationSelected: (index) {
|
child: NavigationBar(
|
||||||
setState(() {
|
selectedIndex: selectedIndex,
|
||||||
selectedIndex = index;
|
onDestinationSelected: (index) {
|
||||||
});
|
setState(() {
|
||||||
if (!widget.isExampleBar) widget.onSelectItem!(index);
|
selectedIndex = index;
|
||||||
},
|
});
|
||||||
destinations: widget.isExampleBar && isBadgeExample
|
if (!widget.isExampleBar) widget.onSelectItem!(index);
|
||||||
? barWithBadgeDestinations
|
},
|
||||||
: widget.isExampleBar
|
destinations: widget.isExampleBar && widget.isBadgeExample
|
||||||
? exampleBarDestinations
|
? barWithBadgeDestinations
|
||||||
: appBarDestinations,
|
: widget.isExampleBar
|
||||||
|
? exampleBarDestinations
|
||||||
|
: appBarDestinations,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (widget.isExampleBar && isBadgeExample) {
|
if (widget.isExampleBar && widget.isBadgeExample) {
|
||||||
navigationBar = ComponentDecoration(
|
navigationBar = ComponentDecoration(
|
||||||
label: 'Badges',
|
label: 'Badges',
|
||||||
tooltipMessage: 'Use Badge or Badge.count',
|
tooltipMessage: 'Use Badge or Badge.count',
|
||||||
@@ -1553,8 +1562,6 @@ class _BottomSheetSectionState extends State<BottomSheetSection> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
showModalBottomSheet<void>(
|
showModalBottomSheet<void>(
|
||||||
context: context,
|
context: context,
|
||||||
// TODO: Remove when this is in the framework https://github.com/flutter/flutter/issues/118619
|
|
||||||
constraints: const BoxConstraints(maxWidth: 640),
|
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 150,
|
height: 150,
|
||||||
@@ -1594,8 +1601,6 @@ class _BottomSheetSectionState extends State<BottomSheetSection> {
|
|||||||
_nonModalBottomSheetController = showBottomSheet<void>(
|
_nonModalBottomSheetController = showBottomSheet<void>(
|
||||||
elevation: 8.0,
|
elevation: 8.0,
|
||||||
context: context,
|
context: context,
|
||||||
// TODO: Remove when this is in the framework https://github.com/flutter/flutter/issues/118619
|
|
||||||
constraints: const BoxConstraints(maxWidth: 640),
|
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 150,
|
height: 150,
|
||||||
@@ -2188,7 +2193,7 @@ class _SlidersState extends State<Sliders> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComponentDecoration extends StatelessWidget {
|
class ComponentDecoration extends StatefulWidget {
|
||||||
const ComponentDecoration({
|
const ComponentDecoration({
|
||||||
super.key,
|
super.key,
|
||||||
required this.label,
|
required this.label,
|
||||||
@@ -2200,6 +2205,13 @@ class ComponentDecoration extends StatelessWidget {
|
|||||||
final Widget child;
|
final Widget child;
|
||||||
final String? tooltipMessage;
|
final String? tooltipMessage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ComponentDecoration> createState() => _ComponentDecorationState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ComponentDecorationState extends State<ComponentDecoration> {
|
||||||
|
final focusNode = FocusNode();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return RepaintBoundary(
|
return RepaintBoundary(
|
||||||
@@ -2210,9 +2222,10 @@ class ComponentDecoration extends StatelessWidget {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(label, style: Theme.of(context).textTheme.titleSmall),
|
Text(widget.label,
|
||||||
|
style: Theme.of(context).textTheme.titleSmall),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: tooltipMessage,
|
message: widget.tooltipMessage,
|
||||||
child: const Padding(
|
child: const Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 5.0),
|
padding: EdgeInsets.symmetric(horizontal: 5.0),
|
||||||
child: Icon(Icons.info_outline, size: 16)),
|
child: Icon(Icons.info_outline, size: 16)),
|
||||||
@@ -2222,18 +2235,32 @@ class ComponentDecoration extends StatelessWidget {
|
|||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints:
|
constraints:
|
||||||
const BoxConstraints.tightFor(width: widthConstraint),
|
const BoxConstraints.tightFor(width: widthConstraint),
|
||||||
child: Card(
|
// Tapping within the a component card should request focus
|
||||||
elevation: 0,
|
// for that component's children.
|
||||||
shape: RoundedRectangleBorder(
|
child: Focus(
|
||||||
side: BorderSide(
|
focusNode: focusNode,
|
||||||
color: Theme.of(context).colorScheme.outlineVariant,
|
canRequestFocus: true,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTapDown: (_) {
|
||||||
|
focusNode.requestFocus();
|
||||||
|
},
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
child: Card(
|
||||||
|
elevation: 0,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
side: BorderSide(
|
||||||
|
color: Theme.of(context).colorScheme.outlineVariant,
|
||||||
|
),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 5.0, vertical: 20.0),
|
||||||
|
child: Center(
|
||||||
|
child: widget.child,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 5.0, vertical: 20.0),
|
|
||||||
child: Center(child: child),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -2253,19 +2280,22 @@ class ComponentGroupDecoration extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Card(
|
// Fully traverse this component group before moving on
|
||||||
margin: EdgeInsets.zero,
|
return FocusTraversalGroup(
|
||||||
elevation: 0,
|
child: Card(
|
||||||
color: Theme.of(context).colorScheme.surfaceVariant.withOpacity(0.3),
|
margin: EdgeInsets.zero,
|
||||||
child: Padding(
|
elevation: 0,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 20.0),
|
color: Theme.of(context).colorScheme.surfaceVariant.withOpacity(0.3),
|
||||||
child: Center(
|
child: Padding(
|
||||||
child: Column(
|
padding: const EdgeInsets.symmetric(vertical: 20.0),
|
||||||
children: [
|
child: Center(
|
||||||
Text(label, style: Theme.of(context).textTheme.titleLarge),
|
child: Column(
|
||||||
colDivider,
|
children: [
|
||||||
...children
|
Text(label, style: Theme.of(context).textTheme.titleLarge),
|
||||||
],
|
colDivider,
|
||||||
|
...children
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -12,24 +12,17 @@ import 'typography_screen.dart';
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(
|
runApp(
|
||||||
const MaterialApp(
|
const Material3Demo(),
|
||||||
debugShowCheckedModeBanner: false,
|
|
||||||
home: Material3Demo(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Material3Demo extends StatefulWidget {
|
|
||||||
const Material3Demo({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<Material3Demo> createState() => _Material3DemoState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// NavigationRail shows if the screen width is greater or equal to
|
// NavigationRail shows if the screen width is greater or equal to
|
||||||
// screenWidthThreshold; otherwise, NavigationBar is used for navigation.
|
// narrowScreenWidthThreshold; otherwise, NavigationBar is used for navigation.
|
||||||
const double narrowScreenWidthThreshold = 450;
|
const double narrowScreenWidthThreshold = 450;
|
||||||
|
|
||||||
|
const double mediumWidthBreakpoint = 1000;
|
||||||
|
const double largeWidthBreakpoint = 5000;
|
||||||
|
|
||||||
const double transitionLength = 500;
|
const double transitionLength = 500;
|
||||||
|
|
||||||
enum ColorSeed {
|
enum ColorSeed {
|
||||||
@@ -58,6 +51,13 @@ enum ScreenSelected {
|
|||||||
final int value;
|
final int value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Material3Demo extends StatefulWidget {
|
||||||
|
const Material3Demo({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<Material3Demo> createState() => _Material3DemoState();
|
||||||
|
}
|
||||||
|
|
||||||
class _Material3DemoState extends State<Material3Demo>
|
class _Material3DemoState extends State<Material3Demo>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
@@ -109,8 +109,8 @@ class _Material3DemoState extends State<Material3Demo>
|
|||||||
|
|
||||||
final double width = MediaQuery.of(context).size.width;
|
final double width = MediaQuery.of(context).size.width;
|
||||||
final AnimationStatus status = controller.status;
|
final AnimationStatus status = controller.status;
|
||||||
if (width > 1000) {
|
if (width > mediumWidthBreakpoint) {
|
||||||
if (width > 1500) {
|
if (width > largeWidthBreakpoint) {
|
||||||
showMediumSizeLayout = false;
|
showMediumSizeLayout = false;
|
||||||
showLargeSizeLayout = true;
|
showLargeSizeLayout = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -131,7 +131,7 @@ class _Material3DemoState extends State<Material3Demo>
|
|||||||
}
|
}
|
||||||
if (!controllerInitialized) {
|
if (!controllerInitialized) {
|
||||||
controllerInitialized = true;
|
controllerInitialized = true;
|
||||||
controller.value = width > 1000 ? 1 : 0;
|
controller.value = width > mediumWidthBreakpoint ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,7 +710,7 @@ class _OneTwoTransitionState extends State<OneTwoTransition> {
|
|||||||
|
|
||||||
widthAnimation = Tween<double>(
|
widthAnimation = Tween<double>(
|
||||||
begin: 0,
|
begin: 0,
|
||||||
end: 1000,
|
end: mediumWidthBreakpoint,
|
||||||
).animate(SizeAnimation(widget.animation));
|
).animate(SizeAnimation(widget.animation));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -719,7 +719,7 @@ class _OneTwoTransitionState extends State<OneTwoTransition> {
|
|||||||
return Row(
|
return Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Flexible(
|
Flexible(
|
||||||
flex: 1000,
|
flex: mediumWidthBreakpoint.toInt(),
|
||||||
child: widget.one,
|
child: widget.one,
|
||||||
),
|
),
|
||||||
if (widthAnimation.value.toInt() > 0) ...[
|
if (widthAnimation.value.toInt() > 0) ...[
|
||||||
|
|||||||
Reference in New Issue
Block a user