Commit 7ac0ce79 authored by Todd Volkert's avatar Todd Volkert

Add API for specifying the system overlay style. (#4422)

Fixes 3544
parent 69ce7f69
...@@ -196,7 +196,7 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> { ...@@ -196,7 +196,7 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
void main() { void main() {
runApp(new MaterialApp( runApp(new MaterialApp(
theme: new ThemeData( theme: new ThemeData(
brightness: ThemeBrightness.light, brightness: Brightness.light,
primarySwatch: Colors.blue, primarySwatch: Colors.blue,
accentColor: Colors.redAccent[200] accentColor: Colors.redAccent[200]
), ),
......
...@@ -145,7 +145,7 @@ void main() { ...@@ -145,7 +145,7 @@ void main() {
runApp(new MaterialApp( runApp(new MaterialApp(
title: 'PageableList', title: 'PageableList',
theme: new ThemeData( theme: new ThemeData(
brightness: ThemeBrightness.light, brightness: Brightness.light,
primarySwatch: Colors.blue, primarySwatch: Colors.blue,
accentColor: Colors.redAccent[200] accentColor: Colors.redAccent[200]
), ),
......
...@@ -160,7 +160,7 @@ class KeyPad extends StatelessWidget { ...@@ -160,7 +160,7 @@ class KeyPad extends StatelessWidget {
return new Theme( return new Theme(
data: new ThemeData( data: new ThemeData(
primarySwatch: Colors.purple, primarySwatch: Colors.purple,
brightness: ThemeBrightness.dark brightness: Brightness.dark
), ),
child: new Flexible( child: new Flexible(
flex: _flex, flex: _flex,
......
...@@ -87,7 +87,7 @@ class ContactsDemoState extends State<ContactsDemo> { ...@@ -87,7 +87,7 @@ class ContactsDemoState extends State<ContactsDemo> {
final double statusBarHeight = MediaQuery.of(context).padding.top; final double statusBarHeight = MediaQuery.of(context).padding.top;
return new Theme( return new Theme(
data: new ThemeData( data: new ThemeData(
brightness: ThemeBrightness.light, brightness: Brightness.light,
primarySwatch: Colors.indigo primarySwatch: Colors.indigo
), ),
child: new Scaffold( child: new Scaffold(
......
...@@ -14,7 +14,7 @@ final Map<double, String> _kLogoImages = <double, String>{ ...@@ -14,7 +14,7 @@ final Map<double, String> _kLogoImages = <double, String>{
170.0: 'packages/flutter_gallery_assets/pesto/logo_big.png', 170.0: 'packages/flutter_gallery_assets/pesto/logo_big.png',
}; };
final ThemeData _kTheme = new ThemeData( final ThemeData _kTheme = new ThemeData(
brightness: ThemeBrightness.light, brightness: Brightness.light,
primarySwatch: Colors.teal, primarySwatch: Colors.teal,
accentColor: Colors.redAccent[200] accentColor: Colors.redAccent[200]
); );
......
...@@ -45,12 +45,12 @@ final Map<String, WidgetBuilder> kRoutes = <String, WidgetBuilder>{ ...@@ -45,12 +45,12 @@ final Map<String, WidgetBuilder> kRoutes = <String, WidgetBuilder>{
}; };
final ThemeData _kGalleryLightTheme = new ThemeData( final ThemeData _kGalleryLightTheme = new ThemeData(
brightness: ThemeBrightness.light, brightness: Brightness.light,
primarySwatch: Colors.purple primarySwatch: Colors.purple
); );
final ThemeData _kGalleryDarkTheme = new ThemeData( final ThemeData _kGalleryDarkTheme = new ThemeData(
brightness: ThemeBrightness.dark, brightness: Brightness.dark,
primarySwatch: Colors.purple primarySwatch: Colors.purple
); );
......
...@@ -66,12 +66,12 @@ class StocksAppState extends State<StocksApp> { ...@@ -66,12 +66,12 @@ class StocksAppState extends State<StocksApp> {
switch (_configuration.stockMode) { switch (_configuration.stockMode) {
case StockMode.optimistic: case StockMode.optimistic:
return new ThemeData( return new ThemeData(
brightness: ThemeBrightness.light, brightness: Brightness.light,
primarySwatch: Colors.purple primarySwatch: Colors.purple
); );
case StockMode.pessimistic: case StockMode.pessimistic:
return new ThemeData( return new ThemeData(
brightness: ThemeBrightness.dark, brightness: Brightness.dark,
accentColor: Colors.redAccent[200] accentColor: Colors.redAccent[200]
); );
} }
......
...@@ -177,6 +177,7 @@ class _MaterialAppState extends State<MaterialApp> { ...@@ -177,6 +177,7 @@ class _MaterialAppState extends State<MaterialApp> {
child: new WidgetsApp( child: new WidgetsApp(
title: config.title, title: config.title,
textStyle: _errorTextStyle, textStyle: _errorTextStyle,
brightness: theme.brightness,
color: theme?.primaryColor ?? Colors.blue[500], // blue[500] is the primary color of the default theme color: theme?.primaryColor ?? Colors.blue[500], // blue[500] is the primary color of the default theme
navigatorObserver: _heroController, navigatorObserver: _heroController,
onGenerateRoute: _onGenerateRoute, onGenerateRoute: _onGenerateRoute,
......
...@@ -129,7 +129,7 @@ class MaterialButton extends StatefulWidget { ...@@ -129,7 +129,7 @@ class MaterialButton extends StatefulWidget {
/// The theme brightness to use for this button. /// The theme brightness to use for this button.
/// ///
/// Defaults to the brightness from [ThemeData.brightness]. /// Defaults to the brightness from [ThemeData.brightness].
final ThemeBrightness colorBrightness; final Brightness colorBrightness;
/// The color scheme to use for this button's text. /// The color scheme to use for this button's text.
/// ///
...@@ -193,7 +193,7 @@ class MaterialButton extends StatefulWidget { ...@@ -193,7 +193,7 @@ class MaterialButton extends StatefulWidget {
class _MaterialButtonState extends State<MaterialButton> { class _MaterialButtonState extends State<MaterialButton> {
bool _highlight = false; bool _highlight = false;
ThemeBrightness get _colorBrightness { Brightness get _colorBrightness {
return config.colorBrightness ?? Theme.of(context).brightness; return config.colorBrightness ?? Theme.of(context).brightness;
} }
...@@ -206,17 +206,17 @@ class _MaterialButtonState extends State<MaterialButton> { ...@@ -206,17 +206,17 @@ class _MaterialButtonState extends State<MaterialButton> {
return Theme.of(context).accentColor; return Theme.of(context).accentColor;
case ButtonTextTheme.normal: case ButtonTextTheme.normal:
switch (_colorBrightness) { switch (_colorBrightness) {
case ThemeBrightness.light: case Brightness.light:
return Colors.black87; return Colors.black87;
case ThemeBrightness.dark: case Brightness.dark:
return Colors.white; return Colors.white;
} }
} }
} else { } else {
switch (_colorBrightness) { switch (_colorBrightness) {
case ThemeBrightness.light: case Brightness.light:
return Colors.black26; return Colors.black26;
case ThemeBrightness.dark: case Brightness.dark:
return Colors.white30; return Colors.white30;
} }
} }
......
...@@ -158,11 +158,11 @@ class _DatePickerHeader extends StatelessWidget { ...@@ -158,11 +158,11 @@ class _DatePickerHeader extends StatelessWidget {
Color dayColor; Color dayColor;
Color yearColor; Color yearColor;
switch(themeData.primaryColorBrightness) { switch(themeData.primaryColorBrightness) {
case ThemeBrightness.light: case Brightness.light:
dayColor = mode == _DatePickerMode.day ? Colors.black87 : Colors.black54; dayColor = mode == _DatePickerMode.day ? Colors.black87 : Colors.black54;
yearColor = mode == _DatePickerMode.year ? Colors.black87 : Colors.black54; yearColor = mode == _DatePickerMode.year ? Colors.black87 : Colors.black54;
break; break;
case ThemeBrightness.dark: case Brightness.dark:
dayColor = mode == _DatePickerMode.day ? Colors.white : Colors.white70; dayColor = mode == _DatePickerMode.day ? Colors.white : Colors.white70;
yearColor = mode == _DatePickerMode.year ? Colors.white : Colors.white70; yearColor = mode == _DatePickerMode.year ? Colors.white : Colors.white70;
break; break;
...@@ -172,10 +172,10 @@ class _DatePickerHeader extends StatelessWidget { ...@@ -172,10 +172,10 @@ class _DatePickerHeader extends StatelessWidget {
Color backgroundColor; Color backgroundColor;
switch (themeData.brightness) { switch (themeData.brightness) {
case ThemeBrightness.light: case Brightness.light:
backgroundColor = themeData.primaryColor; backgroundColor = themeData.primaryColor;
break; break;
case ThemeBrightness.dark: case Brightness.dark:
backgroundColor = themeData.backgroundColor; backgroundColor = themeData.backgroundColor;
break; break;
} }
...@@ -299,7 +299,7 @@ class DayPicker extends StatelessWidget { ...@@ -299,7 +299,7 @@ class DayPicker extends StatelessWidget {
if (selectedDate.year == year && selectedDate.month == month && selectedDate.day == day) { if (selectedDate.year == year && selectedDate.month == month && selectedDate.day == day) {
// The selected day gets a circle background highlight, and a contrasting text color. // The selected day gets a circle background highlight, and a contrasting text color.
itemStyle = themeData.textTheme.body2.copyWith( itemStyle = themeData.textTheme.body2.copyWith(
color: (themeData.brightness == ThemeBrightness.light) ? Colors.white : Colors.black87 color: (themeData.brightness == Brightness.light) ? Colors.white : Colors.black87
); );
decoration = new BoxDecoration( decoration = new BoxDecoration(
backgroundColor: themeData.accentColor, backgroundColor: themeData.accentColor,
......
...@@ -58,9 +58,9 @@ class Dialog extends StatelessWidget { ...@@ -58,9 +58,9 @@ class Dialog extends StatelessWidget {
Color _getColor(BuildContext context) { Color _getColor(BuildContext context) {
switch (Theme.of(context).brightness) { switch (Theme.of(context).brightness) {
case ThemeBrightness.light: case Brightness.light:
return Colors.white; return Colors.white;
case ThemeBrightness.dark: case Brightness.dark:
return Colors.grey[800]; return Colors.grey[800];
} }
} }
......
...@@ -54,13 +54,13 @@ class DrawerItem extends StatelessWidget { ...@@ -54,13 +54,13 @@ class DrawerItem extends StatelessWidget {
Color _getIconColor(ThemeData themeData) { Color _getIconColor(ThemeData themeData) {
switch (themeData.brightness) { switch (themeData.brightness) {
case ThemeBrightness.light: case Brightness.light:
if (selected) if (selected)
return themeData.primaryColor; return themeData.primaryColor;
if (onPressed == null) if (onPressed == null)
return Colors.black26; return Colors.black26;
return Colors.black45; return Colors.black45;
case ThemeBrightness.dark: case Brightness.dark:
if (selected) if (selected)
return themeData.accentColor; return themeData.accentColor;
if (onPressed == null) if (onPressed == null)
...@@ -73,9 +73,9 @@ class DrawerItem extends StatelessWidget { ...@@ -73,9 +73,9 @@ class DrawerItem extends StatelessWidget {
TextStyle result = themeData.textTheme.body2; TextStyle result = themeData.textTheme.body2;
if (selected) { if (selected) {
switch (themeData.brightness) { switch (themeData.brightness) {
case ThemeBrightness.light: case Brightness.light:
return result.copyWith(color: themeData.primaryColor); return result.copyWith(color: themeData.primaryColor);
case ThemeBrightness.dark: case Brightness.dark:
return result.copyWith(color: themeData.accentColor); return result.copyWith(color: themeData.accentColor);
} }
} }
......
...@@ -84,7 +84,7 @@ class FlatButton extends StatelessWidget { ...@@ -84,7 +84,7 @@ class FlatButton extends StatelessWidget {
/// The theme brightness to use for this button. /// The theme brightness to use for this button.
/// ///
/// Defaults to the brightness from [ThemeData.brightness]. /// Defaults to the brightness from [ThemeData.brightness].
final ThemeBrightness colorBrightness; final Brightness colorBrightness;
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
/// ///
......
...@@ -107,7 +107,7 @@ class _FloatingActionButtonState extends State<FloatingActionButton> { ...@@ -107,7 +107,7 @@ class _FloatingActionButtonState extends State<FloatingActionButton> {
if (materialColor == null) { if (materialColor == null) {
ThemeData themeData = Theme.of(context); ThemeData themeData = Theme.of(context);
materialColor = themeData.accentColor; materialColor = themeData.accentColor;
iconColor = themeData.accentColorBrightness == ThemeBrightness.dark ? Colors.white : Colors.black; iconColor = themeData.accentColorBrightness == Brightness.dark ? Colors.white : Colors.black;
} }
Widget result = new Center( Widget result = new Center(
......
...@@ -58,17 +58,17 @@ class Icon extends StatelessWidget { ...@@ -58,17 +58,17 @@ class Icon extends StatelessWidget {
/// brightness. /// brightness.
final Color color; final Color color;
Color _getDefaultColorForThemeBrightness(ThemeBrightness brightness) { Color _getDefaultColorForBrightness(Brightness brightness) {
switch (brightness) { switch (brightness) {
case ThemeBrightness.dark: case Brightness.dark:
return Colors.white; return Colors.white;
case ThemeBrightness.light: case Brightness.light:
return Colors.black; return Colors.black;
} }
} }
Color _getDefaultColor(BuildContext context) { Color _getDefaultColor(BuildContext context) {
return IconTheme.of(context)?.color ?? _getDefaultColorForThemeBrightness(Theme.of(context).brightness); return IconTheme.of(context)?.color ?? _getDefaultColorForBrightness(Theme.of(context).brightness);
} }
@override @override
......
...@@ -117,10 +117,10 @@ class _InputState extends State<Input> { ...@@ -117,10 +117,10 @@ class _InputState extends State<Input> {
Color activeColor = themeData.hintColor; Color activeColor = themeData.hintColor;
if (focused) { if (focused) {
switch (themeData.brightness) { switch (themeData.brightness) {
case ThemeBrightness.dark: case Brightness.dark:
activeColor = themeData.accentColor; activeColor = themeData.accentColor;
break; break;
case ThemeBrightness.light: case Brightness.light:
activeColor = themeData.primaryColor; activeColor = themeData.primaryColor;
break; break;
} }
......
...@@ -159,7 +159,7 @@ class _PopupMenuItemState<T extends PopupMenuItem<dynamic>> extends State<T> { ...@@ -159,7 +159,7 @@ class _PopupMenuItemState<T extends PopupMenuItem<dynamic>> extends State<T> {
) )
); );
if (!config.enabled) { if (!config.enabled) {
final bool isDark = theme.brightness == ThemeBrightness.dark; final bool isDark = theme.brightness == Brightness.dark;
item = new IconTheme( item = new IconTheme(
data: new IconThemeData(opacity: isDark ? 0.5 : 0.38), data: new IconThemeData(opacity: isDark ? 0.5 : 0.38),
child: item child: item
......
...@@ -80,7 +80,7 @@ class RaisedButton extends StatelessWidget { ...@@ -80,7 +80,7 @@ class RaisedButton extends StatelessWidget {
/// The theme brightness to use for this button. /// The theme brightness to use for this button.
/// ///
/// Defaults to the brightness from [ThemeData.brightness]. /// Defaults to the brightness from [ThemeData.brightness].
final ThemeBrightness colorBrightness; final Brightness colorBrightness;
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
/// ///
...@@ -98,9 +98,9 @@ class RaisedButton extends StatelessWidget { ...@@ -98,9 +98,9 @@ class RaisedButton extends StatelessWidget {
if (disabledColor != null) if (disabledColor != null)
return disabledColor; return disabledColor;
switch (Theme.of(context).brightness) { switch (Theme.of(context).brightness) {
case ThemeBrightness.light: case Brightness.light:
return Colors.black12; return Colors.black12;
case ThemeBrightness.dark: case Brightness.dark:
return Colors.white12; return Colors.white12;
} }
} }
......
...@@ -175,7 +175,7 @@ class SnackBar extends StatelessWidget { ...@@ -175,7 +175,7 @@ class SnackBar extends StatelessWidget {
margin: const EdgeInsets.symmetric(horizontal: _kSideMargins), margin: const EdgeInsets.symmetric(horizontal: _kSideMargins),
child: new Theme( child: new Theme(
data: new ThemeData( data: new ThemeData(
brightness: ThemeBrightness.dark, brightness: Brightness.dark,
accentColor: theme.accentColor, accentColor: theme.accentColor,
accentColorBrightness: theme.accentColorBrightness, accentColorBrightness: theme.accentColorBrightness,
textTheme: Typography.white textTheme: Typography.white
......
...@@ -80,7 +80,7 @@ class Switch extends StatelessWidget { ...@@ -80,7 +80,7 @@ class Switch extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context)); assert(debugCheckHasMaterial(context));
ThemeData themeData = Theme.of(context); ThemeData themeData = Theme.of(context);
final bool isDark = themeData.brightness == ThemeBrightness.dark; final bool isDark = themeData.brightness == Brightness.dark;
Color activeThumbColor = activeColor ?? themeData.accentColor; Color activeThumbColor = activeColor ?? themeData.accentColor;
Color activeTrackColor = activeThumbColor.withAlpha(0x80); Color activeTrackColor = activeThumbColor.withAlpha(0x80);
......
...@@ -7,7 +7,7 @@ import 'package:meta/meta.dart'; ...@@ -7,7 +7,7 @@ import 'package:meta/meta.dart';
import 'theme_data.dart'; import 'theme_data.dart';
export 'theme_data.dart' show ThemeData, ThemeBrightness; export 'theme_data.dart' show ThemeData;
/// The duration over which theme changes animate. /// The duration over which theme changes animate.
const Duration kThemeAnimationDuration = const Duration(milliseconds: 200); const Duration kThemeAnimationDuration = const Duration(milliseconds: 200);
......
...@@ -4,28 +4,12 @@ ...@@ -4,28 +4,12 @@
import 'dart:ui' show Color, hashValues; import 'dart:ui' show Color, hashValues;
import 'package:flutter/widgets.dart';
import 'colors.dart'; import 'colors.dart';
import 'icon_theme_data.dart'; import 'icon_theme_data.dart';
import 'typography.dart'; import 'typography.dart';
/// The contrast needs of a color.
///
/// This is used to describe the contrast needs of a theme as a whole
/// ([ThemeData.brightness]), its primary color
/// ([ThemeData.primaryColorBrightness]), and its accent color
/// ([ThemeData.accentColorBrightness]).
enum ThemeBrightness {
/// The color is dark, and will require a light text color to achieve readable contrast.
///
/// For example, the color might be dark grey, requiring white text.
dark,
/// The color is right, and will require a dark text color to achieve readable contrast.
///
/// For example, the color might be bright white, requiring black text.
light,
}
// Deriving these values is black magic. The spec claims that pressed buttons // Deriving these values is black magic. The spec claims that pressed buttons
// have a highlight of 0x66999999, but that's clearly wrong. The videos in the // have a highlight of 0x66999999, but that's clearly wrong. The videos in the
// spec show that buttons have a composited highlight of #E1E1E1 on a background // spec show that buttons have a composited highlight of #E1E1E1 on a background
...@@ -68,12 +52,12 @@ class ThemeData { ...@@ -68,12 +52,12 @@ class ThemeData {
/// See <https://www.google.com/design/spec/style/color.html> for /// See <https://www.google.com/design/spec/style/color.html> for
/// more discussion on how to pick the right colors. /// more discussion on how to pick the right colors.
factory ThemeData({ factory ThemeData({
ThemeBrightness brightness, Brightness brightness,
Map<int, Color> primarySwatch, Map<int, Color> primarySwatch,
Color primaryColor, Color primaryColor,
ThemeBrightness primaryColorBrightness, Brightness primaryColorBrightness,
Color accentColor, Color accentColor,
ThemeBrightness accentColorBrightness, Brightness accentColorBrightness,
Color canvasColor, Color canvasColor,
Color cardColor, Color cardColor,
Color dividerColor, Color dividerColor,
...@@ -93,13 +77,13 @@ class ThemeData { ...@@ -93,13 +77,13 @@ class ThemeData {
TextTheme primaryTextTheme, TextTheme primaryTextTheme,
IconThemeData primaryIconTheme IconThemeData primaryIconTheme
}) { }) {
brightness ??= ThemeBrightness.light; brightness ??= Brightness.light;
final bool isDark = brightness == ThemeBrightness.dark; final bool isDark = brightness == Brightness.dark;
primarySwatch ??= Colors.blue; primarySwatch ??= Colors.blue;
primaryColor ??= isDark ? Colors.grey[900] : primarySwatch[500]; primaryColor ??= isDark ? Colors.grey[900] : primarySwatch[500];
primaryColorBrightness ??= ThemeBrightness.dark; primaryColorBrightness ??= Brightness.dark;
accentColor ??= isDark ? Colors.tealAccent[200] : primarySwatch[500]; accentColor ??= isDark ? Colors.tealAccent[200] : primarySwatch[500];
accentColorBrightness ??= ThemeBrightness.dark; accentColorBrightness ??= Brightness.dark;
canvasColor ??= isDark ? Colors.grey[850] : Colors.grey[50]; canvasColor ??= isDark ? Colors.grey[850] : Colors.grey[50];
cardColor ??= isDark ? Colors.grey[800] : Colors.white; cardColor ??= isDark ? Colors.grey[800] : Colors.white;
dividerColor ??= isDark ? const Color(0x1FFFFFFF) : const Color(0x1F000000); dividerColor ??= isDark ? const Color(0x1FFFFFFF) : const Color(0x1F000000);
...@@ -116,8 +100,8 @@ class ThemeData { ...@@ -116,8 +100,8 @@ class ThemeData {
hintColor ??= isDark ? const Color(0x42FFFFFF) : const Color(0x4C000000); hintColor ??= isDark ? const Color(0x42FFFFFF) : const Color(0x4C000000);
errorColor ??= Colors.red[700]; errorColor ??= Colors.red[700];
textTheme ??= isDark ? Typography.white : Typography.black; textTheme ??= isDark ? Typography.white : Typography.black;
primaryTextTheme ??= primaryColorBrightness == ThemeBrightness.dark ? Typography.white : Typography.black; primaryTextTheme ??= primaryColorBrightness == Brightness.dark ? Typography.white : Typography.black;
primaryIconTheme ??= primaryColorBrightness == ThemeBrightness.dark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black); primaryIconTheme ??= primaryColorBrightness == Brightness.dark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black);
return new ThemeData.raw( return new ThemeData.raw(
brightness: brightness, brightness: brightness,
primaryColor: primaryColor, primaryColor: primaryColor,
...@@ -202,10 +186,10 @@ class ThemeData { ...@@ -202,10 +186,10 @@ class ThemeData {
} }
/// A default light blue theme. /// A default light blue theme.
factory ThemeData.light() => new ThemeData(brightness: ThemeBrightness.light); factory ThemeData.light() => new ThemeData(brightness: Brightness.light);
/// A default dark theme with a teal accent color. /// A default dark theme with a teal accent color.
factory ThemeData.dark() => new ThemeData(brightness: ThemeBrightness.dark); factory ThemeData.dark() => new ThemeData(brightness: Brightness.dark);
/// The default theme. Same as [new ThemeData.light]. /// The default theme. Same as [new ThemeData.light].
/// ///
...@@ -216,20 +200,20 @@ class ThemeData { ...@@ -216,20 +200,20 @@ class ThemeData {
/// like buttons to determine what color to pick when not using the primary or /// like buttons to determine what color to pick when not using the primary or
/// accent color. /// accent color.
/// ///
/// When the ThemeBrightness is dark, the canvas, card, and primary colors are /// When the [Brightness] is dark, the canvas, card, and primary colors are
/// all dark. When the ThemeBrightness is light, the canvas and card colors /// all dark. When the [Brightness] is light, the canvas and card colors
/// are bright, and the primary color's darkness varies as described by /// are bright, and the primary color's darkness varies as described by
/// primaryColorBrightness. The primaryColor does not contrast well with the /// primaryColorBrightness. The primaryColor does not contrast well with the
/// card and canvas colors when the brightness is dark; when the brightness is /// card and canvas colors when the brightness is dark; when the brightness is
/// dark, use Colors.white or the accentColor for a contrasting color. /// dark, use Colors.white or the accentColor for a contrasting color.
final ThemeBrightness brightness; final Brightness brightness;
/// The background color for major parts of the app (toolbars, tab bars, etc) /// The background color for major parts of the app (toolbars, tab bars, etc)
final Color primaryColor; final Color primaryColor;
/// The brightness of the primaryColor. Used to determine the color of text and /// The brightness of the primaryColor. Used to determine the color of text and
/// icons placed on top of the primary color (e.g. toolbar text). /// icons placed on top of the primary color (e.g. toolbar text).
final ThemeBrightness primaryColorBrightness; final Brightness primaryColorBrightness;
/// The foreground color for widgets (knobs, text, etc) /// The foreground color for widgets (knobs, text, etc)
final Color accentColor; final Color accentColor;
...@@ -237,7 +221,7 @@ class ThemeData { ...@@ -237,7 +221,7 @@ class ThemeData {
/// The brightness of the accentColor. Used to determine the color of text /// The brightness of the accentColor. Used to determine the color of text
/// and icons placed on top of the accent color (e.g. the icons on a floating /// and icons placed on top of the accent color (e.g. the icons on a floating
/// action button). /// action button).
final ThemeBrightness accentColorBrightness; final Brightness accentColorBrightness;
/// The color of [Material] when it is of infinite extent, e.g. the /// The color of [Material] when it is of infinite extent, e.g. the
/// body of a [Scaffold]. /// body of a [Scaffold].
......
...@@ -211,11 +211,11 @@ class _TimePickerHeader extends StatelessWidget { ...@@ -211,11 +211,11 @@ class _TimePickerHeader extends StatelessWidget {
Color activeColor; Color activeColor;
Color inactiveColor; Color inactiveColor;
switch(themeData.primaryColorBrightness) { switch(themeData.primaryColorBrightness) {
case ThemeBrightness.light: case Brightness.light:
activeColor = Colors.black87; activeColor = Colors.black87;
inactiveColor = Colors.black54; inactiveColor = Colors.black54;
break; break;
case ThemeBrightness.dark: case Brightness.dark:
activeColor = Colors.white; activeColor = Colors.white;
inactiveColor = Colors.white70; inactiveColor = Colors.white70;
break; break;
...@@ -223,10 +223,10 @@ class _TimePickerHeader extends StatelessWidget { ...@@ -223,10 +223,10 @@ class _TimePickerHeader extends StatelessWidget {
Color backgroundColor; Color backgroundColor;
switch (themeData.brightness) { switch (themeData.brightness) {
case ThemeBrightness.light: case Brightness.light:
backgroundColor = themeData.primaryColor; backgroundColor = themeData.primaryColor;
break; break;
case ThemeBrightness.dark: case Brightness.dark:
backgroundColor = themeData.backgroundColor; backgroundColor = themeData.backgroundColor;
break; break;
} }
...@@ -525,10 +525,10 @@ class _DialState extends State<_Dial> { ...@@ -525,10 +525,10 @@ class _DialState extends State<_Dial> {
Color backgroundColor; Color backgroundColor;
switch (themeData.brightness) { switch (themeData.brightness) {
case ThemeBrightness.light: case Brightness.light:
backgroundColor = Colors.grey[200]; backgroundColor = Colors.grey[200];
break; break;
case ThemeBrightness.dark: case Brightness.dark:
backgroundColor = themeData.backgroundColor; backgroundColor = themeData.backgroundColor;
break; break;
} }
...@@ -538,11 +538,11 @@ class _DialState extends State<_Dial> { ...@@ -538,11 +538,11 @@ class _DialState extends State<_Dial> {
switch (config.mode) { switch (config.mode) {
case _TimePickerMode.hour: case _TimePickerMode.hour:
switch (themeData.brightness) { switch (themeData.brightness) {
case ThemeBrightness.light: case Brightness.light:
primaryLabels = _hoursBlack; primaryLabels = _hoursBlack;
secondaryLabels = _hoursWhite; secondaryLabels = _hoursWhite;
break; break;
case ThemeBrightness.dark: case Brightness.dark:
primaryLabels = _hoursWhite; primaryLabels = _hoursWhite;
secondaryLabels = _hoursBlack; secondaryLabels = _hoursBlack;
break; break;
...@@ -550,11 +550,11 @@ class _DialState extends State<_Dial> { ...@@ -550,11 +550,11 @@ class _DialState extends State<_Dial> {
break; break;
case _TimePickerMode.minute: case _TimePickerMode.minute:
switch (themeData.brightness) { switch (themeData.brightness) {
case ThemeBrightness.light: case Brightness.light:
primaryLabels = _minutesBlack; primaryLabels = _minutesBlack;
secondaryLabels = _minutesWhite; secondaryLabels = _minutesWhite;
break; break;
case ThemeBrightness.dark: case Brightness.dark:
primaryLabels = _minutesWhite; primaryLabels = _minutesWhite;
secondaryLabels = _minutesBlack; secondaryLabels = _minutesBlack;
break; break;
......
...@@ -37,14 +37,35 @@ class SystemChrome { ...@@ -37,14 +37,35 @@ class SystemChrome {
return (await _systemChromeProxy.setPreferredOrientations(deviceOrientationMask)).success; return (await _systemChromeProxy.setPreferredOrientations(deviceOrientationMask)).success;
} }
/// Specifies the description of the current state of the application as it
/// pertains to the application switcher (a.k.a "recent tasks").
///
/// Arguments:
///
/// * [description]: The application description.
///
/// Return Value:
///
/// boolean indicating if the description was conveyed successfully to the
/// embedder.
///
/// Platform Specific Notes:
///
/// If application-specified metadata is unsupported on the platform,
/// specifying it is a no-op and always return true.
static Future<bool> setApplicationSwitcherDescription(mojom.ApplicationSwitcherDescription description) async {
return (await _systemChromeProxy.setApplicationSwitcherDescription(
description)).success;
}
/// Specifies the set of overlays visible on the embedder when the /// Specifies the set of overlays visible on the embedder when the
/// application is running. The embedder may choose to ignore unsupported /// application is running. The embedder may choose to ignore unsupported
/// overlays /// overlays
/// ///
/// Arguments: /// Arguments:
/// ///
/// * [style]: A mask of [SystemUIOverlay] enum values that denotes the overlays /// * [overlaysMask]: A mask of [SystemUIOverlay] enum values that denotes
/// to show. /// the overlays to show.
/// ///
/// Return Value: /// Return Value:
/// ///
...@@ -56,6 +77,29 @@ class SystemChrome { ...@@ -56,6 +77,29 @@ class SystemChrome {
/// If the overlay is unsupported on the platform, enabling or disabling /// If the overlay is unsupported on the platform, enabling or disabling
/// that overlay is a no-op and always return true. /// that overlay is a no-op and always return true.
static Future<bool> setEnabledSystemUIOverlays(int overlaysMask) async { static Future<bool> setEnabledSystemUIOverlays(int overlaysMask) async {
return (await _systemChromeProxy.setEnabledSystemUiOverlays(overlaysMask)).success; return (await _systemChromeProxy.setEnabledSystemUiOverlays(
overlaysMask)).success;
}
/// Specifies the style of the system overlays that are visible on the
/// embedder (if any). The embedder may choose to ignore unsupported
/// overlays.
///
/// Arguments:
///
/// * [style]: A [SystemUiOverlayStyle] enum value denoting the style to use
///
/// Return Value:
///
/// boolean indicating if the preference was conveyed successfully to the
/// embedder.
///
/// Platform Specific Notes:
///
/// If the overlay is unsupported on the platform, enabling or disabling
/// that overlay is a no-op and always return true.
static Future<bool> setSystemUIOverlayStyle(SystemUiOverlayStyle style) async {
return (await _systemChromeProxy.setSystemUiOverlayStyle(
style)).success;
} }
} }
...@@ -40,6 +40,7 @@ class WidgetsApp extends StatefulWidget { ...@@ -40,6 +40,7 @@ class WidgetsApp extends StatefulWidget {
Key key, Key key,
@required this.onGenerateRoute, @required this.onGenerateRoute,
this.title, this.title,
this.brightness,
this.textStyle, this.textStyle,
this.color, this.color,
this.navigatorObserver, this.navigatorObserver,
...@@ -56,6 +57,9 @@ class WidgetsApp extends StatefulWidget { ...@@ -56,6 +57,9 @@ class WidgetsApp extends StatefulWidget {
/// A one-line description of this app for use in the window manager. /// A one-line description of this app for use in the window manager.
final String title; final String title;
/// The overall brightness of the app, describing its contrast needs.
final Brightness brightness;
/// The default text style for [Text] in the application. /// The default text style for [Text] in the application.
final TextStyle textStyle; final TextStyle textStyle;
...@@ -180,6 +184,7 @@ class _WidgetsAppState extends State<WidgetsApp> implements WidgetsBindingObserv ...@@ -180,6 +184,7 @@ class _WidgetsAppState extends State<WidgetsApp> implements WidgetsBindingObserv
devicePixelRatio: ui.window.devicePixelRatio, devicePixelRatio: ui.window.devicePixelRatio,
child: new Title( child: new Title(
title: config.title, title: config.title,
brightness: config.brightness,
color: config.color, color: config.color,
child: new Navigator( child: new Navigator(
key: _navigator, key: _navigator,
......
...@@ -415,6 +415,21 @@ class ClipPath extends SingleChildRenderObjectWidget { ...@@ -415,6 +415,21 @@ class ClipPath extends SingleChildRenderObjectWidget {
} }
} }
/// Describes the contrast needs of a color.
enum Brightness {
/// The color is dark and will require a light text color to achieve readable
/// contrast.
///
/// For example, the color might be dark grey, requiring white text.
dark,
/// The color is light and will require a dark text color to achieve readable
/// contrast.
///
/// For example, the color might be bright white, requiring black text.
light,
}
// POSITIONING AND SIZING NODES // POSITIONING AND SIZING NODES
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:sky_services/flutter/platform/system_chrome.mojom.dart' as mojom;
/// A widget that describes this app in the operating system. /// A widget that describes this app in the operating system.
class Title extends StatelessWidget { class Title extends StatelessWidget {
...@@ -11,6 +12,7 @@ class Title extends StatelessWidget { ...@@ -11,6 +12,7 @@ class Title extends StatelessWidget {
Title({ Title({
Key key, Key key,
this.title, this.title,
this.brightness,
this.color, this.color,
this.child this.child
}) : super(key: key) { }) : super(key: key) {
...@@ -20,6 +22,9 @@ class Title extends StatelessWidget { ...@@ -20,6 +22,9 @@ class Title extends StatelessWidget {
/// A one-line description of this app for use in the window manager. /// A one-line description of this app for use in the window manager.
final String title; final String title;
/// The brightness against which the window manager should render system text.
final Brightness brightness;
/// A color that the window manager should use to identify this app. /// A color that the window manager should use to identify this app.
final Color color; final Color color;
...@@ -28,10 +33,22 @@ class Title extends StatelessWidget { ...@@ -28,10 +33,22 @@ class Title extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_updateSystemChrome();
updateTaskDescription(label: title, color: color); updateTaskDescription(label: title, color: color);
return child; return child;
} }
/// Updates the system chrome settings based on this title's metadata.
void _updateSystemChrome() {
// TODO(tvolkert): This may result in a decent amount of unnecessary
// overhead in the embedder (on every build). Consider making Title
// a StatefulWidget that only calls into the SystemChrome service when
// it sees that a value has changed.
SystemChrome.setSystemUIOverlayStyle(brightness == Brightness.dark
? mojom.SystemUiOverlayStyle.light
: mojom.SystemUiOverlayStyle.dark);
}
@override @override
void debugFillDescription(List<String> description) { void debugFillDescription(List<String> description) {
super.debugFillDescription(description); super.debugFillDescription(description);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment