CupertinoTheme & CupertinoTextTheme dark mode updates (#41859)
This commit is contained in:
parent
20e015ffe6
commit
4ac2daf337
@ -17,6 +17,7 @@ export 'src/cupertino/button.dart';
|
|||||||
export 'src/cupertino/colors.dart';
|
export 'src/cupertino/colors.dart';
|
||||||
export 'src/cupertino/date_picker.dart';
|
export 'src/cupertino/date_picker.dart';
|
||||||
export 'src/cupertino/dialog.dart';
|
export 'src/cupertino/dialog.dart';
|
||||||
|
export 'src/cupertino/icon_theme_data.dart';
|
||||||
export 'src/cupertino/icons.dart';
|
export 'src/cupertino/icons.dart';
|
||||||
export 'src/cupertino/interface_level.dart';
|
export 'src/cupertino/interface_level.dart';
|
||||||
export 'src/cupertino/localizations.dart';
|
export 'src/cupertino/localizations.dart';
|
||||||
|
@ -13,8 +13,7 @@ import 'theme.dart';
|
|||||||
|
|
||||||
// Examples can assume:
|
// Examples can assume:
|
||||||
// Widget child;
|
// Widget child;
|
||||||
// Color lightModeColor;
|
// BuildContext context;
|
||||||
// Color darkModeColor;
|
|
||||||
|
|
||||||
/// A palette of [Color] constants that describe colors commonly used when
|
/// A palette of [Color] constants that describe colors commonly used when
|
||||||
/// matching the iOS platform aesthetics.
|
/// matching the iOS platform aesthetics.
|
||||||
@ -539,45 +538,105 @@ class CupertinoColors {
|
|||||||
/// A [Color] subclass that represents a family of colors, and the currect effective
|
/// A [Color] subclass that represents a family of colors, and the currect effective
|
||||||
/// color in the color family.
|
/// color in the color family.
|
||||||
///
|
///
|
||||||
/// When used as a regular color, `CupertinoDynamicColor` is equivalent to the
|
/// When used as a regular color, [CupertinoDynamicColor] is equivalent to the
|
||||||
/// effective color (i.e. [CupertinoDynamicColor.value] will come from the effective
|
/// effective color (i.e. [CupertinoDynamicColor.value] will come from the effective
|
||||||
/// color), which is determined by the [BuildContext] it is last resolved against.
|
/// color), which is determined by the [BuildContext] it is last resolved against.
|
||||||
/// If it has never been resolved, the light, normal contrast, base elevation variant
|
/// If it has never been resolved, the light, normal contrast, base elevation variant
|
||||||
/// [CupertinoDynamicColor.color] will be the effective color.
|
/// [CupertinoDynamicColor.color] will be the default effective color.
|
||||||
// TODO(LongCatIsLooong): publicize once all Cupertino components have adopted this.
|
///
|
||||||
// {@tool sample}
|
/// Sometimes manually resolving a [CupertinoDynamicColor] is not necessary, because
|
||||||
//
|
/// the Cupertino Library provides built-in support for it.
|
||||||
// The following snippet will create a [CupertinoButton] whose background color
|
///
|
||||||
// is _lightModeColor_ in light mode but _darkModeColor_ in dark mode.
|
/// ### Using a [CupertinoDynamicColor] in a Cupertino widget
|
||||||
//
|
///
|
||||||
//
|
/// When a Cupertino widget is provided with a [CupertinoDynamicColor], either
|
||||||
// ```dart
|
/// directly in its constructor, or from an [InheritedWidget] it depends on (for example,
|
||||||
// CupertinoButton(
|
/// [DefaultTextStyle]), the widget will automatically resolve the color using
|
||||||
// child: child,
|
/// [CupertinoDynamicColor.resolve] against its own [BuildContext], on a best-effort
|
||||||
// color: CupertinoDynamicColor.withVibrancy(
|
/// basis.
|
||||||
// color: lightModeColor,
|
///
|
||||||
// darkColor: darkModeColor,
|
/// {@tool sample}
|
||||||
// ),
|
/// By default a [CupertinoButton] has no background color. The following sample
|
||||||
// onTap: () => null,
|
/// code shows how to build a [CupertinoButton] that appears white in light mode,
|
||||||
// )
|
/// and changes automatically to black in dark mode.
|
||||||
// ```
|
///
|
||||||
// {@end-tool}
|
/// ```dart
|
||||||
//
|
/// CupertinoButton(
|
||||||
// When a Cupertino component is provided with a `CupertinoDynamicColor`, either
|
/// child: child,
|
||||||
// directly in its constructor, or from an [InheritedWidget] it depends on (for example,
|
/// // CupertinoDynamicColor works out of box in a CupertinoButton.
|
||||||
// [DefaultTextStyle]), the component will automatically resolve the color by calling
|
/// color: CupertinoDynamicColor.withBrightness(
|
||||||
// [CupertinoDynamicColor.resolve], using their own [BuildContext].
|
/// color: CupertinoColors.white,
|
||||||
//
|
/// darkColor: CupertinoColors.black,
|
||||||
// When used outside of a Cupertino component, such color resolution will not happen
|
/// ),
|
||||||
// automatically. It's essential to call [CupertinoDynamicColor.resolve] with the
|
/// onPressed: () { },
|
||||||
// correct [BuildContext] before using the color to paint, in order to get the
|
/// )
|
||||||
// desired effect.
|
/// ```
|
||||||
|
/// {@end-tool}
|
||||||
|
///
|
||||||
|
/// ### Using a [CupertinoDynamicColor] from a [CupertinoTheme]
|
||||||
|
///
|
||||||
|
/// When referring to a [CupertinoTheme] color, generally the color will already
|
||||||
|
/// have adapted to the ambient [BuildContext], because [CupertinoTheme.of]
|
||||||
|
/// implicitly resolves all the colors used in the retrieved [CupertinoThemeData],
|
||||||
|
/// before returning it.
|
||||||
|
///
|
||||||
|
/// {@tool sample}
|
||||||
|
/// The following code sample creates a [Container] with the `primaryColor` of the
|
||||||
|
/// current theme. If `primaryColor` is a [CupertinoDynamicColor], the container
|
||||||
|
/// will be adaptive, thanks to [CupertinoTheme.of]: it will switch to `primaryColor`'s
|
||||||
|
/// dark variant once dark mode is turned on, and turns to primaryColor`'s high
|
||||||
|
/// contrast variant when [MediaQueryData.highContrast] is requested in the ambient
|
||||||
|
/// [MediaQuery], etc.
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// Container(
|
||||||
|
/// // Container is not a Cupertino widget, but CupertinoTheme.of implicitly
|
||||||
|
/// // resolves colors used in the retrieved CupertinoThemeData.
|
||||||
|
/// color: CupertinoTheme.of(context).primaryColor,
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
/// {@end-tool}
|
||||||
|
///
|
||||||
|
/// ### Manually Resolving a [CupertinoDynamicColor]
|
||||||
|
///
|
||||||
|
/// When used to configure a non-Cupertino widget, or wrapped in an object opaque
|
||||||
|
/// to the receiving Cupertino component, a [CupertinoDynamicColor] may need to be
|
||||||
|
/// manually resolved using [CupertinoDynamicColor.resolve], before it can used
|
||||||
|
/// to paint. For example, to use a custom [Border] in a [CupertinoNavigationBar],
|
||||||
|
/// the colors used in the [Border] have to be resolved manually before being passed
|
||||||
|
/// to [CupertinoNavigationBar]'s constructor.
|
||||||
|
///
|
||||||
|
/// {@tool sample}
|
||||||
|
///
|
||||||
|
/// The following code samples demostrate two cases where you have to manually
|
||||||
|
/// resolve a [CupertinoDynamicColor].
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// CupertinoNavigationBar(
|
||||||
|
/// // CupertinoNavigationBar does not know how to resolve colors used in
|
||||||
|
/// // a Border class.
|
||||||
|
/// border: Border(
|
||||||
|
/// bottom: BorderSide(
|
||||||
|
/// color: CupertinoDynamicColor.resolve(CupertinoColors.systemBlue, context),
|
||||||
|
/// ),
|
||||||
|
/// ),
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// Container(
|
||||||
|
/// // Container is not a Cupertino widget.
|
||||||
|
/// color: CupertinoDynamicColor.resolve(CupertinoColors.systemBlue, context),
|
||||||
|
/// )
|
||||||
|
/// ```
|
||||||
|
/// {@end-tool}
|
||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [CupertinoUserInterfaceLevel], an [InheritedWidget] that may affect color
|
/// * [CupertinoUserInterfaceLevel], an [InheritedWidget] that may affect color
|
||||||
/// resolution of a `CupertinoDynamicColor`.
|
/// resolution of a [CupertinoDynamicColor].
|
||||||
/// * https://developer.apple.com/documentation/uikit/uicolor/3238042-resolvedcolor.
|
/// * [CupertinoTheme.of], a static method that retrieves the ambient [CupertinoThemeData],
|
||||||
|
/// and then resolves [CupertinoDynamicColor]s used in the retrieved data.
|
||||||
@immutable
|
@immutable
|
||||||
class CupertinoDynamicColor extends Color {
|
class CupertinoDynamicColor extends Color {
|
||||||
/// Creates an adaptive [Color] that changes its effective color based on the
|
/// Creates an adaptive [Color] that changes its effective color based on the
|
||||||
@ -678,7 +737,7 @@ class CupertinoDynamicColor extends Color {
|
|||||||
/// The color to use when the [BuildContext] implies a combination of light mode,
|
/// The color to use when the [BuildContext] implies a combination of light mode,
|
||||||
/// normal contrast, and base interface elevation.
|
/// normal contrast, and base interface elevation.
|
||||||
///
|
///
|
||||||
/// In other words, this color will be the effective color of the `CupertinoDynamicColor`
|
/// In other words, this color will be the effective color of the [CupertinoDynamicColor]
|
||||||
/// after it is resolved against a [BuildContext] that:
|
/// after it is resolved against a [BuildContext] that:
|
||||||
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.light],
|
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.light],
|
||||||
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.light].
|
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.light].
|
||||||
@ -689,7 +748,7 @@ class CupertinoDynamicColor extends Color {
|
|||||||
/// The color to use when the [BuildContext] implies a combination of dark mode,
|
/// The color to use when the [BuildContext] implies a combination of dark mode,
|
||||||
/// normal contrast, and base interface elevation.
|
/// normal contrast, and base interface elevation.
|
||||||
///
|
///
|
||||||
/// In other words, this color will be the effective color of the `CupertinoDynamicColor`
|
/// In other words, this color will be the effective color of the [CupertinoDynamicColor]
|
||||||
/// after it is resolved against a [BuildContext] that:
|
/// after it is resolved against a [BuildContext] that:
|
||||||
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.dark],
|
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.dark],
|
||||||
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.dark].
|
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.dark].
|
||||||
@ -700,7 +759,7 @@ class CupertinoDynamicColor extends Color {
|
|||||||
/// The color to use when the [BuildContext] implies a combination of light mode,
|
/// The color to use when the [BuildContext] implies a combination of light mode,
|
||||||
/// high contrast, and base interface elevation.
|
/// high contrast, and base interface elevation.
|
||||||
///
|
///
|
||||||
/// In other words, this color will be the effective color of the `CupertinoDynamicColor`
|
/// In other words, this color will be the effective color of the [CupertinoDynamicColor]
|
||||||
/// after it is resolved against a [BuildContext] that:
|
/// after it is resolved against a [BuildContext] that:
|
||||||
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.light],
|
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.light],
|
||||||
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.light].
|
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.light].
|
||||||
@ -711,7 +770,7 @@ class CupertinoDynamicColor extends Color {
|
|||||||
/// The color to use when the [BuildContext] implies a combination of dark mode,
|
/// The color to use when the [BuildContext] implies a combination of dark mode,
|
||||||
/// high contrast, and base interface elevation.
|
/// high contrast, and base interface elevation.
|
||||||
///
|
///
|
||||||
/// In other words, this color will be the effective color of the `CupertinoDynamicColor`
|
/// In other words, this color will be the effective color of the [CupertinoDynamicColor]
|
||||||
/// after it is resolved against a [BuildContext] that:
|
/// after it is resolved against a [BuildContext] that:
|
||||||
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.dark],
|
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.dark],
|
||||||
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.dark].
|
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.dark].
|
||||||
@ -722,7 +781,7 @@ class CupertinoDynamicColor extends Color {
|
|||||||
/// The color to use when the [BuildContext] implies a combination of light mode,
|
/// The color to use when the [BuildContext] implies a combination of light mode,
|
||||||
/// normal contrast, and elevated interface elevation.
|
/// normal contrast, and elevated interface elevation.
|
||||||
///
|
///
|
||||||
/// In other words, this color will be the effective color of the `CupertinoDynamicColor`
|
/// In other words, this color will be the effective color of the [CupertinoDynamicColor]
|
||||||
/// after it is resolved against a [BuildContext] that:
|
/// after it is resolved against a [BuildContext] that:
|
||||||
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.light],
|
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.light],
|
||||||
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.light].
|
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.light].
|
||||||
@ -733,7 +792,7 @@ class CupertinoDynamicColor extends Color {
|
|||||||
/// The color to use when the [BuildContext] implies a combination of dark mode,
|
/// The color to use when the [BuildContext] implies a combination of dark mode,
|
||||||
/// normal contrast, and elevated interface elevation.
|
/// normal contrast, and elevated interface elevation.
|
||||||
///
|
///
|
||||||
/// In other words, this color will be the effective color of the `CupertinoDynamicColor`
|
/// In other words, this color will be the effective color of the [CupertinoDynamicColor]
|
||||||
/// after it is resolved against a [BuildContext] that:
|
/// after it is resolved against a [BuildContext] that:
|
||||||
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.dark],
|
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.dark],
|
||||||
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.dark].
|
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.dark].
|
||||||
@ -744,7 +803,7 @@ class CupertinoDynamicColor extends Color {
|
|||||||
/// The color to use when the [BuildContext] implies a combination of light mode,
|
/// The color to use when the [BuildContext] implies a combination of light mode,
|
||||||
/// high contrast, and elevated interface elevation.
|
/// high contrast, and elevated interface elevation.
|
||||||
///
|
///
|
||||||
/// In other words, this color will be the effective color of the `CupertinoDynamicColor`
|
/// In other words, this color will be the effective color of the [CupertinoDynamicColor]
|
||||||
/// after it is resolved against a [BuildContext] that:
|
/// after it is resolved against a [BuildContext] that:
|
||||||
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.light],
|
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.light],
|
||||||
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.light].
|
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.light].
|
||||||
@ -755,7 +814,7 @@ class CupertinoDynamicColor extends Color {
|
|||||||
/// The color to use when the [BuildContext] implies a combination of dark mode,
|
/// The color to use when the [BuildContext] implies a combination of dark mode,
|
||||||
/// high contrast, and elevated interface elevation.
|
/// high contrast, and elevated interface elevation.
|
||||||
///
|
///
|
||||||
/// In other words, this color will be the effective color of the `CupertinoDynamicColor`
|
/// In other words, this color will be the effective color of the [CupertinoDynamicColor]
|
||||||
/// after it is resolved against a [BuildContext] that:
|
/// after it is resolved against a [BuildContext] that:
|
||||||
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.dark],
|
/// - has a [CupertinoTheme] whose [brightness] is [PlatformBrightness.dark],
|
||||||
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.dark].
|
/// or a [MediaQuery] whose [MediaQueryData.platformBrightness] is [PlatformBrightness.dark].
|
||||||
@ -802,10 +861,10 @@ class CupertinoDynamicColor extends Color {
|
|||||||
|| darkHighContrastColor != darkHighContrastElevatedColor;
|
|| darkHighContrastColor != darkHighContrastElevatedColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves this `CupertinoDynamicColor` using the provided [BuildContext].
|
/// Resolves this [CupertinoDynamicColor] using the provided [BuildContext].
|
||||||
///
|
///
|
||||||
/// Calling this method will create a new `CupertinoDynamicColor` that is almost
|
/// Calling this method will create a new [CupertinoDynamicColor] that is almost
|
||||||
/// identical to this `CupertinoDynamicColor`, except the effective color is
|
/// identical to this [CupertinoDynamicColor], except the effective color is
|
||||||
/// changed to adapt to the given [BuildContext].
|
/// changed to adapt to the given [BuildContext].
|
||||||
///
|
///
|
||||||
/// For example, if the given [BuildContext] indicates the widgets in the subtree
|
/// For example, if the given [BuildContext] indicates the widgets in the subtree
|
||||||
@ -814,9 +873,9 @@ class CupertinoDynamicColor extends Color {
|
|||||||
/// with a high accessibility contrast (the surrounding [MediaQuery]'s [MediaQueryData.highContrast]
|
/// with a high accessibility contrast (the surrounding [MediaQuery]'s [MediaQueryData.highContrast]
|
||||||
/// is `true`), and an elevated interface elevation (the surrounding [CupertinoUserInterfaceLevel]'s
|
/// is `true`), and an elevated interface elevation (the surrounding [CupertinoUserInterfaceLevel]'s
|
||||||
/// `data` is [CupertinoUserInterfaceLevelData.elevated]), the resolved
|
/// `data` is [CupertinoUserInterfaceLevelData.elevated]), the resolved
|
||||||
/// `CupertinoDynamicColor` will be the same as this [CupertinoDynamicColor],
|
/// [CupertinoDynamicColor] will be the same as this [CupertinoDynamicColor],
|
||||||
/// except its effective color will be the `darkHighContrastElevatedColor` variant
|
/// except its effective color will be the `darkHighContrastElevatedColor` variant
|
||||||
/// from the orignal `CupertinoDynamicColor`.
|
/// from the orignal [CupertinoDynamicColor].
|
||||||
///
|
///
|
||||||
/// Calling this function may create dependencies on the closest instance of some
|
/// Calling this function may create dependencies on the closest instance of some
|
||||||
/// [InheritedWidget]s that enclose the given [BuildContext]. E.g., if [darkColor]
|
/// [InheritedWidget]s that enclose the given [BuildContext]. E.g., if [darkColor]
|
||||||
|
27
packages/flutter/lib/src/cupertino/icon_theme_data.dart
Normal file
27
packages/flutter/lib/src/cupertino/icon_theme_data.dart
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// Copyright 2019 The Chromium Authors. 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/widgets.dart';
|
||||||
|
import 'colors.dart';
|
||||||
|
|
||||||
|
/// An [IconThemeData] subclass that automatically resolves its [color] when retrieved
|
||||||
|
/// using [IconTheme.of].
|
||||||
|
class CupertinoIconThemeData extends IconThemeData {
|
||||||
|
/// Creates a [CupertinoIconThemeData].
|
||||||
|
///
|
||||||
|
/// The opacity applies to both explicit and default icon colors. The value
|
||||||
|
/// is clamped between 0.0 and 1.0.
|
||||||
|
const CupertinoIconThemeData({
|
||||||
|
Color color,
|
||||||
|
double opacity,
|
||||||
|
double size
|
||||||
|
}) : super(color: color, opacity: opacity, size: size);
|
||||||
|
|
||||||
|
/// Called by [IconThemeData.of] to resolve [color] against the given [BuildContext].
|
||||||
|
@override
|
||||||
|
IconThemeData resolve(BuildContext context) {
|
||||||
|
final Color resolvedColor = CupertinoDynamicColor.resolve(color, context);
|
||||||
|
return resolvedColor == color ? this : copyWith(color: resolvedColor);
|
||||||
|
}
|
||||||
|
}
|
@ -8,26 +8,24 @@ import 'package:flutter/widgets.dart';
|
|||||||
|
|
||||||
import 'colors.dart';
|
import 'colors.dart';
|
||||||
|
|
||||||
|
// Please update _DefaultCupertinoTextThemeData and _DefaultCupertinoTextThemeData
|
||||||
|
// accordingly after changing the default color here, as their implementation
|
||||||
|
// depends on the default value of the color field.
|
||||||
|
//
|
||||||
// Values derived from https://developer.apple.com/design/resources/.
|
// Values derived from https://developer.apple.com/design/resources/.
|
||||||
const TextStyle _kDefaultLightTextStyle = TextStyle(
|
const TextStyle _kDefaultTextStyle = TextStyle(
|
||||||
inherit: false,
|
inherit: false,
|
||||||
fontFamily: '.SF Pro Text',
|
fontFamily: '.SF Pro Text',
|
||||||
fontSize: 17.0,
|
fontSize: 17.0,
|
||||||
letterSpacing: -0.41,
|
letterSpacing: -0.41,
|
||||||
color: CupertinoColors.black,
|
color: CupertinoColors.label,
|
||||||
decoration: TextDecoration.none,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Values derived from https://developer.apple.com/design/resources/.
|
|
||||||
const TextStyle _kDefaultDarkTextStyle = TextStyle(
|
|
||||||
inherit: false,
|
|
||||||
fontFamily: '.SF Pro Text',
|
|
||||||
fontSize: 17.0,
|
|
||||||
letterSpacing: -0.41,
|
|
||||||
color: CupertinoColors.white,
|
|
||||||
decoration: TextDecoration.none,
|
decoration: TextDecoration.none,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Please update _DefaultCupertinoTextThemeData and _DefaultCupertinoTextThemeData
|
||||||
|
// accordingly after changing the default color here, as their implementation
|
||||||
|
// depends on the default value of the color field.
|
||||||
|
//
|
||||||
// Values derived from https://developer.apple.com/design/resources/.
|
// Values derived from https://developer.apple.com/design/resources/.
|
||||||
const TextStyle _kDefaultActionTextStyle = TextStyle(
|
const TextStyle _kDefaultActionTextStyle = TextStyle(
|
||||||
inherit: false,
|
inherit: false,
|
||||||
@ -38,6 +36,10 @@ const TextStyle _kDefaultActionTextStyle = TextStyle(
|
|||||||
decoration: TextDecoration.none,
|
decoration: TextDecoration.none,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Please update _DefaultCupertinoTextThemeData and _DefaultCupertinoTextThemeData
|
||||||
|
// accordingly after changing the default color here, as their implementation
|
||||||
|
// depends on the default value of the color field.
|
||||||
|
//
|
||||||
// Values derived from https://developer.apple.com/design/resources/.
|
// Values derived from https://developer.apple.com/design/resources/.
|
||||||
const TextStyle _kDefaultTabLabelTextStyle = TextStyle(
|
const TextStyle _kDefaultTabLabelTextStyle = TextStyle(
|
||||||
inherit: false,
|
inherit: false,
|
||||||
@ -47,97 +49,83 @@ const TextStyle _kDefaultTabLabelTextStyle = TextStyle(
|
|||||||
color: CupertinoColors.inactiveGray,
|
color: CupertinoColors.inactiveGray,
|
||||||
);
|
);
|
||||||
|
|
||||||
const TextStyle _kDefaultMiddleTitleLightTextStyle = TextStyle(
|
// Please update _DefaultCupertinoTextThemeData and _DefaultCupertinoTextThemeData
|
||||||
|
// accordingly after changing the default color here, as their implementation
|
||||||
|
// depends on the default value of the color field.
|
||||||
|
const TextStyle _kDefaultMiddleTitleTextStyle = TextStyle(
|
||||||
inherit: false,
|
inherit: false,
|
||||||
fontFamily: '.SF Pro Text',
|
fontFamily: '.SF Pro Text',
|
||||||
fontSize: 17.0,
|
fontSize: 17.0,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
letterSpacing: -0.41,
|
letterSpacing: -0.41,
|
||||||
color: CupertinoColors.black,
|
color: CupertinoColors.label,
|
||||||
);
|
);
|
||||||
|
|
||||||
const TextStyle _kDefaultMiddleTitleDarkTextStyle = TextStyle(
|
// Please update _DefaultCupertinoTextThemeData and _DefaultCupertinoTextThemeData
|
||||||
inherit: false,
|
// accordingly after changing the default color here, as their implementation
|
||||||
fontFamily: '.SF Pro Text',
|
// depends on the default value of the color field.
|
||||||
fontSize: 17.0,
|
const TextStyle _kDefaultLargeTitleTextStyle = TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
letterSpacing: -0.41,
|
|
||||||
color: CupertinoColors.white,
|
|
||||||
);
|
|
||||||
|
|
||||||
const TextStyle _kDefaultLargeTitleLightTextStyle = TextStyle(
|
|
||||||
inherit: false,
|
inherit: false,
|
||||||
fontFamily: '.SF Pro Display',
|
fontFamily: '.SF Pro Display',
|
||||||
fontSize: 34.0,
|
fontSize: 34.0,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
letterSpacing: 0.41,
|
letterSpacing: 0.41,
|
||||||
color: CupertinoColors.black,
|
color: CupertinoColors.label,
|
||||||
);
|
);
|
||||||
|
|
||||||
const TextStyle _kDefaultLargeTitleDarkTextStyle = TextStyle(
|
// Please update _DefaultCupertinoTextThemeData and _DefaultCupertinoTextThemeData
|
||||||
inherit: false,
|
// accordingly after changing the default color here, as their implementation
|
||||||
fontFamily: '.SF Pro Display',
|
// depends on the default value of the color field.
|
||||||
fontSize: 34.0,
|
//
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
letterSpacing: 0.41,
|
|
||||||
color: CupertinoColors.white,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Eyeballed value since it's not documented in https://developer.apple.com/design/resources/.
|
|
||||||
const TextStyle _kDefaultPickerLightTextStyle = TextStyle(
|
|
||||||
inherit: false,
|
|
||||||
fontFamily: '.SF Pro Display',
|
|
||||||
fontSize: 25.0,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
letterSpacing: -0.41,
|
|
||||||
color: CupertinoColors.black,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Eyeballed value since it's not documented in https://developer.apple.com/design/resources/.
|
|
||||||
const TextStyle _kDefaultPickerDarkTextStyle = TextStyle(
|
|
||||||
inherit: false,
|
|
||||||
fontFamily: '.SF Pro Display',
|
|
||||||
fontSize: 25.0,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
letterSpacing: -0.41,
|
|
||||||
color: CupertinoColors.white,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Eyeballed value since it's not documented in https://developer.apple.com/design/resources/.
|
|
||||||
// Inspected on iOS 13 simulator with "Debug View Hierarchy".
|
// Inspected on iOS 13 simulator with "Debug View Hierarchy".
|
||||||
const TextStyle _kDefaultDateTimePickerLightTextStyle = TextStyle(
|
// Value extracted from off-center labels. Centered labels have a font size of 25pt.
|
||||||
|
const TextStyle _kDefaultPickerTextStyle = TextStyle(
|
||||||
|
inherit: false,
|
||||||
|
fontFamily: '.SF Pro Display',
|
||||||
|
fontSize: 21.0,
|
||||||
|
fontWeight: FontWeight.w400,
|
||||||
|
letterSpacing: -0.41,
|
||||||
|
color: CupertinoColors.label,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Please update _DefaultCupertinoTextThemeData and _DefaultCupertinoTextThemeData
|
||||||
|
// accordingly after changing the default color here, as their implementation
|
||||||
|
// depends on the default value of the color field.
|
||||||
|
//
|
||||||
|
// Inspected on iOS 13 simulator with "Debug View Hierarchy".
|
||||||
|
// Value extracted from off-center labels. Centered labels have a font size of 25pt.
|
||||||
|
const TextStyle _kDefaultDateTimePickerTextStyle = TextStyle(
|
||||||
inherit: false,
|
inherit: false,
|
||||||
fontFamily: '.SF Pro Display',
|
fontFamily: '.SF Pro Display',
|
||||||
fontSize: 21,
|
fontSize: 21,
|
||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
color: CupertinoColors.black,
|
color: CupertinoColors.label,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Eyeballed value since it's not documented in https://developer.apple.com/design/resources/.
|
TextStyle _resolveTextStyle(TextStyle style, BuildContext context, bool nullOk) {
|
||||||
// Inspected on iOS 13 simulator with "Debug View Hierarchy".
|
// This does not resolve the shadow color, foreground, background, etc.
|
||||||
const TextStyle _kDefaultDateTimePickerDarkTextStyle = TextStyle(
|
return style?.copyWith(
|
||||||
inherit: false,
|
color: CupertinoDynamicColor.resolve(style?.color, context, nullOk: nullOk),
|
||||||
fontFamily: '.SF Pro Display',
|
backgroundColor: CupertinoDynamicColor.resolve(style?.backgroundColor, context, nullOk: nullOk),
|
||||||
fontSize: 21,
|
decorationColor: CupertinoDynamicColor.resolve(style?.decorationColor, context, nullOk: nullOk),
|
||||||
fontWeight: FontWeight.normal,
|
);
|
||||||
color: CupertinoColors.white,
|
}
|
||||||
);
|
|
||||||
|
|
||||||
/// Cupertino typography theme in a [CupertinoThemeData].
|
/// Cupertino typography theme in a [CupertinoThemeData].
|
||||||
@immutable
|
@immutable
|
||||||
class CupertinoTextThemeData extends Diagnosticable {
|
class CupertinoTextThemeData extends Diagnosticable {
|
||||||
/// Create a [CupertinoTextThemeData].
|
/// Create a [CupertinoTextThemeData].
|
||||||
///
|
///
|
||||||
/// The [primaryColor] and [isLight] parameters are used to derive TextStyle
|
/// The [primaryColor] is used to derive TextStyle defaults of other attributes
|
||||||
/// defaults of other attributes such as [textStyle] and [actionTextStyle]
|
/// such as [navActionTextStyle] and [actionTextStyle], it must not be null when
|
||||||
/// etc. The default value of [primaryColor] is [CupertinoColors.activeBlue]
|
/// either [navActionTextStyle] or [actionTextStyle] is null. Defaults to
|
||||||
/// and the default value of [isLight] is true.
|
/// [CupertinoColors.systemBlue].
|
||||||
///
|
///
|
||||||
/// Other [TextStyle] parameters default to default iOS text styles when
|
/// Other [TextStyle] parameters default to default iOS text styles when
|
||||||
/// unspecified.
|
/// unspecified.
|
||||||
const CupertinoTextThemeData({
|
const CupertinoTextThemeData({
|
||||||
Color primaryColor,
|
Color primaryColor = CupertinoColors.systemBlue,
|
||||||
Brightness brightness,
|
@deprecated Brightness brightness, //ignore: avoid_unused_constructor_parameters , the parameter is deprecated.
|
||||||
TextStyle textStyle,
|
TextStyle textStyle,
|
||||||
TextStyle actionTextStyle,
|
TextStyle actionTextStyle,
|
||||||
TextStyle tabLabelTextStyle,
|
TextStyle tabLabelTextStyle,
|
||||||
@ -146,96 +134,90 @@ class CupertinoTextThemeData extends Diagnosticable {
|
|||||||
TextStyle navActionTextStyle,
|
TextStyle navActionTextStyle,
|
||||||
TextStyle pickerTextStyle,
|
TextStyle pickerTextStyle,
|
||||||
TextStyle dateTimePickerTextStyle,
|
TextStyle dateTimePickerTextStyle,
|
||||||
}) : _primaryColor = primaryColor ?? CupertinoColors.activeBlue,
|
}) : this._raw(
|
||||||
_brightness = brightness,
|
const _DefaultCupertinoTextThemeData(),
|
||||||
_textStyle = textStyle,
|
primaryColor,
|
||||||
_actionTextStyle = actionTextStyle,
|
textStyle,
|
||||||
_tabLabelTextStyle = tabLabelTextStyle,
|
actionTextStyle,
|
||||||
_navTitleTextStyle = navTitleTextStyle,
|
tabLabelTextStyle,
|
||||||
_navLargeTitleTextStyle = navLargeTitleTextStyle,
|
navTitleTextStyle,
|
||||||
_navActionTextStyle = navActionTextStyle,
|
navLargeTitleTextStyle,
|
||||||
_pickerTextStyle = pickerTextStyle,
|
navActionTextStyle,
|
||||||
_dateTimePickerTextStyle = dateTimePickerTextStyle;
|
pickerTextStyle,
|
||||||
|
dateTimePickerTextStyle,
|
||||||
|
);
|
||||||
|
|
||||||
|
const CupertinoTextThemeData._raw(
|
||||||
|
this._defaults,
|
||||||
|
this._primaryColor,
|
||||||
|
this._textStyle,
|
||||||
|
this._actionTextStyle,
|
||||||
|
this._tabLabelTextStyle,
|
||||||
|
this._navTitleTextStyle,
|
||||||
|
this._navLargeTitleTextStyle,
|
||||||
|
this._navActionTextStyle,
|
||||||
|
this._pickerTextStyle,
|
||||||
|
this._dateTimePickerTextStyle,
|
||||||
|
) : assert((_navActionTextStyle != null && _actionTextStyle != null) || _primaryColor != null);
|
||||||
|
|
||||||
|
final _DefaultCupertinoTextThemeData _defaults;
|
||||||
final Color _primaryColor;
|
final Color _primaryColor;
|
||||||
final Brightness _brightness;
|
|
||||||
bool get _isLight => _brightness != Brightness.dark;
|
|
||||||
|
|
||||||
final TextStyle _textStyle;
|
final TextStyle _textStyle;
|
||||||
/// Typography of general text content for Cupertino widgets.
|
/// The [TextStyle] of general text content for Cupertino widgets.
|
||||||
TextStyle get textStyle => _textStyle ?? (_isLight ? _kDefaultLightTextStyle : _kDefaultDarkTextStyle);
|
TextStyle get textStyle => _textStyle ?? _defaults.textStyle;
|
||||||
|
|
||||||
final TextStyle _actionTextStyle;
|
final TextStyle _actionTextStyle;
|
||||||
/// Typography of interactive text content such as text in a button without background.
|
/// The [TextStyle] of interactive text content such as text in a button without background.
|
||||||
TextStyle get actionTextStyle {
|
TextStyle get actionTextStyle {
|
||||||
return _actionTextStyle ?? _kDefaultActionTextStyle.copyWith(
|
return _actionTextStyle ?? _defaults.actionTextStyle(primaryColor: _primaryColor);
|
||||||
color: _primaryColor,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final TextStyle _tabLabelTextStyle;
|
final TextStyle _tabLabelTextStyle;
|
||||||
/// Typography of unselected tabs.
|
/// The [TextStyle] of unselected tabs.
|
||||||
TextStyle get tabLabelTextStyle => _tabLabelTextStyle ?? _kDefaultTabLabelTextStyle;
|
TextStyle get tabLabelTextStyle => _tabLabelTextStyle ?? _defaults.tabLabelTextStyle;
|
||||||
|
|
||||||
final TextStyle _navTitleTextStyle;
|
final TextStyle _navTitleTextStyle;
|
||||||
/// Typography of titles in standard navigation bars.
|
/// The [TextStyle] of titles in standard navigation bars.
|
||||||
TextStyle get navTitleTextStyle {
|
TextStyle get navTitleTextStyle => _navTitleTextStyle ?? _defaults.navTitleTextStyle;
|
||||||
return _navTitleTextStyle ??
|
|
||||||
(_isLight ? _kDefaultMiddleTitleLightTextStyle : _kDefaultMiddleTitleDarkTextStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
final TextStyle _navLargeTitleTextStyle;
|
final TextStyle _navLargeTitleTextStyle;
|
||||||
/// Typography of large titles in sliver navigation bars.
|
/// The [TextStyle] of large titles in sliver navigation bars.
|
||||||
TextStyle get navLargeTitleTextStyle {
|
TextStyle get navLargeTitleTextStyle => _navLargeTitleTextStyle ?? _defaults.navLargeTitleTextStyle;
|
||||||
return _navLargeTitleTextStyle ??
|
|
||||||
(_isLight ? _kDefaultLargeTitleLightTextStyle : _kDefaultLargeTitleDarkTextStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
final TextStyle _navActionTextStyle;
|
final TextStyle _navActionTextStyle;
|
||||||
/// Typography of interactive text content in navigation bars.
|
/// The [TextStyle] of interactive text content in navigation bars.
|
||||||
TextStyle get navActionTextStyle {
|
TextStyle get navActionTextStyle {
|
||||||
return _navActionTextStyle ?? _kDefaultActionTextStyle.copyWith(
|
return _navActionTextStyle ?? _defaults.navActionTextStyle(primaryColor: _primaryColor);
|
||||||
color: _primaryColor,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final TextStyle _pickerTextStyle;
|
final TextStyle _pickerTextStyle;
|
||||||
/// Typography of pickers.
|
/// The [TextStyle] of pickers.
|
||||||
TextStyle get pickerTextStyle {
|
TextStyle get pickerTextStyle => _pickerTextStyle ?? _defaults.pickerTextStyle;
|
||||||
return _pickerTextStyle ??
|
|
||||||
(_isLight ? _kDefaultPickerLightTextStyle : _kDefaultPickerDarkTextStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
final TextStyle _dateTimePickerTextStyle;
|
final TextStyle _dateTimePickerTextStyle;
|
||||||
/// Typography of date time pickers.
|
/// The [TextStyle] of date time pickers.
|
||||||
TextStyle get dateTimePickerTextStyle {
|
TextStyle get dateTimePickerTextStyle => _dateTimePickerTextStyle ?? _defaults.dateTimePickerTextStyle;
|
||||||
return _dateTimePickerTextStyle ??
|
|
||||||
(_isLight ? _kDefaultDateTimePickerLightTextStyle : _kDefaultDateTimePickerDarkTextStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a copy of the current [CupertinoTextThemeData] with all the colors
|
/// Returns a copy of the current [CupertinoTextThemeData] with all the colors
|
||||||
/// resolved against the given [BuildContext].
|
/// resolved against the given [BuildContext].
|
||||||
|
///
|
||||||
|
/// Throws an exception if any of the [InheritedWidget]s required to resolve
|
||||||
|
/// this [CupertinoTextThemeData] is not found in [context], unless [nullOk] is
|
||||||
|
/// set to true, in which case [CupertinoDynamicColor]s that fail to resolve will
|
||||||
|
/// be used as-is.
|
||||||
CupertinoTextThemeData resolveFrom(BuildContext context, { bool nullOk = false }) {
|
CupertinoTextThemeData resolveFrom(BuildContext context, { bool nullOk = false }) {
|
||||||
Color convertColor(Color color) => CupertinoDynamicColor.resolve(color, context, nullOk: nullOk);
|
return CupertinoTextThemeData._raw(
|
||||||
|
_defaults?.resolveFrom(context, nullOk),
|
||||||
TextStyle resolveTextStyle(TextStyle textStyle) {
|
CupertinoDynamicColor.resolve(_primaryColor, context, nullOk: nullOk),
|
||||||
return textStyle?.copyWith(
|
_resolveTextStyle(_textStyle, context, nullOk),
|
||||||
color: convertColor(textStyle.color),
|
_resolveTextStyle(_actionTextStyle, context, nullOk),
|
||||||
backgroundColor: convertColor(textStyle.backgroundColor),
|
_resolveTextStyle(_tabLabelTextStyle, context, nullOk),
|
||||||
decorationColor: convertColor(textStyle.decorationColor),
|
_resolveTextStyle(_navTitleTextStyle, context, nullOk),
|
||||||
);
|
_resolveTextStyle(_navLargeTitleTextStyle, context, nullOk),
|
||||||
}
|
_resolveTextStyle(_navActionTextStyle, context, nullOk),
|
||||||
|
_resolveTextStyle(_pickerTextStyle, context, nullOk),
|
||||||
return copyWith(
|
_resolveTextStyle(_dateTimePickerTextStyle, context, nullOk),
|
||||||
primaryColor: convertColor(_primaryColor),
|
|
||||||
textStyle: resolveTextStyle(_textStyle),
|
|
||||||
actionTextStyle: resolveTextStyle(_actionTextStyle),
|
|
||||||
tabLabelTextStyle: resolveTextStyle(_tabLabelTextStyle),
|
|
||||||
navTitleTextStyle : resolveTextStyle(_navTitleTextStyle),
|
|
||||||
navLargeTitleTextStyle: resolveTextStyle(_navLargeTitleTextStyle),
|
|
||||||
navActionTextStyle: resolveTextStyle(_navActionTextStyle),
|
|
||||||
pickerTextStyle: resolveTextStyle(_pickerTextStyle),
|
|
||||||
dateTimePickerTextStyle: resolveTextStyle(_dateTimePickerTextStyle),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,7 +225,7 @@ class CupertinoTextThemeData extends Diagnosticable {
|
|||||||
/// specified overrides.
|
/// specified overrides.
|
||||||
CupertinoTextThemeData copyWith({
|
CupertinoTextThemeData copyWith({
|
||||||
Color primaryColor,
|
Color primaryColor,
|
||||||
Brightness brightness,
|
@deprecated Brightness brightness,
|
||||||
TextStyle textStyle,
|
TextStyle textStyle,
|
||||||
TextStyle actionTextStyle,
|
TextStyle actionTextStyle,
|
||||||
TextStyle tabLabelTextStyle,
|
TextStyle tabLabelTextStyle,
|
||||||
@ -253,17 +235,53 @@ class CupertinoTextThemeData extends Diagnosticable {
|
|||||||
TextStyle pickerTextStyle,
|
TextStyle pickerTextStyle,
|
||||||
TextStyle dateTimePickerTextStyle,
|
TextStyle dateTimePickerTextStyle,
|
||||||
}) {
|
}) {
|
||||||
return CupertinoTextThemeData(
|
return CupertinoTextThemeData._raw(
|
||||||
primaryColor: primaryColor ?? _primaryColor,
|
_defaults,
|
||||||
brightness: brightness ?? _brightness,
|
primaryColor ?? _primaryColor,
|
||||||
textStyle: textStyle ?? _textStyle,
|
textStyle ?? _textStyle,
|
||||||
actionTextStyle: actionTextStyle ?? _actionTextStyle,
|
actionTextStyle ?? _actionTextStyle,
|
||||||
tabLabelTextStyle: tabLabelTextStyle ?? _tabLabelTextStyle,
|
tabLabelTextStyle ?? _tabLabelTextStyle,
|
||||||
navTitleTextStyle: navTitleTextStyle ?? _navTitleTextStyle,
|
navTitleTextStyle ?? _navTitleTextStyle,
|
||||||
navLargeTitleTextStyle: navLargeTitleTextStyle ?? _navLargeTitleTextStyle,
|
navLargeTitleTextStyle ?? _navLargeTitleTextStyle,
|
||||||
navActionTextStyle: navActionTextStyle ?? _navActionTextStyle,
|
navActionTextStyle ?? _navActionTextStyle,
|
||||||
pickerTextStyle: pickerTextStyle ?? _pickerTextStyle,
|
pickerTextStyle ?? _pickerTextStyle,
|
||||||
dateTimePickerTextStyle: dateTimePickerTextStyle ?? _dateTimePickerTextStyle,
|
dateTimePickerTextStyle ?? _dateTimePickerTextStyle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class _DefaultCupertinoTextThemeData extends Diagnosticable {
|
||||||
|
const _DefaultCupertinoTextThemeData({
|
||||||
|
this.labelColor = CupertinoColors.label,
|
||||||
|
this.inactiveGrayColor = CupertinoColors.inactiveGray,
|
||||||
|
}) : assert(labelColor != null),
|
||||||
|
assert(inactiveGrayColor != null);
|
||||||
|
|
||||||
|
final Color labelColor;
|
||||||
|
final Color inactiveGrayColor;
|
||||||
|
|
||||||
|
static TextStyle _applyLabelColor(TextStyle original, Color color) {
|
||||||
|
return original?.color == color
|
||||||
|
? original
|
||||||
|
: original?.copyWith(color: color);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStyle get textStyle => _applyLabelColor(_kDefaultTextStyle, labelColor);
|
||||||
|
TextStyle get tabLabelTextStyle => _applyLabelColor(_kDefaultTabLabelTextStyle, inactiveGrayColor);
|
||||||
|
TextStyle get navTitleTextStyle => _applyLabelColor(_kDefaultMiddleTitleTextStyle, labelColor);
|
||||||
|
TextStyle get navLargeTitleTextStyle => _applyLabelColor(_kDefaultLargeTitleTextStyle, labelColor);
|
||||||
|
TextStyle get pickerTextStyle => _applyLabelColor(_kDefaultPickerTextStyle, labelColor);
|
||||||
|
TextStyle get dateTimePickerTextStyle => _applyLabelColor(_kDefaultDateTimePickerTextStyle, labelColor);
|
||||||
|
|
||||||
|
TextStyle actionTextStyle({ Color primaryColor }) => _kDefaultActionTextStyle.copyWith(color: primaryColor);
|
||||||
|
TextStyle navActionTextStyle({ Color primaryColor }) => actionTextStyle(primaryColor: primaryColor);
|
||||||
|
|
||||||
|
_DefaultCupertinoTextThemeData resolveFrom(BuildContext context, bool nullOk) {
|
||||||
|
final Color resolvedLabelColor = CupertinoDynamicColor.resolve(labelColor, context, nullOk: nullOk);
|
||||||
|
final Color resolvedInactiveGray = CupertinoDynamicColor.resolve(inactiveGrayColor, context, nullOk: nullOk);
|
||||||
|
return resolvedLabelColor == labelColor && resolvedInactiveGray == CupertinoColors.inactiveGray
|
||||||
|
? this
|
||||||
|
: _DefaultCupertinoTextThemeData(labelColor: resolvedLabelColor, inactiveGrayColor: resolvedInactiveGray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,13 +7,24 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
import 'colors.dart';
|
import 'colors.dart';
|
||||||
|
import 'icon_theme_data.dart';
|
||||||
import 'text_theme.dart';
|
import 'text_theme.dart';
|
||||||
|
|
||||||
export 'package:flutter/services.dart' show Brightness;
|
export 'package:flutter/services.dart' show Brightness;
|
||||||
|
|
||||||
// Values derived from https://developer.apple.com/design/resources/.
|
// Values derived from https://developer.apple.com/design/resources/.
|
||||||
const Color _kDefaultBarLightBackgroundColor = Color(0xCCF8F8F8);
|
const _CupertinoThemeDefaults _kDefaultTheme = _CupertinoThemeDefaults(
|
||||||
const Color _kDefaultBarDarkBackgroundColor = Color(0xB7212121);
|
null,
|
||||||
|
CupertinoColors.systemBlue,
|
||||||
|
CupertinoColors.systemBackground,
|
||||||
|
CupertinoDynamicColor.withBrightness(
|
||||||
|
color: Color(0xF0F9F9F9),
|
||||||
|
darkColor: Color(0xF01D1D1D),
|
||||||
|
// Values extracted from navigation bar. For toolbar or tabbar the dark color is 0xF0161616.
|
||||||
|
),
|
||||||
|
CupertinoColors.systemBackground,
|
||||||
|
_CupertinoTextThemeDefaults(CupertinoColors.label, CupertinoColors.inactiveGray),
|
||||||
|
);
|
||||||
|
|
||||||
/// Applies a visual styling theme to descendant Cupertino widgets.
|
/// Applies a visual styling theme to descendant Cupertino widgets.
|
||||||
///
|
///
|
||||||
@ -30,7 +41,8 @@ const Color _kDefaultBarDarkBackgroundColor = Color(0xB7212121);
|
|||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [CupertinoThemeData], specifies the theme's visual styling.
|
/// * [CupertinoThemeData], specifies the theme's visual styling.
|
||||||
/// * [CupertinoApp], which will automatically add a [CupertinoTheme].
|
/// * [CupertinoApp], which will automatically add a [CupertinoTheme] based on the
|
||||||
|
/// value of [CupertinoApp.theme].
|
||||||
/// * [Theme], a Material theme which will automatically add a [CupertinoTheme]
|
/// * [Theme], a Material theme which will automatically add a [CupertinoTheme]
|
||||||
/// with a [CupertinoThemeData] derived from the Material [ThemeData].
|
/// with a [CupertinoThemeData] derived from the Material [ThemeData].
|
||||||
class CupertinoTheme extends StatelessWidget {
|
class CupertinoTheme extends StatelessWidget {
|
||||||
@ -48,20 +60,22 @@ class CupertinoTheme extends StatelessWidget {
|
|||||||
/// The [CupertinoThemeData] styling for this theme.
|
/// The [CupertinoThemeData] styling for this theme.
|
||||||
final CupertinoThemeData data;
|
final CupertinoThemeData data;
|
||||||
|
|
||||||
/// Retrieve the [CupertinoThemeData] from an ancestor [CupertinoTheme] widget.
|
/// Retrieves the [CupertinoThemeData] from the closest ancestor [CupertinoTheme]
|
||||||
|
/// widget, or a default [CupertinoThemeData] if no [CupertinoTheme] ancestor
|
||||||
|
/// exists.
|
||||||
///
|
///
|
||||||
/// Returns a default [CupertinoThemeData] if no [CupertinoTheme] widgets
|
/// Resolves all the colors defined in that [CupertinoThemeData] against the
|
||||||
/// exist in the ancestry tree.
|
/// given [BuildContext] on a best-effort basis.
|
||||||
static CupertinoThemeData of(BuildContext context) {
|
static CupertinoThemeData of(BuildContext context) {
|
||||||
final _InheritedCupertinoTheme inheritedTheme = context.inheritFromWidgetOfExactType(_InheritedCupertinoTheme);
|
final _InheritedCupertinoTheme inheritedTheme = context.inheritFromWidgetOfExactType(_InheritedCupertinoTheme);
|
||||||
return (inheritedTheme?.theme?.data ?? const CupertinoThemeData()).resolveFrom(context, nullOk: true);
|
return (inheritedTheme?.theme?.data ?? const CupertinoThemeData()).resolveFrom(context, nullOk: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the [Brightness] value from the closest ancestor [CupertinoTheme]
|
/// Retrieves the [Brightness] value from the closest ancestor [CupertinoTheme]
|
||||||
/// widget.
|
/// widget.
|
||||||
///
|
///
|
||||||
/// If no ancestral [CupertinoTheme] widget with explicit brightness value could
|
/// If no [CupertinoTheme] ancestor with an explicit brightness value could be
|
||||||
/// be found, the method will resort to the closest ancestor [MediaQuery] widget.
|
/// found, this method will resort to the closest ancestor [MediaQuery] widget.
|
||||||
///
|
///
|
||||||
/// Throws an exception if no such [CupertinoTheme] or [MediaQuery] widgets exist
|
/// Throws an exception if no such [CupertinoTheme] or [MediaQuery] widgets exist
|
||||||
/// in the ancestry tree, unless [nullOk] is set to true.
|
/// in the ancestry tree, unless [nullOk] is set to true.
|
||||||
@ -80,7 +94,7 @@ class CupertinoTheme extends StatelessWidget {
|
|||||||
return _InheritedCupertinoTheme(
|
return _InheritedCupertinoTheme(
|
||||||
theme: this,
|
theme: this,
|
||||||
child: IconTheme(
|
child: IconTheme(
|
||||||
data: IconThemeData(color: data.primaryColor),
|
data: CupertinoIconThemeData(color: data.primaryColor),
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -119,7 +133,7 @@ class _InheritedCupertinoTheme extends InheritedWidget {
|
|||||||
/// styling via a [CupertinoThemeData] subclass [MaterialBasedCupertinoThemeData].
|
/// styling via a [CupertinoThemeData] subclass [MaterialBasedCupertinoThemeData].
|
||||||
@immutable
|
@immutable
|
||||||
class CupertinoThemeData extends Diagnosticable {
|
class CupertinoThemeData extends Diagnosticable {
|
||||||
/// Create a [CupertinoTheme] styling specification.
|
/// Creates a [CupertinoTheme] styling specification.
|
||||||
///
|
///
|
||||||
/// Unspecified parameters default to a reasonable iOS default style.
|
/// Unspecified parameters default to a reasonable iOS default style.
|
||||||
const CupertinoThemeData({
|
const CupertinoThemeData({
|
||||||
@ -144,89 +158,104 @@ class CupertinoThemeData extends Diagnosticable {
|
|||||||
/// Used by subclasses to get the superclass's defaulting behaviors.
|
/// Used by subclasses to get the superclass's defaulting behaviors.
|
||||||
@protected
|
@protected
|
||||||
const CupertinoThemeData.raw(
|
const CupertinoThemeData.raw(
|
||||||
|
Brightness brightness,
|
||||||
|
Color primaryColor,
|
||||||
|
Color primaryContrastingColor,
|
||||||
|
CupertinoTextThemeData textTheme,
|
||||||
|
Color barBackgroundColor,
|
||||||
|
Color scaffoldBackgroundColor,
|
||||||
|
) : this._rawWithDefaults(
|
||||||
|
brightness,
|
||||||
|
primaryColor,
|
||||||
|
primaryContrastingColor,
|
||||||
|
textTheme,
|
||||||
|
barBackgroundColor,
|
||||||
|
scaffoldBackgroundColor,
|
||||||
|
_kDefaultTheme,
|
||||||
|
);
|
||||||
|
|
||||||
|
const CupertinoThemeData._rawWithDefaults(
|
||||||
this._brightness,
|
this._brightness,
|
||||||
this._primaryColor,
|
this._primaryColor,
|
||||||
this._primaryContrastingColor,
|
this._primaryContrastingColor,
|
||||||
this._textTheme,
|
this._textTheme,
|
||||||
this._barBackgroundColor,
|
this._barBackgroundColor,
|
||||||
this._scaffoldBackgroundColor,
|
this._scaffoldBackgroundColor,
|
||||||
|
this._defaults,
|
||||||
);
|
);
|
||||||
|
|
||||||
bool get _isLight => brightness == Brightness.light;
|
final _CupertinoThemeDefaults _defaults;
|
||||||
|
|
||||||
/// The general brightness theme of the [CupertinoThemeData].
|
/// The general brightness theme of the [CupertinoThemeData].
|
||||||
///
|
///
|
||||||
/// Affects all other theme properties when unspecified. Defaults to
|
/// Overrides the ambient [MediaQueryData.platformBrightness] when specified.
|
||||||
/// [Brightness.light].
|
/// Defaults to [Brightness.light].
|
||||||
///
|
///
|
||||||
/// If coming from a Material [Theme] and unspecified, [brightness] will be
|
/// If coming from a Material [Theme] and unspecified, [brightness] will be
|
||||||
/// derived from the Material [ThemeData]'s `brightness`.
|
/// derived from the Material [ThemeData]'s `brightness`.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [MaterialBasedCupertinoThemeData], a [CupertinoThemeData] that defers
|
||||||
|
/// [brightness] to its Material [Theme] parent if it's unspecified.
|
||||||
Brightness get brightness => _brightness ?? Brightness.light;
|
Brightness get brightness => _brightness ?? Brightness.light;
|
||||||
final Brightness _brightness;
|
final Brightness _brightness;
|
||||||
|
|
||||||
/// A color used on interactive elements of the theme.
|
/// A color used on interactive elements of the theme.
|
||||||
///
|
///
|
||||||
/// This color is generally used on text and icons in buttons and tappable
|
/// This color is generally used on text and icons in buttons and tappable
|
||||||
/// elements. Defaults to [CupertinoColors.activeBlue] or
|
/// elements. Defaults to [CupertinoColors.activeBlue].
|
||||||
/// [CupertinoColors.activeOrange] when [brightness] is light or dark.
|
|
||||||
///
|
///
|
||||||
/// If coming from a Material [Theme] and unspecified, [primaryColor] will be
|
/// If coming from a Material [Theme] and unspecified, [primaryColor] will be
|
||||||
/// derived from the Material [ThemeData]'s `colorScheme.primary`. However, in
|
/// derived from the Material [ThemeData]'s `colorScheme.primary`. However, in
|
||||||
/// iOS styling, the [primaryColor] is more sparsely used than in Material
|
/// iOS styling, the [primaryColor] is more sparsely used than in Material
|
||||||
/// Design where the [primaryColor] can appear on non-interactive surfaces like
|
/// Design where the [primaryColor] can appear on non-interactive surfaces like
|
||||||
/// the [AppBar] background, [TextField] borders etc.
|
/// the [AppBar] background, [TextField] borders etc.
|
||||||
Color get primaryColor {
|
///
|
||||||
return _primaryColor ??
|
/// See also:
|
||||||
(_isLight ? CupertinoColors.activeBlue : CupertinoColors.activeOrange);
|
///
|
||||||
}
|
/// * [MaterialBasedCupertinoThemeData], a [CupertinoThemeData] that defers
|
||||||
|
/// [primaryColor] to its Material [Theme] parent if it's unspecified.
|
||||||
|
Color get primaryColor => _primaryColor ?? _defaults.primaryColor;
|
||||||
final Color _primaryColor;
|
final Color _primaryColor;
|
||||||
|
|
||||||
/// A color used for content that must contrast against a [primaryColor] background.
|
/// A color that must be easy to see when rendered on a [primaryColor] background.
|
||||||
///
|
///
|
||||||
/// For example, this color is used for a [CupertinoButton]'s text and icons
|
/// For example, this color is used for a [CupertinoButton]'s text and icons
|
||||||
/// when the button's background is [primaryColor].
|
/// when the button's background is [primaryColor].
|
||||||
///
|
///
|
||||||
/// If coming from a Material [Theme] and unspecified, [primaryContrastingColor]
|
/// If coming from a Material [Theme] and unspecified, [primaryContrastingColor]
|
||||||
/// will be derived from the Material [ThemeData]'s `colorScheme.onPrimary`.
|
/// will be derived from the Material [ThemeData]'s `colorScheme.onPrimary`.
|
||||||
Color get primaryContrastingColor {
|
///
|
||||||
return _primaryContrastingColor ??
|
/// See also:
|
||||||
(_isLight ? CupertinoColors.white : CupertinoColors.black);
|
///
|
||||||
}
|
/// * [MaterialBasedCupertinoThemeData], a [CupertinoThemeData] that defers
|
||||||
|
/// [primaryContrastingColor] to its Material [Theme] parent if it's unspecified.
|
||||||
|
Color get primaryContrastingColor => _primaryContrastingColor ?? _defaults.primaryContrastingColor;
|
||||||
final Color _primaryContrastingColor;
|
final Color _primaryContrastingColor;
|
||||||
|
|
||||||
/// Text styles used by Cupertino widgets.
|
/// Text styles used by Cupertino widgets.
|
||||||
///
|
///
|
||||||
/// Derived from [brightness] and [primaryColor] if unspecified, including
|
/// Derived from [primaryColor] if unspecified.
|
||||||
/// [brightness] and [primaryColor] of a Material [ThemeData] if coming
|
|
||||||
/// from a Material [Theme].
|
|
||||||
CupertinoTextThemeData get textTheme {
|
CupertinoTextThemeData get textTheme {
|
||||||
return _textTheme ?? CupertinoTextThemeData(
|
return _textTheme ?? _defaults.textThemeDefaults.createDefaults(primaryColor: primaryColor);
|
||||||
brightness: brightness,
|
|
||||||
primaryColor: primaryColor,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
final CupertinoTextThemeData _textTheme;
|
final CupertinoTextThemeData _textTheme;
|
||||||
|
|
||||||
/// Background color of the top nav bar and bottom tab bar.
|
/// Background color of the top nav bar and bottom tab bar.
|
||||||
///
|
///
|
||||||
/// Defaults to a light gray or a dark gray translucent color depending
|
/// Defaults to a light gray in light mode, or a dark translucent gray color in
|
||||||
/// on the [brightness].
|
/// dark mode.
|
||||||
Color get barBackgroundColor {
|
Color get barBackgroundColor => _barBackgroundColor ?? _defaults.barBackgroundColor;
|
||||||
return _barBackgroundColor ??
|
|
||||||
(_isLight ? _kDefaultBarLightBackgroundColor : _kDefaultBarDarkBackgroundColor);
|
|
||||||
}
|
|
||||||
final Color _barBackgroundColor;
|
final Color _barBackgroundColor;
|
||||||
|
|
||||||
/// Background color of the scaffold.
|
/// Background color of the scaffold.
|
||||||
///
|
///
|
||||||
/// Defaults to white or black depending on the [brightness].
|
/// Defaults to [CupertinoColors.systemBackground].
|
||||||
Color get scaffoldBackgroundColor {
|
Color get scaffoldBackgroundColor => _scaffoldBackgroundColor ?? _defaults.scaffoldBackgroundColor;
|
||||||
return _scaffoldBackgroundColor ??
|
|
||||||
(_isLight ? CupertinoColors.white : CupertinoColors.black);
|
|
||||||
}
|
|
||||||
final Color _scaffoldBackgroundColor;
|
final Color _scaffoldBackgroundColor;
|
||||||
|
|
||||||
/// Return an instance of the [CupertinoThemeData] whose property getters
|
/// Returns an instance of the [CupertinoThemeData] whose property getters
|
||||||
/// only return the construction time specifications with no derived values.
|
/// only return the construction time specifications with no derived values.
|
||||||
///
|
///
|
||||||
/// Used in Material themes to let unspecified properties fallback to Material
|
/// Used in Material themes to let unspecified properties fallback to Material
|
||||||
@ -242,30 +271,33 @@ class CupertinoThemeData extends Diagnosticable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a new `CupertinoThemeData` whose colors are from this `CupertinoThemeData`,
|
/// Returns a new `CupertinoThemeData` with all its colors resolved aginst the
|
||||||
/// but resolved aginst the given [BuildContext].
|
/// given [BuildContext].
|
||||||
///
|
///
|
||||||
/// It will be called in [CupertinoTheme.of].
|
/// Called by [CupertinoTheme.of] to resolve colors defined in the retrieved
|
||||||
|
/// [CupertinoThemeData].
|
||||||
@protected
|
@protected
|
||||||
CupertinoThemeData resolveFrom(BuildContext context, { bool nullOk = false }) {
|
CupertinoThemeData resolveFrom(BuildContext context, { bool nullOk = false }) {
|
||||||
Color convertColor(Color color) => CupertinoDynamicColor.resolve(color, context, nullOk: nullOk);
|
Color convertColor(Color color) => CupertinoDynamicColor.resolve(color, context, nullOk: nullOk);
|
||||||
|
|
||||||
return copyWith(
|
return CupertinoThemeData._rawWithDefaults(
|
||||||
primaryColor: convertColor(primaryColor),
|
_brightness,
|
||||||
primaryContrastingColor: convertColor(primaryContrastingColor),
|
convertColor(_primaryColor),
|
||||||
textTheme: textTheme?.resolveFrom(context, nullOk: nullOk),
|
convertColor(_primaryContrastingColor),
|
||||||
barBackgroundColor: convertColor(barBackgroundColor),
|
textTheme?.resolveFrom(context, nullOk: nullOk),
|
||||||
scaffoldBackgroundColor: convertColor(scaffoldBackgroundColor),
|
convertColor(_barBackgroundColor),
|
||||||
|
convertColor(_scaffoldBackgroundColor),
|
||||||
|
_defaults.resolveFrom(context, nullOk: nullOk),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a copy of [CupertinoThemeData] with specified attributes overridden.
|
/// Creates a copy of [CupertinoThemeData] with specified attributes overridden.
|
||||||
///
|
///
|
||||||
/// Only the current instance's specified attributes are copied instead of
|
/// Only the current instance's specified attributes are copied instead of
|
||||||
/// derived values. For instance, if the current [primaryColor] is implied
|
/// derived values. For instance, if the current [CupertinoThemeData.textTheme]
|
||||||
/// to be [CupertinoColors.activeOrange] due to the current [brightness],
|
/// is implied from the current [primaryColor] because it was not specified,
|
||||||
/// copying with a different [brightness] will also change the copy's
|
/// copying with a different [primaryColor] will also change the copy's implied
|
||||||
/// implied [primaryColor].
|
/// [textTheme].
|
||||||
CupertinoThemeData copyWith({
|
CupertinoThemeData copyWith({
|
||||||
Brightness brightness,
|
Brightness brightness,
|
||||||
Color primaryColor,
|
Color primaryColor,
|
||||||
@ -274,13 +306,14 @@ class CupertinoThemeData extends Diagnosticable {
|
|||||||
Color barBackgroundColor,
|
Color barBackgroundColor,
|
||||||
Color scaffoldBackgroundColor,
|
Color scaffoldBackgroundColor,
|
||||||
}) {
|
}) {
|
||||||
return CupertinoThemeData(
|
return CupertinoThemeData._rawWithDefaults(
|
||||||
brightness: brightness ?? _brightness,
|
brightness ?? _brightness,
|
||||||
primaryColor: primaryColor ?? _primaryColor,
|
primaryColor ?? _primaryColor,
|
||||||
primaryContrastingColor: primaryContrastingColor ?? _primaryContrastingColor,
|
primaryContrastingColor ?? _primaryContrastingColor,
|
||||||
textTheme: textTheme ?? _textTheme,
|
textTheme ?? _textTheme,
|
||||||
barBackgroundColor: barBackgroundColor ?? _barBackgroundColor,
|
barBackgroundColor ?? _barBackgroundColor,
|
||||||
scaffoldBackgroundColor: scaffoldBackgroundColor ?? _scaffoldBackgroundColor,
|
scaffoldBackgroundColor ?? _scaffoldBackgroundColor,
|
||||||
|
_defaults,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,13 +338,14 @@ class _NoDefaultCupertinoThemeData extends CupertinoThemeData {
|
|||||||
this.textTheme,
|
this.textTheme,
|
||||||
this.barBackgroundColor,
|
this.barBackgroundColor,
|
||||||
this.scaffoldBackgroundColor,
|
this.scaffoldBackgroundColor,
|
||||||
) : super.raw(
|
) : super._rawWithDefaults(
|
||||||
brightness,
|
brightness,
|
||||||
primaryColor,
|
primaryColor,
|
||||||
primaryContrastingColor,
|
primaryContrastingColor,
|
||||||
textTheme,
|
textTheme,
|
||||||
barBackgroundColor,
|
barBackgroundColor,
|
||||||
scaffoldBackgroundColor,
|
scaffoldBackgroundColor,
|
||||||
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -360,3 +394,98 @@ class _NoDefaultCupertinoThemeData extends CupertinoThemeData {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class _CupertinoThemeDefaults {
|
||||||
|
const _CupertinoThemeDefaults(
|
||||||
|
this.brightness,
|
||||||
|
this.primaryColor,
|
||||||
|
this.primaryContrastingColor,
|
||||||
|
this.barBackgroundColor,
|
||||||
|
this.scaffoldBackgroundColor,
|
||||||
|
this.textThemeDefaults,
|
||||||
|
);
|
||||||
|
|
||||||
|
final Brightness brightness;
|
||||||
|
final Color primaryColor;
|
||||||
|
final Color primaryContrastingColor;
|
||||||
|
final Color barBackgroundColor;
|
||||||
|
final Color scaffoldBackgroundColor;
|
||||||
|
final _CupertinoTextThemeDefaults textThemeDefaults;
|
||||||
|
|
||||||
|
_CupertinoThemeDefaults resolveFrom(BuildContext context, { @required bool nullOk }) {
|
||||||
|
assert(nullOk != null);
|
||||||
|
Color convertColor(Color color) => CupertinoDynamicColor.resolve(color, context, nullOk: nullOk);
|
||||||
|
|
||||||
|
return _CupertinoThemeDefaults(
|
||||||
|
brightness,
|
||||||
|
convertColor(primaryColor),
|
||||||
|
convertColor(primaryContrastingColor),
|
||||||
|
convertColor(barBackgroundColor),
|
||||||
|
convertColor(scaffoldBackgroundColor),
|
||||||
|
textThemeDefaults?.resolveFrom(context, nullOk: nullOk),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class _CupertinoTextThemeDefaults {
|
||||||
|
const _CupertinoTextThemeDefaults(
|
||||||
|
this.labelColor,
|
||||||
|
this.inactiveGray,
|
||||||
|
);
|
||||||
|
|
||||||
|
final Color labelColor;
|
||||||
|
final Color inactiveGray;
|
||||||
|
|
||||||
|
_CupertinoTextThemeDefaults resolveFrom(BuildContext context, { @required bool nullOk }) {
|
||||||
|
return _CupertinoTextThemeDefaults(
|
||||||
|
CupertinoDynamicColor.resolve(labelColor, context, nullOk: nullOk),
|
||||||
|
CupertinoDynamicColor.resolve(inactiveGray, context, nullOk: nullOk),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
CupertinoTextThemeData createDefaults({ @required Color primaryColor }) {
|
||||||
|
assert(primaryColor != null);
|
||||||
|
return _DefaultCupertinoTextThemeData(
|
||||||
|
primaryColor: primaryColor,
|
||||||
|
labelColor: labelColor,
|
||||||
|
inactiveGray: inactiveGray,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CupertinoTextThemeData with no text styles explicitly specified.
|
||||||
|
// The implementation of this class may need to be updated when any of the default
|
||||||
|
// text styles changes.
|
||||||
|
class _DefaultCupertinoTextThemeData extends CupertinoTextThemeData {
|
||||||
|
const _DefaultCupertinoTextThemeData({
|
||||||
|
@required this.labelColor,
|
||||||
|
@required this.inactiveGray,
|
||||||
|
@required Color primaryColor,
|
||||||
|
}) : assert(labelColor != null),
|
||||||
|
assert(inactiveGray != null),
|
||||||
|
assert(primaryColor != null),
|
||||||
|
super(primaryColor: primaryColor);
|
||||||
|
|
||||||
|
final Color labelColor;
|
||||||
|
final Color inactiveGray;
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextStyle get textStyle => super.textStyle.copyWith(color: labelColor);
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextStyle get tabLabelTextStyle => super.tabLabelTextStyle.copyWith(color: inactiveGray);
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextStyle get navTitleTextStyle => super.navTitleTextStyle.copyWith(color: labelColor);
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextStyle get navLargeTitleTextStyle => super.navLargeTitleTextStyle.copyWith(color: labelColor);
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextStyle get pickerTextStyle => super.pickerTextStyle.copyWith(color: labelColor);
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextStyle get dateTimePickerTextStyle => super.dateTimePickerTextStyle.copyWith(color: labelColor);
|
||||||
|
}
|
||||||
|
@ -59,7 +59,7 @@ class IconTheme extends InheritedTheme {
|
|||||||
/// IconThemeData theme = IconTheme.of(context);
|
/// IconThemeData theme = IconTheme.of(context);
|
||||||
/// ```
|
/// ```
|
||||||
static IconThemeData of(BuildContext context) {
|
static IconThemeData of(BuildContext context) {
|
||||||
final IconThemeData iconThemeData = _getInheritedIconThemeData(context);
|
final IconThemeData iconThemeData = _getInheritedIconThemeData(context).resolve(context);
|
||||||
return iconThemeData.isConcrete ? iconThemeData : const IconThemeData.fallback().merge(iconThemeData);
|
return iconThemeData.isConcrete ? iconThemeData : const IconThemeData.fallback().merge(iconThemeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ import 'dart:ui' as ui show lerpDouble;
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/painting.dart';
|
import 'package:flutter/painting.dart';
|
||||||
|
|
||||||
|
import 'framework.dart' show BuildContext;
|
||||||
|
|
||||||
/// Defines the color, opacity, and size of icons.
|
/// Defines the color, opacity, and size of icons.
|
||||||
///
|
///
|
||||||
/// Used by [IconTheme] to control the color, opacity, and size of icons in a
|
/// Used by [IconTheme] to control the color, opacity, and size of icons in a
|
||||||
@ -54,6 +56,24 @@ class IconThemeData extends Diagnosticable {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Called by [IconTheme.of] to convert this instance to an [IconThemeData]
|
||||||
|
/// that fits the given [BuildContext].
|
||||||
|
///
|
||||||
|
/// This method gives the ambient [IconThemeData] a chance to update itself,
|
||||||
|
/// after it's been retrieved by [IconTheme.of], and before being returned as
|
||||||
|
/// the final result. For instance, [CupertinoIconThemeData] overrides this method
|
||||||
|
/// to resolve [color], in case [color] is a [CupertinoDynamicColor] and needs
|
||||||
|
/// to be resolved against the given [BuildContext] before it can be used as a
|
||||||
|
/// regular [Color].
|
||||||
|
///
|
||||||
|
/// The default implementation returns this [IconThemeData] as-is.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [CupertinoIconThemeData.resolve] an implementation that resolves
|
||||||
|
/// [CupertinoIconThemeData.color] before returning.
|
||||||
|
IconThemeData resolve(BuildContext context) => this;
|
||||||
|
|
||||||
/// Whether all the properties of this object are non-null.
|
/// Whether all the properties of this object are non-null.
|
||||||
bool get isConcrete => color != null && opacity != null && size != null;
|
bool get isConcrete => color != null && opacity != null && size != null;
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ void main() {
|
|||||||
matching: find.byType(RichText),
|
matching: find.byType(RichText),
|
||||||
));
|
));
|
||||||
|
|
||||||
expect(actualActive.text.style.color.value, CupertinoColors.activeOrange.darkColor.value);
|
expect(actualActive.text.style.color, isSameColorAs(CupertinoColors.activeBlue.darkColor));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Use active icon', (WidgetTester tester) async {
|
testWidgets('Use active icon', (WidgetTester tester) async {
|
||||||
|
@ -306,7 +306,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(textStyle.color, CupertinoColors.white);
|
expect(textStyle.color, isSameColorAs(CupertinoColors.white));
|
||||||
BoxDecoration decoration = tester.widget<DecoratedBox>(
|
BoxDecoration decoration = tester.widget<DecoratedBox>(
|
||||||
find.descendant(
|
find.descendant(
|
||||||
of: find.byType(CupertinoButton),
|
of: find.byType(CupertinoButton),
|
||||||
@ -327,7 +327,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(textStyle.color.value, CupertinoColors.activeOrange.darkColor.value);
|
expect(textStyle.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -341,14 +341,14 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
expect(textStyle.color, CupertinoColors.black);
|
expect(textStyle.color, isSameColorAs(CupertinoColors.black));
|
||||||
decoration = tester.widget<DecoratedBox>(
|
decoration = tester.widget<DecoratedBox>(
|
||||||
find.descendant(
|
find.descendant(
|
||||||
of: find.byType(CupertinoButton),
|
of: find.byType(CupertinoButton),
|
||||||
matching: find.byType(DecoratedBox),
|
matching: find.byType(DecoratedBox),
|
||||||
),
|
),
|
||||||
).decoration;
|
).decoration;
|
||||||
expect(decoration.color.value, CupertinoColors.activeOrange.darkColor.value);
|
expect(decoration.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
38
packages/flutter/test/cupertino/icon_theme_data_test.dart
Normal file
38
packages/flutter/test/cupertino/icon_theme_data_test.dart
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2019 The Chromium Authors. 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/cupertino.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
testWidgets('IconTheme.of works', (WidgetTester tester) async {
|
||||||
|
const IconThemeData data = IconThemeData(color: Color(0xAAAAAAAA), opacity: 0.5, size: 16.0);
|
||||||
|
|
||||||
|
IconThemeData retrieved;
|
||||||
|
await tester.pumpWidget(
|
||||||
|
IconTheme(data: data, child: Builder(builder: (BuildContext context) {
|
||||||
|
retrieved = IconTheme.of(context);
|
||||||
|
return const SizedBox();
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(retrieved, data);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
IconTheme(
|
||||||
|
data: const CupertinoIconThemeData(color: CupertinoColors.systemBlue),
|
||||||
|
child: MediaQuery(
|
||||||
|
data: const MediaQueryData(platformBrightness: Brightness.dark),
|
||||||
|
child: Builder(builder: (BuildContext context) {
|
||||||
|
retrieved = IconTheme.of(context);
|
||||||
|
return const SizedBox();
|
||||||
|
},
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(retrieved.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
|
||||||
|
});
|
||||||
|
}
|
@ -133,7 +133,7 @@ void main() {
|
|||||||
matching: find.byType(DecoratedBox),
|
matching: find.byType(DecoratedBox),
|
||||||
)).decoration;
|
)).decoration;
|
||||||
|
|
||||||
expect(tabDecoration.color, const Color(0xCCF8F8F8));
|
expect(tabDecoration.color, isSameColorAs(const Color(0xF0F9F9F9))); // Inherited from theme.
|
||||||
|
|
||||||
await tester.tap(find.text('Tab 2'));
|
await tester.tap(find.text('Tab 2'));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
@ -159,7 +159,7 @@ void main() {
|
|||||||
matching: find.byType(DecoratedBox),
|
matching: find.byType(DecoratedBox),
|
||||||
)).decoration;
|
)).decoration;
|
||||||
|
|
||||||
expect(tabDecoration.color, const Color(0xB7212121));
|
expect(tabDecoration.color, isSameColorAs(const Color(0xF01D1D1D)));
|
||||||
|
|
||||||
final RichText tab1 = tester.widget(find.descendant(
|
final RichText tab1 = tester.widget(find.descendant(
|
||||||
of: find.text('Tab 1'),
|
of: find.text('Tab 1'),
|
||||||
|
@ -188,19 +188,18 @@ void main() {
|
|||||||
|
|
||||||
testWidgets('Nav bar respects themes', (WidgetTester tester) async {
|
testWidgets('Nav bar respects themes', (WidgetTester tester) async {
|
||||||
count = 0x000000;
|
count = 0x000000;
|
||||||
const CupertinoDynamicColor orange = CupertinoColors.activeOrange;
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
theme: const CupertinoThemeData(brightness: Brightness.dark),
|
theme: const CupertinoThemeData(brightness: Brightness.dark),
|
||||||
home: CupertinoNavigationBar(
|
home: CupertinoNavigationBar(
|
||||||
leading: CupertinoButton(
|
leading: CupertinoButton(
|
||||||
onPressed: () { },
|
onPressed: () { },
|
||||||
child: _ExpectStyles(color: orange.darkColor, index: 0x000001),
|
child: _ExpectStyles(color: CupertinoColors.systemBlue.darkColor, index: 0x000001),
|
||||||
),
|
),
|
||||||
middle: const _ExpectStyles(color: CupertinoColors.white, index: 0x000100),
|
middle: const _ExpectStyles(color: CupertinoColors.white, index: 0x000100),
|
||||||
trailing: CupertinoButton(
|
trailing: CupertinoButton(
|
||||||
onPressed: () { },
|
onPressed: () { },
|
||||||
child: _ExpectStyles(color: orange.darkColor, index: 0x010000),
|
child: _ExpectStyles(color: CupertinoColors.systemBlue.darkColor, index: 0x010000),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -1129,7 +1128,7 @@ class _ExpectStyles extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final TextStyle style = DefaultTextStyle.of(context).style;
|
final TextStyle style = DefaultTextStyle.of(context).style;
|
||||||
expect(style.color.value, color.value);
|
expect(style.color, isSameColorAs(color));
|
||||||
expect(style.fontFamily, '.SF Pro Text');
|
expect(style.fontFamily, '.SF Pro Text');
|
||||||
expect(style.fontSize, 17.0);
|
expect(style.fontSize, 17.0);
|
||||||
expect(style.letterSpacing, -0.41);
|
expect(style.letterSpacing, -0.41);
|
||||||
|
@ -226,7 +226,7 @@ void main() {
|
|||||||
// The transition's stack is ordered. The bottom middle is inserted first.
|
// The transition's stack is ordered. The bottom middle is inserted first.
|
||||||
final RenderParagraph bottomMiddle =
|
final RenderParagraph bottomMiddle =
|
||||||
tester.renderObject(flying(tester, find.text('Page 1')).first);
|
tester.renderObject(flying(tester, find.text('Page 1')).first);
|
||||||
expect(bottomMiddle.text.style.color, const Color(0xfffffaf4));
|
expect(bottomMiddle.text.style.color, const Color(0xFFF4F9FF));
|
||||||
expect(bottomMiddle.text.style.fontWeight, FontWeight.w600);
|
expect(bottomMiddle.text.style.fontWeight, FontWeight.w600);
|
||||||
expect(bottomMiddle.text.style.fontFamily, '.SF Pro Text');
|
expect(bottomMiddle.text.style.fontFamily, '.SF Pro Text');
|
||||||
expect(bottomMiddle.text.style.letterSpacing, -0.41);
|
expect(bottomMiddle.text.style.letterSpacing, -0.41);
|
||||||
@ -237,7 +237,7 @@ void main() {
|
|||||||
// are flipped.
|
// are flipped.
|
||||||
final RenderParagraph topBackLabel =
|
final RenderParagraph topBackLabel =
|
||||||
tester.renderObject(flying(tester, find.text('Page 1')).last);
|
tester.renderObject(flying(tester, find.text('Page 1')).last);
|
||||||
expect(topBackLabel.text.style.color, const Color(0xfffffaf4));
|
expect(topBackLabel.text.style.color, const Color(0xFFF4F9FF));
|
||||||
expect(topBackLabel.text.style.fontWeight, FontWeight.w600);
|
expect(topBackLabel.text.style.fontWeight, FontWeight.w600);
|
||||||
expect(topBackLabel.text.style.fontFamily, '.SF Pro Text');
|
expect(topBackLabel.text.style.fontFamily, '.SF Pro Text');
|
||||||
expect(topBackLabel.text.style.letterSpacing, -0.41);
|
expect(topBackLabel.text.style.letterSpacing, -0.41);
|
||||||
@ -246,14 +246,14 @@ void main() {
|
|||||||
|
|
||||||
// Move animation further a bit.
|
// Move animation further a bit.
|
||||||
await tester.pump(const Duration(milliseconds: 200));
|
await tester.pump(const Duration(milliseconds: 200));
|
||||||
expect(bottomMiddle.text.style.color, const Color(0xffffa923));
|
expect(bottomMiddle.text.style.color, const Color(0xFF2390FF));
|
||||||
expect(bottomMiddle.text.style.fontWeight, FontWeight.w400);
|
expect(bottomMiddle.text.style.fontWeight, FontWeight.w400);
|
||||||
expect(bottomMiddle.text.style.fontFamily, '.SF Pro Text');
|
expect(bottomMiddle.text.style.fontFamily, '.SF Pro Text');
|
||||||
expect(bottomMiddle.text.style.letterSpacing, -0.41);
|
expect(bottomMiddle.text.style.letterSpacing, -0.41);
|
||||||
|
|
||||||
checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.0);
|
checkOpacity(tester, flying(tester, find.text('Page 1')).first, 0.0);
|
||||||
|
|
||||||
expect(topBackLabel.text.style.color, const Color(0xffffa923));
|
expect(topBackLabel.text.style.color, const Color(0xFF2390FF));
|
||||||
expect(topBackLabel.text.style.fontWeight, FontWeight.w400);
|
expect(topBackLabel.text.style.fontWeight, FontWeight.w400);
|
||||||
expect(topBackLabel.text.style.fontFamily, '.SF Pro Text');
|
expect(topBackLabel.text.style.fontFamily, '.SF Pro Text');
|
||||||
expect(topBackLabel.text.style.letterSpacing, -0.41);
|
expect(topBackLabel.text.style.letterSpacing, -0.41);
|
||||||
|
@ -34,10 +34,11 @@ void main() {
|
|||||||
|
|
||||||
final RenderParagraph paragraph = tester.renderObject(find.text('1'));
|
final RenderParagraph paragraph = tester.renderObject(find.text('1'));
|
||||||
|
|
||||||
expect(paragraph.text.style, const TextStyle(
|
expect(paragraph.text.style.color, isSameColorAs(CupertinoColors.black));
|
||||||
|
expect(paragraph.text.style.copyWith(color: CupertinoColors.black), const TextStyle(
|
||||||
inherit: false,
|
inherit: false,
|
||||||
fontFamily: '.SF Pro Display',
|
fontFamily: '.SF Pro Display',
|
||||||
fontSize: 25.0,
|
fontSize: 21.0,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
letterSpacing: -0.41,
|
letterSpacing: -0.41,
|
||||||
color: CupertinoColors.black,
|
color: CupertinoColors.black,
|
||||||
|
@ -411,7 +411,7 @@ void main() {
|
|||||||
expect(decoratedBox.decoration.runtimeType, BoxDecoration);
|
expect(decoratedBox.decoration.runtimeType, BoxDecoration);
|
||||||
|
|
||||||
final BoxDecoration decoration = decoratedBox.decoration;
|
final BoxDecoration decoration = decoratedBox.decoration;
|
||||||
expect(decoration.color, CupertinoColors.white);
|
expect(decoration.color, isSameColorAs(CupertinoColors.white));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Overrides background color', (WidgetTester tester) async {
|
testWidgets('Overrides background color', (WidgetTester tester) async {
|
||||||
|
@ -290,7 +290,7 @@ void main() {
|
|||||||
DefaultTextStyle textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1'));
|
DefaultTextStyle textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1'));
|
||||||
IconTheme iconTheme = tester.widget(find.widgetWithIcon(IconTheme, const IconData(1)));
|
IconTheme iconTheme = tester.widget(find.widgetWithIcon(IconTheme, const IconData(1)));
|
||||||
|
|
||||||
expect(textStyle.style.color, CupertinoColors.white);
|
expect(textStyle.style.color, isSameColorAs(CupertinoColors.white));
|
||||||
expect(iconTheme.data.color, CupertinoColors.activeBlue);
|
expect(iconTheme.data.color, CupertinoColors.activeBlue);
|
||||||
|
|
||||||
await tester.tap(find.widgetWithIcon(IconTheme, const IconData(1)));
|
await tester.tap(find.widgetWithIcon(IconTheme, const IconData(1)));
|
||||||
@ -300,7 +300,7 @@ void main() {
|
|||||||
iconTheme = tester.widget(find.widgetWithIcon(IconTheme, const IconData(1)));
|
iconTheme = tester.widget(find.widgetWithIcon(IconTheme, const IconData(1)));
|
||||||
|
|
||||||
expect(textStyle.style.color, CupertinoColors.activeBlue);
|
expect(textStyle.style.color, CupertinoColors.activeBlue);
|
||||||
expect(iconTheme.data.color, CupertinoColors.white);
|
expect(iconTheme.data.color, isSameColorAs(CupertinoColors.white));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
@ -334,8 +334,8 @@ void main() {
|
|||||||
DefaultTextStyle textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1').first);
|
DefaultTextStyle textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1').first);
|
||||||
IconThemeData iconTheme = IconTheme.of(tester.element(find.byIcon(const IconData(1))));
|
IconThemeData iconTheme = IconTheme.of(tester.element(find.byIcon(const IconData(1))));
|
||||||
|
|
||||||
expect(textStyle.style.color, CupertinoColors.black);
|
expect(textStyle.style.color, isSameColorAs(CupertinoColors.black));
|
||||||
expect(iconTheme.color.value, CupertinoColors.activeOrange.darkColor.value);
|
expect(iconTheme.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
|
||||||
|
|
||||||
await tester.tap(find.byIcon(const IconData(1)));
|
await tester.tap(find.byIcon(const IconData(1)));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
@ -344,8 +344,8 @@ void main() {
|
|||||||
textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1').first);
|
textStyle = tester.widget(find.widgetWithText(DefaultTextStyle, 'Child 1').first);
|
||||||
iconTheme = IconTheme.of(tester.element(find.byIcon(const IconData(1))));
|
iconTheme = IconTheme.of(tester.element(find.byIcon(const IconData(1))));
|
||||||
|
|
||||||
expect(textStyle.style.color.value, CupertinoColors.activeOrange.darkColor.value);
|
expect(textStyle.style.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
|
||||||
expect(iconTheme.color, CupertinoColors.black);
|
expect(iconTheme.color, isSameColorAs(CupertinoColors.black));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -484,13 +484,13 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
await tester.tap(find.text('Child 2'));
|
await tester.tap(find.text('Child 2'));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
@ -499,7 +499,7 @@ void main() {
|
|||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
await tester.pumpWidget(setupSimpleSegmentedControl());
|
await tester.pumpWidget(setupSimpleSegmentedControl());
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
await tester.tap(find.text('Child 2'));
|
await tester.tap(find.text('Child 2'));
|
||||||
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
||||||
@ -552,7 +552,7 @@ void main() {
|
|||||||
expect(getRenderSegmentedControl(tester).selectedIndex, 0);
|
expect(getRenderSegmentedControl(tester).selectedIndex, 0);
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Null input for value results in no child initially selected', (WidgetTester tester) async {
|
testWidgets('Null input for value results in no child initially selected', (WidgetTester tester) async {
|
||||||
@ -582,15 +582,15 @@ void main() {
|
|||||||
|
|
||||||
expect(getRenderSegmentedControl(tester).selectedIndex, null);
|
expect(getRenderSegmentedControl(tester).selectedIndex, null);
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 0), isSameColorAs(CupertinoColors.white));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Long press changes background color of not-selected child', (WidgetTester tester) async {
|
testWidgets('Long press changes background color of not-selected child', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(setupSimpleSegmentedControl());
|
await tester.pumpWidget(setupSimpleSegmentedControl());
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
final Offset center = tester.getCenter(find.text('Child 2'));
|
final Offset center = tester.getCenter(find.text('Child 2'));
|
||||||
await tester.startGesture(center);
|
await tester.startGesture(center);
|
||||||
@ -604,14 +604,14 @@ void main() {
|
|||||||
await tester.pumpWidget(setupSimpleSegmentedControl());
|
await tester.pumpWidget(setupSimpleSegmentedControl());
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
final Offset center = tester.getCenter(find.text('Child 1'));
|
final Offset center = tester.getCenter(find.text('Child 1'));
|
||||||
await tester.startGesture(center);
|
await tester.startGesture(center);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Height of segmented control is determined by tallest widget', (WidgetTester tester) async {
|
testWidgets('Height of segmented control is determined by tallest widget', (WidgetTester tester) async {
|
||||||
@ -768,12 +768,12 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
await tester.tap(find.text('Child 2'));
|
await tester.tap(find.text('Child 2'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 0), isSameColorAs(CupertinoColors.white));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
||||||
|
|
||||||
await tester.tap(find.text('Child 2'));
|
await tester.tap(find.text('Child 2'));
|
||||||
@ -952,7 +952,7 @@ void main() {
|
|||||||
expect(getBackgroundColor(tester, 1), const Color(0xf8007aff));
|
expect(getBackgroundColor(tester, 1), const Color(0xf8007aff));
|
||||||
|
|
||||||
await tester.pump(const Duration(milliseconds: 40));
|
await tester.pump(const Duration(milliseconds: 40));
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 0), isSameColorAs(CupertinoColors.white));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1104,7 +1104,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
const Duration(milliseconds: 40),
|
const Duration(milliseconds: 40),
|
||||||
);
|
);
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 0), isSameColorAs(CupertinoColors.white));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1134,20 +1134,20 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
await tester.startGesture(tester.getCenter(find.text('B')));
|
await tester.startGesture(tester.getCenter(find.text('B')));
|
||||||
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
||||||
|
|
||||||
expect(getBackgroundColor(tester, 1), const Color(0x33007aff));
|
expect(getBackgroundColor(tester, 1), const Color(0x33007aff));
|
||||||
expect(getBackgroundColor(tester, 2), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 2), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
await tester.startGesture(tester.getCenter(find.text('C')));
|
await tester.startGesture(tester.getCenter(find.text('C')));
|
||||||
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
||||||
|
|
||||||
// Press on C has no effect while B is held down.
|
// Press on C has no effect while B is held down.
|
||||||
expect(getBackgroundColor(tester, 1), const Color(0x33007aff));
|
expect(getBackgroundColor(tester, 1), const Color(0x33007aff));
|
||||||
expect(getBackgroundColor(tester, 2), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 2), isSameColorAs(CupertinoColors.white));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Transition is triggered while a transition is already occurring', (WidgetTester tester) async {
|
testWidgets('Transition is triggered while a transition is already occurring', (WidgetTester tester) async {
|
||||||
@ -1199,12 +1199,12 @@ void main() {
|
|||||||
await tester.pump(const Duration(milliseconds: 40));
|
await tester.pump(const Duration(milliseconds: 40));
|
||||||
// B background color has reached unselected state.
|
// B background color has reached unselected state.
|
||||||
expect(getBackgroundColor(tester, 0), const Color(0xff7bbaff));
|
expect(getBackgroundColor(tester, 0), const Color(0xff7bbaff));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
expect(getBackgroundColor(tester, 2), const Color(0x64007aff));
|
expect(getBackgroundColor(tester, 2), const Color(0x64007aff));
|
||||||
|
|
||||||
await tester.pump(const Duration(milliseconds: 100));
|
await tester.pump(const Duration(milliseconds: 100));
|
||||||
// A background color has reached unselected state.
|
// A background color has reached unselected state.
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 0), isSameColorAs(CupertinoColors.white));
|
||||||
expect(getBackgroundColor(tester, 2), const Color(0xe0007aff));
|
expect(getBackgroundColor(tester, 2), const Color(0xe0007aff));
|
||||||
|
|
||||||
await tester.pump(const Duration(milliseconds: 40));
|
await tester.pump(const Duration(milliseconds: 40));
|
||||||
@ -1237,7 +1237,7 @@ void main() {
|
|||||||
await tester.pump(const Duration(milliseconds: 40));
|
await tester.pump(const Duration(milliseconds: 40));
|
||||||
// A and B finish transitioning.
|
// A and B finish transitioning.
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 0), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Add segment while animation is running', (WidgetTester tester) async {
|
testWidgets('Add segment while animation is running', (WidgetTester tester) async {
|
||||||
@ -1273,19 +1273,19 @@ void main() {
|
|||||||
await tester.tap(find.text('B'));
|
await tester.tap(find.text('B'));
|
||||||
|
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 0), isSameColorAs(CupertinoColors.white));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 3), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 3), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
await tester.pump(const Duration(milliseconds: 40));
|
await tester.pump(const Duration(milliseconds: 40));
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 0), isSameColorAs(CupertinoColors.white));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 3), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 3), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
await tester.pump(const Duration(milliseconds: 150));
|
await tester.pump(const Duration(milliseconds: 150));
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 0), isSameColorAs(CupertinoColors.white));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
expect(getBackgroundColor(tester, 1), CupertinoColors.activeBlue);
|
||||||
expect(getBackgroundColor(tester, 3), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 3), isSameColorAs(CupertinoColors.white));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Remove segment while animation is running', (WidgetTester tester) async {
|
testWidgets('Remove segment while animation is running', (WidgetTester tester) async {
|
||||||
@ -1373,15 +1373,15 @@ void main() {
|
|||||||
|
|
||||||
await tester.pump(const Duration(milliseconds: 40));
|
await tester.pump(const Duration(milliseconds: 40));
|
||||||
expect(getBackgroundColor(tester, 0), const Color(0xff3d9aff));
|
expect(getBackgroundColor(tester, 0), const Color(0xff3d9aff));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
await tester.pump(const Duration(milliseconds: 40));
|
await tester.pump(const Duration(milliseconds: 40));
|
||||||
expect(getBackgroundColor(tester, 0), const Color(0xff7bbaff));
|
expect(getBackgroundColor(tester, 0), const Color(0xff7bbaff));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
|
|
||||||
await tester.pump(const Duration(milliseconds: 100));
|
await tester.pump(const Duration(milliseconds: 100));
|
||||||
expect(getBackgroundColor(tester, 0), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 0), isSameColorAs(CupertinoColors.white));
|
||||||
expect(getBackgroundColor(tester, 1), CupertinoColors.white);
|
expect(getBackgroundColor(tester, 1), isSameColorAs(CupertinoColors.white));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Golden Test Placeholder Widget', (WidgetTester tester) async {
|
testWidgets('Golden Test Placeholder Widget', (WidgetTester tester) async {
|
||||||
|
@ -427,10 +427,9 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const CupertinoDynamicColor orange = CupertinoColors.activeOrange;
|
|
||||||
expect(
|
expect(
|
||||||
find.byType(CupertinoSlider),
|
find.byType(CupertinoSlider),
|
||||||
paints..rrect(color: orange.darkColor),
|
paints..rrect(color: CupertinoColors.systemBlue.darkColor),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -340,7 +340,7 @@ void main() {
|
|||||||
matching: find.byType(DecoratedBox),
|
matching: find.byType(DecoratedBox),
|
||||||
)).decoration;
|
)).decoration;
|
||||||
|
|
||||||
expect(tabDecoration.color, const Color(0xCCF8F8F8));
|
expect(tabDecoration.color, isSameColorAs(const Color(0xF0F9F9F9))); // Inherited from theme.
|
||||||
|
|
||||||
await tester.tap(find.text('Tab 2'));
|
await tester.tap(find.text('Tab 2'));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
@ -366,7 +366,7 @@ void main() {
|
|||||||
matching: find.byType(DecoratedBox),
|
matching: find.byType(DecoratedBox),
|
||||||
)).decoration;
|
)).decoration;
|
||||||
|
|
||||||
expect(tabDecoration.color, const Color(0xB7212121));
|
expect(tabDecoration.color, isSameColorAs(const Color(0xF01D1D1D)));
|
||||||
|
|
||||||
final RichText tab1 = tester.widget(find.descendant(
|
final RichText tab1 = tester.widget(find.descendant(
|
||||||
of: find.text('Tab 1'),
|
of: find.text('Tab 1'),
|
||||||
@ -378,7 +378,7 @@ void main() {
|
|||||||
of: find.text('Tab 2'),
|
of: find.text('Tab 2'),
|
||||||
matching: find.byType(RichText),
|
matching: find.byType(RichText),
|
||||||
));
|
));
|
||||||
expect(tab2.text.style.color.value, CupertinoColors.systemRed.darkColor.value);
|
expect(tab2.text.style.color, isSameColorAs(CupertinoColors.systemRed.darkColor));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Tab contents are padded when there are view insets', (WidgetTester tester) async {
|
testWidgets('Tab contents are padded when there are view insets', (WidgetTester tester) async {
|
||||||
|
@ -2749,7 +2749,7 @@ void main() {
|
|||||||
tester.renderObject<RenderEditable>(
|
tester.renderObject<RenderEditable>(
|
||||||
find.byElementPredicate((Element element) => element.renderObject is RenderEditable)
|
find.byElementPredicate((Element element) => element.renderObject is RenderEditable)
|
||||||
).text.style.color,
|
).text.style.color,
|
||||||
CupertinoColors.white,
|
isSameColorAs(CupertinoColors.white),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -2899,7 +2899,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(renderEditable.cursorColor, CupertinoColors.activeOrange.darkColor);
|
expect(renderEditable.cursorColor, CupertinoColors.activeBlue.darkColor);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
const CupertinoApp(
|
const CupertinoApp(
|
||||||
|
@ -59,7 +59,7 @@ void main() {
|
|||||||
primaryColor: CupertinoColors.destructiveRed,
|
primaryColor: CupertinoColors.destructiveRed,
|
||||||
));
|
));
|
||||||
|
|
||||||
expect(theme.textTheme.actionTextStyle.color, CupertinoColors.destructiveRed);
|
expect(theme.textTheme.actionTextStyle.color, isSameColorAs(CupertinoColors.destructiveRed));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Dependent attribute can be overridden from cascaded value', (WidgetTester tester) async {
|
testWidgets('Dependent attribute can be overridden from cascaded value', (WidgetTester tester) async {
|
||||||
@ -71,9 +71,9 @@ void main() {
|
|||||||
));
|
));
|
||||||
|
|
||||||
// The brightness still cascaded down to the background color.
|
// The brightness still cascaded down to the background color.
|
||||||
expect(theme.scaffoldBackgroundColor, CupertinoColors.black);
|
expect(theme.scaffoldBackgroundColor, isSameColorAs(CupertinoColors.black));
|
||||||
// But not to the font color which we overrode.
|
// But not to the font color which we overrode.
|
||||||
expect(theme.textTheme.textStyle.color, CupertinoColors.black);
|
expect(theme.textTheme.textStyle.color, isSameColorAs(CupertinoColors.black));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
@ -125,24 +125,32 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final CupertinoThemeData theme = await testTheme(tester, originalTheme.copyWith(
|
final CupertinoThemeData theme = await testTheme(tester, originalTheme.copyWith(
|
||||||
primaryColor: CupertinoColors.activeGreen,
|
primaryColor: CupertinoColors.systemGreen,
|
||||||
));
|
));
|
||||||
|
|
||||||
expect(theme.brightness, Brightness.dark);
|
expect(theme.brightness, Brightness.dark);
|
||||||
expect(theme.primaryColor.value, CupertinoColors.systemGreen.darkColor.value);
|
expect(theme.primaryColor, isSameColorAs(CupertinoColors.systemGreen.darkColor));
|
||||||
// Now check calculated derivatives.
|
// Now check calculated derivatives.
|
||||||
expect(theme.textTheme.actionTextStyle.color.value, CupertinoColors.systemGreen.darkColor.value);
|
expect(theme.textTheme.actionTextStyle.color, isSameColorAs(CupertinoColors.systemGreen.darkColor));
|
||||||
expect(theme.scaffoldBackgroundColor.value, CupertinoColors.black.value);
|
expect(theme.scaffoldBackgroundColor, isSameColorAs(CupertinoColors.black));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
testWidgets("Theme has default IconThemeData, which is derived from the theme's primary color", (WidgetTester tester) async {
|
testWidgets("Theme has default IconThemeData, which is derived from the theme's primary color", (WidgetTester tester) async {
|
||||||
const Color primaryColor = CupertinoColors.destructiveRed;
|
const CupertinoDynamicColor primaryColor = CupertinoColors.destructiveRed;
|
||||||
const CupertinoThemeData themeData = CupertinoThemeData(primaryColor: primaryColor);
|
const CupertinoThemeData themeData = CupertinoThemeData(primaryColor: primaryColor);
|
||||||
|
|
||||||
final IconThemeData resultingIconTheme = await testIconTheme(tester, themeData);
|
final IconThemeData resultingIconTheme = await testIconTheme(tester, themeData);
|
||||||
|
|
||||||
expect(resultingIconTheme.color, themeData.primaryColor);
|
expect(resultingIconTheme.color, themeData.primaryColor);
|
||||||
|
|
||||||
|
// Works in dark mode if primaryColor is a CupertinoDynamicColor.
|
||||||
|
final Color darkColor = (await testIconTheme(
|
||||||
|
tester,
|
||||||
|
themeData.copyWith(brightness: Brightness.dark),
|
||||||
|
)).color;
|
||||||
|
|
||||||
|
expect(darkColor, isSameColorAs(primaryColor.darkColor));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('IconTheme.of creates a dependency on iconTheme', (WidgetTester tester) async {
|
testWidgets('IconTheme.of creates a dependency on iconTheme', (WidgetTester tester) async {
|
||||||
@ -155,4 +163,56 @@ void main() {
|
|||||||
expect(buildCount, 2);
|
expect(buildCount, 2);
|
||||||
expect(iconTheme.color, CupertinoColors.activeOrange);
|
expect(iconTheme.color, CupertinoColors.activeOrange);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Brightness currentBrightness;
|
||||||
|
void colorMatches(Color componentColor, CupertinoDynamicColor expectedDynamicColor) {
|
||||||
|
switch (currentBrightness) {
|
||||||
|
case Brightness.light:
|
||||||
|
expect(componentColor, isSameColorAs(expectedDynamicColor.color));
|
||||||
|
break;
|
||||||
|
case Brightness.dark:
|
||||||
|
expect(componentColor, isSameColorAs(expectedDynamicColor.darkColor));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Function dynamicColorsTestGroup = () {
|
||||||
|
testWidgets('CupertinoTheme.of resolves colors', (WidgetTester tester) async {
|
||||||
|
final CupertinoThemeData data = CupertinoThemeData(brightness: currentBrightness, primaryColor: CupertinoColors.systemRed);
|
||||||
|
final CupertinoThemeData theme = await testTheme(tester, data);
|
||||||
|
|
||||||
|
expect(data.primaryColor, isSameColorAs(CupertinoColors.systemRed.color));
|
||||||
|
colorMatches(theme.primaryColor, CupertinoColors.systemRed);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('CupertinoTheme.of resolves default values', (WidgetTester tester) async {
|
||||||
|
const CupertinoDynamicColor primaryColor = CupertinoColors.systemRed;
|
||||||
|
final CupertinoThemeData data = CupertinoThemeData(brightness: currentBrightness, primaryColor: primaryColor);
|
||||||
|
|
||||||
|
const CupertinoDynamicColor barBackgroundColor = CupertinoDynamicColor.withBrightness(
|
||||||
|
color: Color(0xF0F9F9F9),
|
||||||
|
darkColor: Color(0xF01D1D1D),
|
||||||
|
);
|
||||||
|
|
||||||
|
final CupertinoThemeData theme = await testTheme(tester, data);
|
||||||
|
|
||||||
|
colorMatches(theme.primaryContrastingColor, CupertinoColors.systemBackground);
|
||||||
|
colorMatches(theme.barBackgroundColor, barBackgroundColor);
|
||||||
|
colorMatches(theme.scaffoldBackgroundColor, CupertinoColors.systemBackground);
|
||||||
|
colorMatches(theme.textTheme.textStyle.color, CupertinoColors.label);
|
||||||
|
colorMatches(theme.textTheme.actionTextStyle.color, primaryColor);
|
||||||
|
colorMatches(theme.textTheme.tabLabelTextStyle.color, CupertinoColors.inactiveGray);
|
||||||
|
colorMatches(theme.textTheme.navTitleTextStyle.color, CupertinoColors.label);
|
||||||
|
colorMatches(theme.textTheme.navLargeTitleTextStyle.color, CupertinoColors.label);
|
||||||
|
colorMatches(theme.textTheme.navActionTextStyle.color, primaryColor);
|
||||||
|
colorMatches(theme.textTheme.pickerTextStyle.color, CupertinoColors.label);
|
||||||
|
colorMatches(theme.textTheme.dateTimePickerTextStyle.color, CupertinoColors.label);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
currentBrightness = Brightness.light;
|
||||||
|
group('light colors', dynamicColorsTestGroup);
|
||||||
|
|
||||||
|
currentBrightness = Brightness.dark;
|
||||||
|
group('dark colors', dynamicColorsTestGroup);
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,12 @@ const Matcher isInCard = _IsInCard();
|
|||||||
/// * [isInCard], the opposite.
|
/// * [isInCard], the opposite.
|
||||||
const Matcher isNotInCard = _IsNotInCard();
|
const Matcher isNotInCard = _IsNotInCard();
|
||||||
|
|
||||||
|
/// Asserts that the object represents the same color as [color] when used to paint.
|
||||||
|
///
|
||||||
|
/// Specifically this matcher checks the object is of type [Color] and its [Color.value]
|
||||||
|
/// equals to that of the given [color].
|
||||||
|
Matcher isSameColorAs(Color color) => _ColorMatcher(targetColor: color);
|
||||||
|
|
||||||
/// Asserts that an object's toString() is a plausible one-line description.
|
/// Asserts that an object's toString() is a plausible one-line description.
|
||||||
///
|
///
|
||||||
/// Specifically, this matcher checks that the string does not contains newline
|
/// Specifically, this matcher checks that the string does not contains newline
|
||||||
@ -1609,6 +1615,24 @@ class _CoversSameAreaAs extends Matcher {
|
|||||||
description.add('covers expected area and only expected area');
|
description.add('covers expected area and only expected area');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ColorMatcher extends Matcher {
|
||||||
|
const _ColorMatcher({
|
||||||
|
@required this.targetColor,
|
||||||
|
}) : assert(targetColor != null);
|
||||||
|
|
||||||
|
final Color targetColor;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
|
||||||
|
if (item is Color)
|
||||||
|
return item.value == targetColor.value;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Description describe(Description description) => description.add('matches color $targetColor');
|
||||||
|
}
|
||||||
|
|
||||||
Future<ui.Image> _captureImage(Element element) {
|
Future<ui.Image> _captureImage(Element element) {
|
||||||
RenderObject renderObject = element.renderObject;
|
RenderObject renderObject = element.renderObject;
|
||||||
while (!renderObject.isRepaintBoundary) {
|
while (!renderObject.isRepaintBoundary) {
|
||||||
|
@ -237,6 +237,33 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('isSameColorAs', () {
|
||||||
|
expect(
|
||||||
|
const Color(0x87654321),
|
||||||
|
isSameColorAs(_CustomColor(0x87654321)),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
_CustomColor(0x87654321),
|
||||||
|
isSameColorAs(const Color(0x87654321)),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
const Color(0x12345678),
|
||||||
|
isNot(isSameColorAs(_CustomColor(0x87654321))),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
_CustomColor(0x87654321),
|
||||||
|
isNot(isSameColorAs(const Color(0x12345678))),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
_CustomColor(0xFF123456),
|
||||||
|
isSameColorAs(_CustomColor(0xFF123456)..isEqual = false),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
group('coversSameAreaAs', () {
|
group('coversSameAreaAs', () {
|
||||||
test('empty Paths', () {
|
test('empty Paths', () {
|
||||||
expect(
|
expect(
|
||||||
@ -676,3 +703,14 @@ class _FakeSemanticsNode extends SemanticsNode {
|
|||||||
@override
|
@override
|
||||||
SemanticsData getSemanticsData() => data;
|
SemanticsData getSemanticsData() => data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _CustomColor extends Color {
|
||||||
|
_CustomColor(int value) : super(value);
|
||||||
|
bool isEqual;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(dynamic other) => isEqual ?? super == other;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => hashValues(super.hashCode, isEqual);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user