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.
samples/material_3_demo/lib/color_palettes_screen.dart

387 lines
11 KiB

// 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/gestures.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
const Widget divider = SizedBox(height: 10);
// If screen content width is greater or equal to this value, the light and dark
// color schemes will be displayed in a column. Otherwise, they will
// be displayed in a row.
const double narrowScreenWidthThreshold = 400;
class ColorPalettesScreen extends StatelessWidget {
const ColorPalettesScreen({super.key});
@override
Widget build(BuildContext context) {
Color selectedColor = Theme.of(context).primaryColor;
ThemeData lightTheme = ThemeData(
colorSchemeSeed: selectedColor,
brightness: Brightness.light,
);
ThemeData darkTheme = ThemeData(
colorSchemeSeed: selectedColor,
brightness: Brightness.dark,
);
Widget schemeLabel(String brightness) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 15),
child: Text(
brightness,
style: const TextStyle(fontWeight: FontWeight.bold),
),
);
}
Widget schemeView(ThemeData theme) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: ColorSchemeView(
colorScheme: theme.colorScheme,
),
);
}
Widget dynamicColorNotice() => RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: Theme.of(context).textTheme.bodySmall,
children: [
const TextSpan(
text: 'To create color schemes based on a '
'platform\'s implementation of dynamic color, '
'use the '),
TextSpan(
text: 'dynamic_color',
style: const TextStyle(decoration: TextDecoration.underline),
recognizer: TapGestureRecognizer()
..onTap = () async {
final url = Uri.parse(
'https://pub.dev/packages/dynamic_color',
);
if (!await launchUrl(url)) {
throw Exception('Could not launch $url');
}
},
),
const TextSpan(text: ' package.'),
],
),
);
return Expanded(
child: LayoutBuilder(builder: (context, constraints) {
if (constraints.maxWidth < narrowScreenWidthThreshold) {
return SingleChildScrollView(
child: Column(
children: [
dynamicColorNotice(),
divider,
schemeLabel('Light ColorScheme'),
schemeView(lightTheme),
divider,
divider,
schemeLabel('Dark ColorScheme'),
schemeView(darkTheme),
],
),
);
} else {
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(top: 5),
child: Column(
children: [
dynamicColorNotice(),
Row(
children: [
Expanded(
child: Column(
children: [
schemeLabel('Light ColorScheme'),
schemeView(lightTheme),
],
),
),
Expanded(
child: Column(
children: [
schemeLabel('Dark ColorScheme'),
schemeView(darkTheme),
],
),
),
],
),
],
),
),
);
}
}),
);
}
}
class ColorSchemeView extends StatelessWidget {
const ColorSchemeView({super.key, required this.colorScheme});
final ColorScheme colorScheme;
@override
Widget build(BuildContext context) {
return Column(
children: [
ColorGroup(
children: [
ColorChip(
label: 'primary',
color: colorScheme.primary,
onColor: colorScheme.onPrimary,
),
ColorChip(
label: 'onPrimary',
color: colorScheme.onPrimary,
onColor: colorScheme.primary,
),
ColorChip(
label: 'primaryContainer',
color: colorScheme.primaryContainer,
onColor: colorScheme.onPrimaryContainer,
),
ColorChip(
label: 'onPrimaryContainer',
color: colorScheme.onPrimaryContainer,
onColor: colorScheme.primaryContainer,
),
],
),
divider,
ColorGroup(
children: [
ColorChip(
label: 'secondary',
color: colorScheme.secondary,
onColor: colorScheme.onSecondary,
),
ColorChip(
label: 'onSecondary',
color: colorScheme.onSecondary,
onColor: colorScheme.secondary,
),
ColorChip(
label: 'secondaryContainer',
color: colorScheme.secondaryContainer,
onColor: colorScheme.onSecondaryContainer,
),
ColorChip(
label: 'onSecondaryContainer',
color: colorScheme.onSecondaryContainer,
onColor: colorScheme.secondaryContainer,
),
],
),
divider,
ColorGroup(
children: [
ColorChip(
label: 'tertiary',
color: colorScheme.tertiary,
onColor: colorScheme.onTertiary,
),
ColorChip(
label: 'onTertiary',
color: colorScheme.onTertiary,
onColor: colorScheme.tertiary,
),
ColorChip(
label: 'tertiaryContainer',
color: colorScheme.tertiaryContainer,
onColor: colorScheme.onTertiaryContainer,
),
ColorChip(
label: 'onTertiaryContainer',
color: colorScheme.onTertiaryContainer,
onColor: colorScheme.tertiaryContainer,
),
],
),
divider,
ColorGroup(
children: [
ColorChip(
label: 'error',
color: colorScheme.error,
onColor: colorScheme.onError,
),
ColorChip(
label: 'onError',
color: colorScheme.onError,
onColor: colorScheme.error,
),
ColorChip(
label: 'errorContainer',
color: colorScheme.errorContainer,
onColor: colorScheme.onErrorContainer,
),
ColorChip(
label: 'onErrorContainer',
color: colorScheme.onErrorContainer,
onColor: colorScheme.errorContainer,
),
],
),
divider,
ColorGroup(
children: [
ColorChip(
label: 'surface',
color: colorScheme.surface,
onColor: colorScheme.onSurface,
),
ColorChip(
label: 'onSurface',
color: colorScheme.onSurface,
onColor: colorScheme.surface,
),
ColorChip(
label: 'surfaceVariant',
color: colorScheme.surfaceVariant,
onColor: colorScheme.onSurfaceVariant,
),
ColorChip(
label: 'onSurfaceVariant',
color: colorScheme.onSurfaceVariant,
onColor: colorScheme.surfaceVariant,
),
ColorChip(
label: 'surfaceTint',
color: colorScheme.surfaceTint,
),
],
),
divider,
ColorGroup(
children: [
ColorChip(
label: 'outline',
color: colorScheme.outline,
),
ColorChip(
label: 'outlineVariant',
color: colorScheme.outlineVariant,
),
],
),
divider,
ColorGroup(
children: [
ColorChip(
label: 'inverseSurface',
color: colorScheme.inverseSurface,
onColor: colorScheme.onInverseSurface,
),
ColorChip(
label: 'onInverseSurface',
color: colorScheme.onInverseSurface,
onColor: colorScheme.inverseSurface,
),
ColorChip(
label: 'inversePrimary',
color: colorScheme.inversePrimary,
onColor: colorScheme.primary,
),
],
),
divider,
ColorGroup(
children: [
ColorChip(
label: 'background',
color: colorScheme.background,
onColor: colorScheme.onBackground,
),
ColorChip(
label: 'onBackground',
color: colorScheme.onBackground,
onColor: colorScheme.background,
),
ColorChip(
label: 'scrim',
color: colorScheme.scrim,
),
ColorChip(
label: 'shadow',
color: colorScheme.shadow,
),
],
),
divider,
],
);
}
}
class ColorGroup extends StatelessWidget {
const ColorGroup({super.key, required this.children});
final List<Widget> children;
@override
Widget build(BuildContext context) {
return RepaintBoundary(
child: Card(
clipBehavior: Clip.antiAlias,
child: Column(
children: children,
),
),
);
}
}
class ColorChip extends StatelessWidget {
const ColorChip({
super.key,
required this.color,
required this.label,
this.onColor,
});
final Color color;
final Color? onColor;
final String label;
static Color contrastColor(Color color) {
final brightness = ThemeData.estimateBrightnessForColor(color);
switch (brightness) {
case Brightness.dark:
return Colors.white;
case Brightness.light:
return Colors.black;
}
}
@override
Widget build(BuildContext context) {
final Color labelColor = onColor ?? contrastColor(color);
return Container(
color: color,
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
Expanded(child: Text(label, style: TextStyle(color: labelColor))),
],
),
),
);
}
}