1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'package:flutter/material.dart';
6
7void main() {
8 runApp(const ThemeDataExampleApp());
9}
10
11// This app's theme specifies an overall ColorScheme as well as overrides
12// for the default configuration of FloatingActionButtons. To customize
13// the appearance of other components, add additional component specific
14// themes, rather than tweaking the color scheme.
15//
16// Creating an entire color scheme from a single seed color is a good
17// way to ensure a visually appealing color palette where the default
18// component colors have sufficient contrast for accessibility. Another
19// good way to create an app's color scheme is to use
20// ColorScheme.fromImageProvider.
21//
22// The color scheme reflects the platform's light or dark setting
23// which is retrieved with `MediaQuery.platformBrightnessOf`. The color
24// scheme's colors will be different for light and dark settings although
25// they'll all be related to the seed color in both cases.
26//
27// Color scheme colors have been used where component defaults have
28// been overridden so that the app will look good and remain accessible
29// in both light and dark modes.
30//
31// Text styles are derived from the theme's textTheme (not the obsolete
32// primaryTextTheme property) and then customized using copyWith.
33// Using the _on_ version of a color scheme color as the foreground,
34// as in `tertiary` and `onTertiary`, guarantees sufficient contrast
35// for readability/accessibility.
36
37class ThemeDataExampleApp extends StatelessWidget {
38 const ThemeDataExampleApp({super.key});
39
40 @override
41 Widget build(BuildContext context) {
42 final ColorScheme colorScheme = ColorScheme.fromSeed(
43 brightness: MediaQuery.platformBrightnessOf(context),
44 seedColor: Colors.indigo,
45 );
46 return MaterialApp(
47 title: 'ThemeData Demo',
48 theme: ThemeData(
49 colorScheme: colorScheme,
50 floatingActionButtonTheme: FloatingActionButtonThemeData(
51 backgroundColor: colorScheme.tertiary,
52 foregroundColor: colorScheme.onTertiary,
53 ),
54 ),
55 home: const Home(),
56 );
57 }
58}
59
60class Home extends StatefulWidget {
61 const Home({super.key});
62
63 @override
64 State<Home> createState() => _HomeState();
65}
66
67class _HomeState extends State<Home> {
68 int buttonPressCount = 0;
69
70 @override
71 Widget build(BuildContext context) {
72 final ThemeData theme = Theme.of(context);
73 final ColorScheme colorScheme = theme.colorScheme;
74 final double pointCount = 8 + (buttonPressCount % 6);
75
76 return Scaffold(
77 appBar: AppBar(title: const Text('Press the + Button')),
78 // An AnimatedContainer makes the decoration changes entertaining.
79 body: AnimatedContainer(
80 duration: const Duration(milliseconds: 500),
81 margin: const EdgeInsets.all(32),
82 alignment: Alignment.center,
83 decoration: ShapeDecoration(
84 color: colorScheme.tertiaryContainer,
85 shape: StarBorder(
86 points: pointCount,
87 pointRounding: 0.4,
88 valleyRounding: 0.6,
89 side: BorderSide(width: 9, color: colorScheme.tertiary),
90 ),
91 ),
92 child: Text(
93 '${pointCount.toInt()} Points',
94 style: theme.textTheme.headlineMedium!.copyWith(color: colorScheme.onPrimaryContainer),
95 ),
96 ),
97 floatingActionButton: FloatingActionButton(
98 onPressed: () {
99 setState(() {
100 buttonPressCount += 1;
101 });
102 },
103 tooltip: "Change the shape's point count",
104 child: const Icon(Icons.add),
105 ),
106 );
107 }
108}
109