mirror of https://github.com/flutter/samples.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
6.1 KiB
216 lines
6.1 KiB
2 years ago
|
// Copyright 2021 The Flutter team. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'color_palettes_screen.dart';
|
||
|
import 'component_screen.dart';
|
||
|
import 'elevation_screen.dart';
|
||
|
import 'typography_screen.dart';
|
||
|
|
||
|
void main() {
|
||
|
runApp(const 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
|
||
|
// screenWidthThreshold; otherwise, NavigationBar is used for navigation.
|
||
|
const double narrowScreenWidthThreshold = 450;
|
||
|
|
||
|
const Color m3BaseColor = Color(0xff6750a4);
|
||
|
const List<Color> colorOptions = [
|
||
|
m3BaseColor,
|
||
|
Colors.blue,
|
||
|
Colors.teal,
|
||
|
Colors.green,
|
||
|
Colors.yellow,
|
||
|
Colors.orange,
|
||
|
Colors.pink
|
||
|
];
|
||
|
const List<String> colorText = <String>[
|
||
|
'M3 Baseline',
|
||
|
'Blue',
|
||
|
'Teal',
|
||
|
'Green',
|
||
|
'Yellow',
|
||
|
'Orange',
|
||
|
'Pink',
|
||
|
];
|
||
|
|
||
|
enum ScreenSelected {
|
||
|
component(0),
|
||
|
color(1),
|
||
|
typography(2),
|
||
|
elevation(3);
|
||
|
|
||
|
const ScreenSelected(this.value);
|
||
|
final int value;
|
||
|
}
|
||
|
|
||
|
class _Material3DemoState extends State<Material3Demo> {
|
||
|
bool useMaterial3 = true;
|
||
|
bool useLightMode = true;
|
||
|
int colorSelected = 0;
|
||
|
int screenIndex = ScreenSelected.component.value;
|
||
|
|
||
|
late ThemeData themeData;
|
||
|
|
||
|
@override
|
||
|
initState() {
|
||
|
super.initState();
|
||
|
themeData = updateThemes(colorSelected, useMaterial3, useLightMode);
|
||
|
}
|
||
|
|
||
|
ThemeData updateThemes(int colorIndex, bool useMaterial3, bool useLightMode) {
|
||
|
return ThemeData(
|
||
|
colorSchemeSeed: colorOptions[colorSelected],
|
||
|
useMaterial3: useMaterial3,
|
||
|
brightness: useLightMode ? Brightness.light : Brightness.dark);
|
||
|
}
|
||
|
|
||
|
void handleScreenChanged(int screenSelected) {
|
||
|
setState(() {
|
||
|
screenIndex = screenSelected;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
void handleBrightnessChange() {
|
||
|
setState(() {
|
||
|
useLightMode = !useLightMode;
|
||
|
themeData = updateThemes(colorSelected, useMaterial3, useLightMode);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
void handleMaterialVersionChange() {
|
||
|
setState(() {
|
||
|
useMaterial3 = !useMaterial3;
|
||
|
themeData = updateThemes(colorSelected, useMaterial3, useLightMode);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
void handleColorSelect(int value) {
|
||
|
setState(() {
|
||
|
colorSelected = value;
|
||
|
themeData = updateThemes(colorSelected, useMaterial3, useLightMode);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
Widget createScreenFor(
|
||
|
ScreenSelected screenSelected, bool showNavBarExample) {
|
||
|
switch (screenSelected) {
|
||
|
case ScreenSelected.component:
|
||
|
return ComponentScreen(showNavBottomBar: showNavBarExample);
|
||
|
case ScreenSelected.color:
|
||
|
return const ColorPalettesScreen();
|
||
|
case ScreenSelected.typography:
|
||
|
return const TypographyScreen();
|
||
|
case ScreenSelected.elevation:
|
||
|
return const ElevationScreen();
|
||
|
default:
|
||
|
return ComponentScreen(showNavBottomBar: showNavBarExample);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PreferredSizeWidget createAppBar() {
|
||
|
return AppBar(
|
||
|
title: useMaterial3 ? const Text('Material 3') : const Text('Material 2'),
|
||
|
actions: [
|
||
|
IconButton(
|
||
|
icon: useLightMode
|
||
|
? const Icon(Icons.wb_sunny_outlined)
|
||
|
: const Icon(Icons.wb_sunny),
|
||
|
onPressed: handleBrightnessChange,
|
||
|
tooltip: 'Toggle brightness',
|
||
|
),
|
||
|
IconButton(
|
||
|
icon: useMaterial3
|
||
|
? const Icon(Icons.filter_3)
|
||
|
: const Icon(Icons.filter_2),
|
||
|
onPressed: handleMaterialVersionChange,
|
||
|
tooltip: 'Switch to Material ${useMaterial3 ? 2 : 3}',
|
||
|
),
|
||
|
PopupMenuButton(
|
||
|
icon: const Icon(Icons.more_vert),
|
||
|
shape:
|
||
|
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||
|
itemBuilder: (context) {
|
||
|
return List.generate(colorOptions.length, (index) {
|
||
|
return PopupMenuItem(
|
||
|
value: index,
|
||
|
child: Wrap(
|
||
|
children: [
|
||
|
Padding(
|
||
|
padding: const EdgeInsets.only(left: 10),
|
||
|
child: Icon(
|
||
|
index == colorSelected
|
||
|
? Icons.color_lens
|
||
|
: Icons.color_lens_outlined,
|
||
|
color: colorOptions[index],
|
||
|
),
|
||
|
),
|
||
|
Padding(
|
||
|
padding: const EdgeInsets.only(left: 20),
|
||
|
child: Text(colorText[index]),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
);
|
||
|
});
|
||
|
},
|
||
|
onSelected: handleColorSelect,
|
||
|
),
|
||
|
],
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return MaterialApp(
|
||
|
debugShowCheckedModeBanner: false,
|
||
|
title: 'Material 3',
|
||
|
themeMode: useLightMode ? ThemeMode.light : ThemeMode.dark,
|
||
|
theme: themeData,
|
||
|
home: LayoutBuilder(builder: (context, constraints) {
|
||
|
if (constraints.maxWidth < narrowScreenWidthThreshold) {
|
||
|
return Scaffold(
|
||
|
appBar: createAppBar(),
|
||
|
body: Row(children: <Widget>[
|
||
|
createScreenFor(ScreenSelected.values[screenIndex], false),
|
||
|
]),
|
||
|
bottomNavigationBar: NavigationBars(
|
||
|
onSelectItem: handleScreenChanged,
|
||
|
selectedIndex: screenIndex,
|
||
|
isExampleBar: false,
|
||
|
),
|
||
|
);
|
||
|
} else {
|
||
|
return Scaffold(
|
||
|
appBar: createAppBar(),
|
||
|
body: SafeArea(
|
||
|
bottom: false,
|
||
|
top: false,
|
||
|
child: Row(
|
||
|
children: <Widget>[
|
||
|
Padding(
|
||
|
padding: const EdgeInsets.symmetric(horizontal: 5),
|
||
|
child: NavigationRailSection(
|
||
|
onSelectItem: handleScreenChanged,
|
||
|
selectedIndex: screenIndex)),
|
||
|
const VerticalDivider(thickness: 1, width: 1),
|
||
|
createScreenFor(ScreenSelected.values[screenIndex], true),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}),
|
||
|
);
|
||
|
}
|
||
|
}
|