mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
This PR fixes #92525 and introduces the following changes according to [latest iOS HIG](https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS): - `CupertinoButton` now has a `size` property (type `enum CupertinoButtonSize`, values sm/md/lg, default `lg`) that allows the devs to apply new iOS 15+ button styles - Previously `CupertinoButton` had a larger padding when no background color was specified. With the new HIG, that is no longer the case - `CupertinoButton` now has a `.tinted` constructor that renders a translucent background (transparency % is brightness-dependent) and uses a different foreground color compared to `.filled` - `CupertinoButton` now uses the `actionTextStyle` TextStyle from the given theme - `CupertinoButton`'s child IconTheme's size will always be x1.2 the given TextStyle's size - `CupertinoTextThemeData` now has a `actionSmallTextStyle` property to use with small buttons (including a default `_kDefaultActionSmallTextStyle` TextStyle) Preview & example:  > **NOTE**: there is a discrepancy in dark mode button foreground color between the default CupertinoTheme and the HIG. A separate issue will be opened for this. ~EDIT: issue reported here https://github.com/flutter/flutter/issues/152846~ EDIT2: fixed by #153039 !  ## Example ```dart import 'package:flutter/cupertino.dart'; const Widget body = Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Icon( CupertinoIcons.play_fill, ), Text("Play"), ], ); void main() => runApp( CupertinoApp( home: Container( child: Wrap( direction: Axis.horizontal, children: <Widget>[ // header Text(''), Text('Plain'), Text('Grey'), Text('Tinted'), Text('Filled'), // small Text('Small'), CupertinoButton( child: body, onPressed: () {}, size: CupertinoButtonSize.small, ), CupertinoButton.tinted( child: body, onPressed: () {}, size: CupertinoButtonSize.small, color: CupertinoColors.systemGrey, ), CupertinoButton.tinted( child: body, onPressed: () {}, size: CupertinoButtonSize.small, ), CupertinoButton.filled( child: body, onPressed: () {}, size: CupertinoButtonSize.small, ), // medium Text('Medium'), CupertinoButton( child: body, onPressed: () {}, size: CupertinoButtonSize.medium, ), CupertinoButton.tinted( child: body, onPressed: () {}, size: CupertinoButtonSize.medium, color: CupertinoColors.systemGrey, ), CupertinoButton.tinted( child: body, onPressed: () {}, size: CupertinoButtonSize.medium, ), CupertinoButton.filled( child: body, onPressed: () {}, size: CupertinoButtonSize.medium, ), // large Text('Large'), CupertinoButton( child: body, onPressed: () {}, size: CupertinoButtonSize.large, ), CupertinoButton.tinted( child: body, onPressed: () {}, color: CupertinoColors.systemGrey, size: CupertinoButtonSize.large, ), CupertinoButton.tinted( child: body, onPressed: () {}, size: CupertinoButtonSize.large, ), CupertinoButton.filled( child: body, onPressed: () {}, size: CupertinoButtonSize.large, ), ].map((Widget w) => SizedBox(width: 110, height: 70, child: Center(child: w))).toList(), ), ) ), ); ``` *List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.* *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
This commit is contained in:
parent
2f0415f37b
commit
dae3a87d93
@ -63,7 +63,6 @@ class _EditableTextToolbarBuilderExampleAppState extends State<EditableTextToolb
|
|||||||
// buttons depending on the platform.
|
// buttons depending on the platform.
|
||||||
children: editableTextState.contextMenuButtonItems.map((ContextMenuButtonItem buttonItem) {
|
children: editableTextState.contextMenuButtonItems.map((ContextMenuButtonItem buttonItem) {
|
||||||
return CupertinoButton(
|
return CupertinoButton(
|
||||||
borderRadius: null,
|
|
||||||
color: const Color(0xffaaaa00),
|
color: const Color(0xffaaaa00),
|
||||||
disabledColor: const Color(0xffaaaaff),
|
disabledColor: const Color(0xffaaaaff),
|
||||||
onPressed: buttonItem.onPressed,
|
onPressed: buttonItem.onPressed,
|
||||||
|
@ -10,14 +10,33 @@ import 'package:flutter/widgets.dart';
|
|||||||
|
|
||||||
import 'colors.dart';
|
import 'colors.dart';
|
||||||
import 'constants.dart';
|
import 'constants.dart';
|
||||||
|
import 'text_theme.dart';
|
||||||
import 'theme.dart';
|
import 'theme.dart';
|
||||||
|
|
||||||
// Measured against iOS 12 in Xcode.
|
// Measured against iOS (17) [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS).
|
||||||
const EdgeInsets _kButtonPadding = EdgeInsets.all(16.0);
|
|
||||||
const EdgeInsets _kBackgroundButtonPadding = EdgeInsets.symmetric(
|
/// The size of a [CupertinoButton].
|
||||||
vertical: 14.0,
|
/// Based on the iOS (17) [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS).
|
||||||
horizontal: 64.0,
|
enum CupertinoButtonSize {
|
||||||
);
|
/// Displays a smaller button with round sides and smaller text (uses [CupertinoTextThemeData.actionSmallTextStyle]).
|
||||||
|
small,
|
||||||
|
/// Displays a medium sized button with round sides and regular-sized text.
|
||||||
|
medium,
|
||||||
|
/// Displays a (classic) large button with rounded edges and regular-sized text.
|
||||||
|
large,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The style of a [CupertinoButton] that changes the style of the button's background.
|
||||||
|
///
|
||||||
|
/// Based on the iOS Human Interface Guidelines (https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS).
|
||||||
|
enum _CupertinoButtonStyle {
|
||||||
|
/// No background or border, primary foreground color.
|
||||||
|
plain,
|
||||||
|
/// Translucent background, primary foreground color.
|
||||||
|
tinted,
|
||||||
|
/// Solid background, contrasting foreground color.
|
||||||
|
filled,
|
||||||
|
}
|
||||||
|
|
||||||
/// An iOS-style button.
|
/// An iOS-style button.
|
||||||
///
|
///
|
||||||
@ -48,12 +67,13 @@ class CupertinoButton extends StatefulWidget {
|
|||||||
const CupertinoButton({
|
const CupertinoButton({
|
||||||
super.key,
|
super.key,
|
||||||
required this.child,
|
required this.child,
|
||||||
|
this.sizeStyle = CupertinoButtonSize.large,
|
||||||
this.padding,
|
this.padding,
|
||||||
this.color,
|
this.color,
|
||||||
this.disabledColor = CupertinoColors.quaternarySystemFill,
|
this.disabledColor = CupertinoColors.quaternarySystemFill,
|
||||||
this.minSize = kMinInteractiveDimensionCupertino,
|
this.minSize,
|
||||||
this.pressedOpacity = 0.4,
|
this.pressedOpacity = 0.4,
|
||||||
this.borderRadius = const BorderRadius.all(Radius.circular(8.0)),
|
this.borderRadius,
|
||||||
this.alignment = Alignment.center,
|
this.alignment = Alignment.center,
|
||||||
this.focusColor,
|
this.focusColor,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
@ -61,7 +81,34 @@ class CupertinoButton extends StatefulWidget {
|
|||||||
this.autofocus = false,
|
this.autofocus = false,
|
||||||
required this.onPressed,
|
required this.onPressed,
|
||||||
}) : assert(pressedOpacity == null || (pressedOpacity >= 0.0 && pressedOpacity <= 1.0)),
|
}) : assert(pressedOpacity == null || (pressedOpacity >= 0.0 && pressedOpacity <= 1.0)),
|
||||||
_filled = false;
|
_style = _CupertinoButtonStyle.plain;
|
||||||
|
|
||||||
|
/// Creates an iOS-style button with a tinted background.
|
||||||
|
///
|
||||||
|
/// The background color is derived from the [CupertinoTheme]'s `primaryColor` + transparency.
|
||||||
|
/// The foreground color is the [CupertinoTheme]'s `primaryColor`.
|
||||||
|
///
|
||||||
|
/// To specify a custom background color, use the [color] argument of the
|
||||||
|
/// default constructor.
|
||||||
|
///
|
||||||
|
/// To match the iOS "grey" button style, set [color] to [CupertinoColors.systemGrey].
|
||||||
|
const CupertinoButton.tinted({
|
||||||
|
super.key,
|
||||||
|
required this.child,
|
||||||
|
this.sizeStyle = CupertinoButtonSize.large,
|
||||||
|
this.padding,
|
||||||
|
this.color,
|
||||||
|
this.disabledColor = CupertinoColors.tertiarySystemFill,
|
||||||
|
this.minSize,
|
||||||
|
this.pressedOpacity = 0.4,
|
||||||
|
this.borderRadius,
|
||||||
|
this.alignment = Alignment.center,
|
||||||
|
this.focusColor,
|
||||||
|
this.focusNode,
|
||||||
|
this.onFocusChange,
|
||||||
|
this.autofocus = false,
|
||||||
|
required this.onPressed,
|
||||||
|
}) : _style = _CupertinoButtonStyle.tinted;
|
||||||
|
|
||||||
/// Creates an iOS-style button with a filled background.
|
/// Creates an iOS-style button with a filled background.
|
||||||
///
|
///
|
||||||
@ -72,11 +119,12 @@ class CupertinoButton extends StatefulWidget {
|
|||||||
const CupertinoButton.filled({
|
const CupertinoButton.filled({
|
||||||
super.key,
|
super.key,
|
||||||
required this.child,
|
required this.child,
|
||||||
|
this.sizeStyle = CupertinoButtonSize.large,
|
||||||
this.padding,
|
this.padding,
|
||||||
this.disabledColor = CupertinoColors.quaternarySystemFill,
|
this.disabledColor = CupertinoColors.tertiarySystemFill,
|
||||||
this.minSize = kMinInteractiveDimensionCupertino,
|
this.minSize,
|
||||||
this.pressedOpacity = 0.4,
|
this.pressedOpacity = 0.4,
|
||||||
this.borderRadius = const BorderRadius.all(Radius.circular(8.0)),
|
this.borderRadius,
|
||||||
this.alignment = Alignment.center,
|
this.alignment = Alignment.center,
|
||||||
this.focusColor,
|
this.focusColor,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
@ -85,7 +133,7 @@ class CupertinoButton extends StatefulWidget {
|
|||||||
required this.onPressed,
|
required this.onPressed,
|
||||||
}) : assert(pressedOpacity == null || (pressedOpacity >= 0.0 && pressedOpacity <= 1.0)),
|
}) : assert(pressedOpacity == null || (pressedOpacity >= 0.0 && pressedOpacity <= 1.0)),
|
||||||
color = null,
|
color = null,
|
||||||
_filled = true;
|
_style = _CupertinoButtonStyle.filled;
|
||||||
|
|
||||||
/// The widget below this widget in the tree.
|
/// The widget below this widget in the tree.
|
||||||
///
|
///
|
||||||
@ -133,9 +181,14 @@ class CupertinoButton extends StatefulWidget {
|
|||||||
|
|
||||||
/// The radius of the button's corners when it has a background color.
|
/// The radius of the button's corners when it has a background color.
|
||||||
///
|
///
|
||||||
/// Defaults to round corners of 8 logical pixels.
|
/// Defaults to [kCupertinoButtonSizeBorderRadius], based on [sizeStyle].
|
||||||
final BorderRadius? borderRadius;
|
final BorderRadius? borderRadius;
|
||||||
|
|
||||||
|
/// The size of the button.
|
||||||
|
///
|
||||||
|
/// Defaults to [CupertinoButtonSize.large].
|
||||||
|
final CupertinoButtonSize sizeStyle;
|
||||||
|
|
||||||
/// The alignment of the button's [child].
|
/// The alignment of the button's [child].
|
||||||
///
|
///
|
||||||
/// Typically buttons are sized to be just big enough to contain the child and its
|
/// Typically buttons are sized to be just big enough to contain the child and its
|
||||||
@ -166,7 +219,7 @@ class CupertinoButton extends StatefulWidget {
|
|||||||
/// {@macro flutter.widgets.Focus.autofocus}
|
/// {@macro flutter.widgets.Focus.autofocus}
|
||||||
final bool autofocus;
|
final bool autofocus;
|
||||||
|
|
||||||
final bool _filled;
|
final _CupertinoButtonStyle _style;
|
||||||
|
|
||||||
/// Whether the button is enabled or disabled. Buttons are disabled by default. To
|
/// Whether the button is enabled or disabled. Buttons are disabled by default. To
|
||||||
/// enable a button, set its [onPressed] property to a non-null value.
|
/// enable a button, set its [onPressed] property to a non-null value.
|
||||||
@ -273,15 +326,24 @@ class _CupertinoButtonState extends State<CupertinoButton> with SingleTickerProv
|
|||||||
final bool enabled = widget.enabled;
|
final bool enabled = widget.enabled;
|
||||||
final CupertinoThemeData themeData = CupertinoTheme.of(context);
|
final CupertinoThemeData themeData = CupertinoTheme.of(context);
|
||||||
final Color primaryColor = themeData.primaryColor;
|
final Color primaryColor = themeData.primaryColor;
|
||||||
final Color? backgroundColor = widget.color == null
|
final Color? backgroundColor = (
|
||||||
? (widget._filled ? primaryColor : null)
|
widget.color == null
|
||||||
: CupertinoDynamicColor.maybeResolve(widget.color, context);
|
? widget._style != _CupertinoButtonStyle.plain
|
||||||
|
? primaryColor
|
||||||
final Color foregroundColor = backgroundColor != null
|
: null
|
||||||
|
: CupertinoDynamicColor.maybeResolve(widget.color, context)
|
||||||
|
)?.withOpacity(
|
||||||
|
widget._style == _CupertinoButtonStyle.tinted
|
||||||
|
? CupertinoTheme.brightnessOf(context) == Brightness.light
|
||||||
|
? kCupertinoButtonTintedOpacityLight
|
||||||
|
: kCupertinoButtonTintedOpacityDark
|
||||||
|
: widget.color?.opacity ?? 1.0,
|
||||||
|
);
|
||||||
|
final Color foregroundColor = widget._style == _CupertinoButtonStyle.filled
|
||||||
? themeData.primaryContrastingColor
|
? themeData.primaryContrastingColor
|
||||||
: enabled
|
: enabled
|
||||||
? primaryColor
|
? primaryColor
|
||||||
: CupertinoDynamicColor.resolve(CupertinoColors.placeholderText, context);
|
: CupertinoDynamicColor.resolve(CupertinoColors.tertiaryLabel, context);
|
||||||
|
|
||||||
final Color effectiveFocusOutlineColor = widget.focusColor ??
|
final Color effectiveFocusOutlineColor = widget.focusColor ??
|
||||||
HSLColor
|
HSLColor
|
||||||
@ -291,8 +353,17 @@ class _CupertinoButtonState extends State<CupertinoButton> with SingleTickerProv
|
|||||||
.withSaturation(kCupertinoFocusColorSaturation)
|
.withSaturation(kCupertinoFocusColorSaturation)
|
||||||
.toColor();
|
.toColor();
|
||||||
|
|
||||||
final TextStyle textStyle = themeData.textTheme.textStyle.copyWith(color: foregroundColor);
|
final TextStyle textStyle = (
|
||||||
final IconThemeData iconTheme = IconTheme.of(context).copyWith(color: foregroundColor);
|
widget.sizeStyle == CupertinoButtonSize.small
|
||||||
|
? themeData.textTheme.actionSmallTextStyle
|
||||||
|
: themeData.textTheme.actionTextStyle
|
||||||
|
).copyWith(color: foregroundColor);
|
||||||
|
final IconThemeData iconTheme = IconTheme.of(context).copyWith(
|
||||||
|
color: foregroundColor,
|
||||||
|
size: textStyle.fontSize != null
|
||||||
|
? textStyle.fontSize! * 1.2
|
||||||
|
: kCupertinoButtonDefaultIconSize,
|
||||||
|
);
|
||||||
|
|
||||||
return MouseRegion(
|
return MouseRegion(
|
||||||
cursor: enabled && kIsWeb ? SystemMouseCursors.click : MouseCursor.defer,
|
cursor: enabled && kIsWeb ? SystemMouseCursors.click : MouseCursor.defer,
|
||||||
@ -311,12 +382,10 @@ class _CupertinoButtonState extends State<CupertinoButton> with SingleTickerProv
|
|||||||
child: Semantics(
|
child: Semantics(
|
||||||
button: true,
|
button: true,
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: widget.minSize == null
|
constraints: BoxConstraints(
|
||||||
? const BoxConstraints()
|
minWidth: widget.minSize ?? kCupertinoButtonMinSize[widget.sizeStyle] ?? kMinInteractiveDimensionCupertino,
|
||||||
: BoxConstraints(
|
minHeight: widget.minSize ?? kCupertinoButtonMinSize[widget.sizeStyle] ?? kMinInteractiveDimensionCupertino,
|
||||||
minWidth: widget.minSize!,
|
),
|
||||||
minHeight: widget.minSize!,
|
|
||||||
),
|
|
||||||
child: FadeTransition(
|
child: FadeTransition(
|
||||||
opacity: _opacityAnimation,
|
opacity: _opacityAnimation,
|
||||||
child: DecoratedBox(
|
child: DecoratedBox(
|
||||||
@ -330,15 +399,13 @@ class _CupertinoButtonState extends State<CupertinoButton> with SingleTickerProv
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
borderRadius: widget.borderRadius,
|
borderRadius: widget.borderRadius ?? kCupertinoButtonSizeBorderRadius[widget.sizeStyle],
|
||||||
color: backgroundColor != null && !enabled
|
color: backgroundColor != null && !enabled
|
||||||
? CupertinoDynamicColor.resolve(widget.disabledColor, context)
|
? CupertinoDynamicColor.resolve(widget.disabledColor, context)
|
||||||
: backgroundColor,
|
: backgroundColor,
|
||||||
),
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: widget.padding ?? (backgroundColor != null
|
padding: widget.padding ?? kCupertinoButtonPadding[widget.sizeStyle]!,
|
||||||
? _kBackgroundButtonPadding
|
|
||||||
: _kButtonPadding),
|
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: widget.alignment,
|
alignment: widget.alignment,
|
||||||
widthFactor: 1.0,
|
widthFactor: 1.0,
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
/// @docImport 'package:flutter/material.dart';
|
/// @docImport 'package:flutter/material.dart';
|
||||||
library;
|
library;
|
||||||
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
import 'button.dart';
|
||||||
|
|
||||||
/// The minimum dimension of any interactive region according to the iOS Human
|
/// The minimum dimension of any interactive region according to the iOS Human
|
||||||
/// Interface Guidelines.
|
/// Interface Guidelines.
|
||||||
///
|
///
|
||||||
@ -31,3 +35,55 @@ const double kMinInteractiveDimensionCupertino = 44.0;
|
|||||||
const double kCupertinoFocusColorOpacity = 0.80,
|
const double kCupertinoFocusColorOpacity = 0.80,
|
||||||
kCupertinoFocusColorBrightness = 0.69,
|
kCupertinoFocusColorBrightness = 0.69,
|
||||||
kCupertinoFocusColorSaturation = 0.835;
|
kCupertinoFocusColorSaturation = 0.835;
|
||||||
|
|
||||||
|
/// Opacity values for the background of a [CupertinoButton.tinted].
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * <https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS>
|
||||||
|
const double kCupertinoButtonTintedOpacityLight = 0.12,
|
||||||
|
kCupertinoButtonTintedOpacityDark = 0.26;
|
||||||
|
|
||||||
|
/// The default value for [IconThemeData.size] of [CupertinoButton.child].
|
||||||
|
///
|
||||||
|
/// Set to match the most-frequent size of icons in iOS (matches md/lg).
|
||||||
|
///
|
||||||
|
/// Used only when the [CupertinoTextThemeData.actionTextStyle] or [CupertinoTextThemeData.actionSmallTextStyle]
|
||||||
|
/// has a null [TextStyle.fontSize].
|
||||||
|
const double kCupertinoButtonDefaultIconSize = 20.0;
|
||||||
|
|
||||||
|
/// The padding values for the different [CupertinoButtonSize]s.
|
||||||
|
///
|
||||||
|
/// Based on the iOS (17) [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS).
|
||||||
|
const Map<CupertinoButtonSize, EdgeInsetsGeometry> kCupertinoButtonPadding = <CupertinoButtonSize, EdgeInsetsGeometry>{
|
||||||
|
CupertinoButtonSize.small: EdgeInsets.symmetric(
|
||||||
|
vertical: 6,
|
||||||
|
horizontal: 12,
|
||||||
|
),
|
||||||
|
CupertinoButtonSize.medium: EdgeInsets.symmetric(
|
||||||
|
vertical: 10,
|
||||||
|
horizontal: 15,
|
||||||
|
),
|
||||||
|
CupertinoButtonSize.large: EdgeInsets.symmetric(
|
||||||
|
vertical: 16,
|
||||||
|
horizontal: 20,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The border radius values for the different [CupertinoButtonSize]s.
|
||||||
|
///
|
||||||
|
/// Based on the iOS (17) [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS).
|
||||||
|
final Map<CupertinoButtonSize, BorderRadius> kCupertinoButtonSizeBorderRadius = <CupertinoButtonSize, BorderRadius>{
|
||||||
|
CupertinoButtonSize.small: BorderRadius.circular(40),
|
||||||
|
CupertinoButtonSize.medium: BorderRadius.circular(40),
|
||||||
|
CupertinoButtonSize.large: BorderRadius.circular(12),
|
||||||
|
};
|
||||||
|
|
||||||
|
/// The minimum size of a [CupertinoButton] based on the [CupertinoButtonSize].
|
||||||
|
///
|
||||||
|
/// Based on the iOS (17) [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS).
|
||||||
|
const Map<CupertinoButtonSize, double> kCupertinoButtonMinSize = <CupertinoButtonSize, double>{
|
||||||
|
CupertinoButtonSize.small: 28,
|
||||||
|
CupertinoButtonSize.medium: 32,
|
||||||
|
CupertinoButtonSize.large: 44,
|
||||||
|
};
|
||||||
|
@ -133,7 +133,6 @@ class _CupertinoTextSelectionToolbarButtonState extends State<CupertinoTextSelec
|
|||||||
color: isPressed
|
color: isPressed
|
||||||
? _kToolbarPressedColor.resolveFrom(context)
|
? _kToolbarPressedColor.resolveFrom(context)
|
||||||
: CupertinoColors.transparent,
|
: CupertinoColors.transparent,
|
||||||
borderRadius: null,
|
|
||||||
disabledColor: CupertinoColors.transparent,
|
disabledColor: CupertinoColors.transparent,
|
||||||
// This CupertinoButton does not actually handle the onPressed callback,
|
// This CupertinoButton does not actually handle the onPressed callback,
|
||||||
// this is only here to correctly enable/disable the button (see
|
// this is only here to correctly enable/disable the button (see
|
||||||
|
@ -30,6 +30,7 @@ const TextStyle _kDefaultTextStyle = TextStyle(
|
|||||||
// field.
|
// field.
|
||||||
//
|
//
|
||||||
// Values derived from https://developer.apple.com/design/resources/.
|
// Values derived from https://developer.apple.com/design/resources/.
|
||||||
|
// See [iOS 17 + iPadOS 17 UI Kit](https://www.figma.com/community/file/1248375255495415511) for details.
|
||||||
const TextStyle _kDefaultActionTextStyle = TextStyle(
|
const TextStyle _kDefaultActionTextStyle = TextStyle(
|
||||||
inherit: false,
|
inherit: false,
|
||||||
fontFamily: 'CupertinoSystemText',
|
fontFamily: 'CupertinoSystemText',
|
||||||
@ -39,6 +40,21 @@ const TextStyle _kDefaultActionTextStyle = TextStyle(
|
|||||||
decoration: TextDecoration.none,
|
decoration: TextDecoration.none,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Please update _TextThemeDefaultsBuilder 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/.
|
||||||
|
// See [iOS 17 + iPadOS 17 UI Kit](https://www.figma.com/community/file/1248375255495415511) for details.
|
||||||
|
const TextStyle _kDefaultActionSmallTextStyle = TextStyle(
|
||||||
|
inherit: false,
|
||||||
|
fontFamily: 'CupertinoSystemText',
|
||||||
|
fontSize: 15.0,
|
||||||
|
letterSpacing: -0.23,
|
||||||
|
color: CupertinoColors.activeBlue,
|
||||||
|
decoration: TextDecoration.none,
|
||||||
|
);
|
||||||
|
|
||||||
// Please update _TextThemeDefaultsBuilder accordingly after changing the default
|
// Please update _TextThemeDefaultsBuilder accordingly after changing the default
|
||||||
// color here, as their implementation depends on the default value of the color
|
// color here, as their implementation depends on the default value of the color
|
||||||
// field.
|
// field.
|
||||||
@ -131,6 +147,7 @@ class CupertinoTextThemeData with Diagnosticable {
|
|||||||
Color primaryColor = CupertinoColors.systemBlue,
|
Color primaryColor = CupertinoColors.systemBlue,
|
||||||
TextStyle? textStyle,
|
TextStyle? textStyle,
|
||||||
TextStyle? actionTextStyle,
|
TextStyle? actionTextStyle,
|
||||||
|
TextStyle? actionSmallTextStyle,
|
||||||
TextStyle? tabLabelTextStyle,
|
TextStyle? tabLabelTextStyle,
|
||||||
TextStyle? navTitleTextStyle,
|
TextStyle? navTitleTextStyle,
|
||||||
TextStyle? navLargeTitleTextStyle,
|
TextStyle? navLargeTitleTextStyle,
|
||||||
@ -142,6 +159,7 @@ class CupertinoTextThemeData with Diagnosticable {
|
|||||||
primaryColor,
|
primaryColor,
|
||||||
textStyle,
|
textStyle,
|
||||||
actionTextStyle,
|
actionTextStyle,
|
||||||
|
actionSmallTextStyle,
|
||||||
tabLabelTextStyle,
|
tabLabelTextStyle,
|
||||||
navTitleTextStyle,
|
navTitleTextStyle,
|
||||||
navLargeTitleTextStyle,
|
navLargeTitleTextStyle,
|
||||||
@ -155,6 +173,7 @@ class CupertinoTextThemeData with Diagnosticable {
|
|||||||
this._primaryColor,
|
this._primaryColor,
|
||||||
this._textStyle,
|
this._textStyle,
|
||||||
this._actionTextStyle,
|
this._actionTextStyle,
|
||||||
|
this._actionSmallTextStyle,
|
||||||
this._tabLabelTextStyle,
|
this._tabLabelTextStyle,
|
||||||
this._navTitleTextStyle,
|
this._navTitleTextStyle,
|
||||||
this._navLargeTitleTextStyle,
|
this._navLargeTitleTextStyle,
|
||||||
@ -176,6 +195,12 @@ class CupertinoTextThemeData with Diagnosticable {
|
|||||||
return _actionTextStyle ?? _defaults.actionTextStyle(primaryColor: _primaryColor);
|
return _actionTextStyle ?? _defaults.actionTextStyle(primaryColor: _primaryColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final TextStyle? _actionSmallTextStyle;
|
||||||
|
/// The [TextStyle] of interactive text content such as text in a small button.
|
||||||
|
TextStyle get actionSmallTextStyle {
|
||||||
|
return _actionSmallTextStyle ?? _defaults.actionSmallTextStyle(primaryColor: _primaryColor);
|
||||||
|
}
|
||||||
|
|
||||||
final TextStyle? _tabLabelTextStyle;
|
final TextStyle? _tabLabelTextStyle;
|
||||||
/// The [TextStyle] of unselected tabs.
|
/// The [TextStyle] of unselected tabs.
|
||||||
TextStyle get tabLabelTextStyle => _tabLabelTextStyle ?? _defaults.tabLabelTextStyle;
|
TextStyle get tabLabelTextStyle => _tabLabelTextStyle ?? _defaults.tabLabelTextStyle;
|
||||||
@ -216,6 +241,7 @@ class CupertinoTextThemeData with Diagnosticable {
|
|||||||
CupertinoDynamicColor.maybeResolve(_primaryColor, context),
|
CupertinoDynamicColor.maybeResolve(_primaryColor, context),
|
||||||
_resolveTextStyle(_textStyle, context),
|
_resolveTextStyle(_textStyle, context),
|
||||||
_resolveTextStyle(_actionTextStyle, context),
|
_resolveTextStyle(_actionTextStyle, context),
|
||||||
|
_resolveTextStyle(_actionSmallTextStyle, context),
|
||||||
_resolveTextStyle(_tabLabelTextStyle, context),
|
_resolveTextStyle(_tabLabelTextStyle, context),
|
||||||
_resolveTextStyle(_navTitleTextStyle, context),
|
_resolveTextStyle(_navTitleTextStyle, context),
|
||||||
_resolveTextStyle(_navLargeTitleTextStyle, context),
|
_resolveTextStyle(_navLargeTitleTextStyle, context),
|
||||||
@ -231,6 +257,7 @@ class CupertinoTextThemeData with Diagnosticable {
|
|||||||
Color? primaryColor,
|
Color? primaryColor,
|
||||||
TextStyle? textStyle,
|
TextStyle? textStyle,
|
||||||
TextStyle? actionTextStyle,
|
TextStyle? actionTextStyle,
|
||||||
|
TextStyle? actionSmallTextStyle,
|
||||||
TextStyle? tabLabelTextStyle,
|
TextStyle? tabLabelTextStyle,
|
||||||
TextStyle? navTitleTextStyle,
|
TextStyle? navTitleTextStyle,
|
||||||
TextStyle? navLargeTitleTextStyle,
|
TextStyle? navLargeTitleTextStyle,
|
||||||
@ -243,6 +270,7 @@ class CupertinoTextThemeData with Diagnosticable {
|
|||||||
primaryColor ?? _primaryColor,
|
primaryColor ?? _primaryColor,
|
||||||
textStyle ?? _textStyle,
|
textStyle ?? _textStyle,
|
||||||
actionTextStyle ?? _actionTextStyle,
|
actionTextStyle ?? _actionTextStyle,
|
||||||
|
actionSmallTextStyle ?? _actionSmallTextStyle,
|
||||||
tabLabelTextStyle ?? _tabLabelTextStyle,
|
tabLabelTextStyle ?? _tabLabelTextStyle,
|
||||||
navTitleTextStyle ?? _navTitleTextStyle,
|
navTitleTextStyle ?? _navTitleTextStyle,
|
||||||
navLargeTitleTextStyle ?? _navLargeTitleTextStyle,
|
navLargeTitleTextStyle ?? _navLargeTitleTextStyle,
|
||||||
@ -258,6 +286,7 @@ class CupertinoTextThemeData with Diagnosticable {
|
|||||||
const CupertinoTextThemeData defaultData = CupertinoTextThemeData();
|
const CupertinoTextThemeData defaultData = CupertinoTextThemeData();
|
||||||
properties.add(DiagnosticsProperty<TextStyle>('textStyle', textStyle, defaultValue: defaultData.textStyle));
|
properties.add(DiagnosticsProperty<TextStyle>('textStyle', textStyle, defaultValue: defaultData.textStyle));
|
||||||
properties.add(DiagnosticsProperty<TextStyle>('actionTextStyle', actionTextStyle, defaultValue: defaultData.actionTextStyle));
|
properties.add(DiagnosticsProperty<TextStyle>('actionTextStyle', actionTextStyle, defaultValue: defaultData.actionTextStyle));
|
||||||
|
properties.add(DiagnosticsProperty<TextStyle>('actionSmallTextStyle', actionSmallTextStyle, defaultValue: defaultData.actionSmallTextStyle));
|
||||||
properties.add(DiagnosticsProperty<TextStyle>('tabLabelTextStyle', tabLabelTextStyle, defaultValue: defaultData.tabLabelTextStyle));
|
properties.add(DiagnosticsProperty<TextStyle>('tabLabelTextStyle', tabLabelTextStyle, defaultValue: defaultData.tabLabelTextStyle));
|
||||||
properties.add(DiagnosticsProperty<TextStyle>('navTitleTextStyle', navTitleTextStyle, defaultValue: defaultData.navTitleTextStyle));
|
properties.add(DiagnosticsProperty<TextStyle>('navTitleTextStyle', navTitleTextStyle, defaultValue: defaultData.navTitleTextStyle));
|
||||||
properties.add(DiagnosticsProperty<TextStyle>('navLargeTitleTextStyle', navLargeTitleTextStyle, defaultValue: defaultData.navLargeTitleTextStyle));
|
properties.add(DiagnosticsProperty<TextStyle>('navLargeTitleTextStyle', navLargeTitleTextStyle, defaultValue: defaultData.navLargeTitleTextStyle));
|
||||||
@ -279,6 +308,7 @@ class CupertinoTextThemeData with Diagnosticable {
|
|||||||
&& other._primaryColor == _primaryColor
|
&& other._primaryColor == _primaryColor
|
||||||
&& other._textStyle == _textStyle
|
&& other._textStyle == _textStyle
|
||||||
&& other._actionTextStyle == _actionTextStyle
|
&& other._actionTextStyle == _actionTextStyle
|
||||||
|
&& other._actionSmallTextStyle == _actionSmallTextStyle
|
||||||
&& other._tabLabelTextStyle == _tabLabelTextStyle
|
&& other._tabLabelTextStyle == _tabLabelTextStyle
|
||||||
&& other._navTitleTextStyle == _navTitleTextStyle
|
&& other._navTitleTextStyle == _navTitleTextStyle
|
||||||
&& other._navLargeTitleTextStyle == _navLargeTitleTextStyle
|
&& other._navLargeTitleTextStyle == _navLargeTitleTextStyle
|
||||||
@ -293,6 +323,7 @@ class CupertinoTextThemeData with Diagnosticable {
|
|||||||
_primaryColor,
|
_primaryColor,
|
||||||
_textStyle,
|
_textStyle,
|
||||||
_actionTextStyle,
|
_actionTextStyle,
|
||||||
|
_actionSmallTextStyle,
|
||||||
_tabLabelTextStyle,
|
_tabLabelTextStyle,
|
||||||
_navTitleTextStyle,
|
_navTitleTextStyle,
|
||||||
_navLargeTitleTextStyle,
|
_navLargeTitleTextStyle,
|
||||||
@ -327,6 +358,7 @@ class _TextThemeDefaultsBuilder {
|
|||||||
TextStyle get dateTimePickerTextStyle => _applyLabelColor(_kDefaultDateTimePickerTextStyle, labelColor);
|
TextStyle get dateTimePickerTextStyle => _applyLabelColor(_kDefaultDateTimePickerTextStyle, labelColor);
|
||||||
|
|
||||||
TextStyle actionTextStyle({ Color? primaryColor }) => _kDefaultActionTextStyle.copyWith(color: primaryColor);
|
TextStyle actionTextStyle({ Color? primaryColor }) => _kDefaultActionTextStyle.copyWith(color: primaryColor);
|
||||||
|
TextStyle actionSmallTextStyle({ Color? primaryColor }) => _kDefaultActionSmallTextStyle.copyWith(color: primaryColor);
|
||||||
TextStyle navActionTextStyle({ Color? primaryColor }) => actionTextStyle(primaryColor: primaryColor);
|
TextStyle navActionTextStyle({ Color? primaryColor }) => actionTextStyle(primaryColor: primaryColor);
|
||||||
|
|
||||||
_TextThemeDefaultsBuilder resolveFrom(BuildContext context) {
|
_TextThemeDefaultsBuilder resolveFrom(BuildContext context) {
|
||||||
|
@ -27,8 +27,8 @@ void main() {
|
|||||||
final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
|
final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
|
||||||
expect(
|
expect(
|
||||||
buttonBox.size,
|
buttonBox.size,
|
||||||
// 1 10px character + 16px * 2 is smaller than the default 44px minimum.
|
// 1 10px character + 20px * 2 = 50.0
|
||||||
const Size.square(44.0),
|
const Size(50.0, 44.0),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ void main() {
|
|||||||
final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
|
final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
|
||||||
expect(
|
expect(
|
||||||
buttonBox.size,
|
buttonBox.size,
|
||||||
// 1 10px character + 16px * 2 is smaller than defined 60.0px minimum
|
// 1 10px character + 20px * 2 = 50.0 (is smaller than minSize: 60.0)
|
||||||
const Size.square(minSize),
|
const Size.square(minSize),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -59,8 +59,8 @@ void main() {
|
|||||||
final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
|
final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
|
||||||
expect(
|
expect(
|
||||||
buttonBox.size.width,
|
buttonBox.size.width,
|
||||||
// 4 10px character + 16px * 2 = 72.
|
// 4 10px character + 20px * 2 = 80.0
|
||||||
72.0,
|
80.0,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -129,17 +129,37 @@ void main() {
|
|||||||
expect(align.alignment, Alignment.centerLeft);
|
expect(align.alignment, Alignment.centerLeft);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Button with background is wider', (WidgetTester tester) async {
|
testWidgets('Button size changes depending on size property', (WidgetTester tester) async {
|
||||||
|
const Widget child = Text('X', style: testStyle);
|
||||||
|
|
||||||
await tester.pumpWidget(boilerplate(child: const CupertinoButton(
|
await tester.pumpWidget(boilerplate(child: const CupertinoButton(
|
||||||
onPressed: null,
|
onPressed: null,
|
||||||
color: Color(0xFFFFFFFF),
|
sizeStyle: CupertinoButtonSize.small,
|
||||||
child: Text('X', style: testStyle),
|
child: child,
|
||||||
)));
|
)));
|
||||||
final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
|
final RenderBox buttonBox = tester.renderObject(find.byType(CupertinoButton));
|
||||||
expect(
|
expect(
|
||||||
buttonBox.size.width,
|
buttonBox.size,
|
||||||
// 1 10px character + 64 * 2 = 138 for buttons with background.
|
const Size(34.0, 28.0)
|
||||||
138.0,
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(boilerplate(child: const CupertinoButton(
|
||||||
|
onPressed: null,
|
||||||
|
sizeStyle: CupertinoButtonSize.medium,
|
||||||
|
child: child,
|
||||||
|
)));
|
||||||
|
expect(
|
||||||
|
buttonBox.size,
|
||||||
|
const Size(40.0, 32.0),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(boilerplate(child: const CupertinoButton(
|
||||||
|
onPressed: null,
|
||||||
|
child: child,
|
||||||
|
)));
|
||||||
|
expect(
|
||||||
|
buttonBox.size,
|
||||||
|
const Size(50.0, 44.0),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -404,8 +424,27 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
expect(textStyle.color, isSameColorAs(CupertinoColors.activeBlue));
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: CupertinoButton.tinted(
|
||||||
|
onPressed: () { },
|
||||||
|
child: Builder(builder: (BuildContext context) {
|
||||||
|
textStyle = DefaultTextStyle.of(context).style;
|
||||||
|
return const Placeholder();
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
expect(textStyle.color, CupertinoColors.activeBlue);
|
expect(textStyle.color, CupertinoColors.activeBlue);
|
||||||
|
BoxDecoration decoration = tester.widget<DecoratedBox>(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(CupertinoButton),
|
||||||
|
matching: find.byType(DecoratedBox),
|
||||||
|
),
|
||||||
|
).decoration as BoxDecoration;
|
||||||
|
expect(decoration.color, isSameColorAs(CupertinoColors.activeBlue.withOpacity(0.12)));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -418,15 +457,14 @@ void main() {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(textStyle.color, isSameColorAs(CupertinoColors.white));
|
expect(textStyle.color, isSameColorAs(CupertinoColors.white));
|
||||||
BoxDecoration 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 as BoxDecoration;
|
).decoration as BoxDecoration;
|
||||||
expect(decoration.color, CupertinoColors.activeBlue);
|
expect(decoration.color, isSameColorAs(CupertinoColors.activeBlue));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -442,6 +480,27 @@ void main() {
|
|||||||
);
|
);
|
||||||
expect(textStyle.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
|
expect(textStyle.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
theme: const CupertinoThemeData(brightness: Brightness.dark),
|
||||||
|
home: CupertinoButton.tinted(
|
||||||
|
onPressed: () { },
|
||||||
|
child: Builder(builder: (BuildContext context) {
|
||||||
|
textStyle = DefaultTextStyle.of(context).style;
|
||||||
|
return const Placeholder();
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(textStyle.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
|
||||||
|
decoration = tester.widget<DecoratedBox>(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(CupertinoButton),
|
||||||
|
matching: find.byType(DecoratedBox),
|
||||||
|
),
|
||||||
|
).decoration as BoxDecoration;
|
||||||
|
expect(decoration.color, isSameColorAs(CupertinoColors.activeBlue.darkColor.withOpacity(0.26)));
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
theme: const CupertinoThemeData(brightness: Brightness.dark),
|
theme: const CupertinoThemeData(brightness: Brightness.dark),
|
||||||
@ -464,6 +523,14 @@ void main() {
|
|||||||
expect(decoration.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
|
expect(decoration.color, isSameColorAs(CupertinoColors.systemBlue.darkColor));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets("All CupertinoButton const maps keys' match the available style sizes", (WidgetTester tester) async {
|
||||||
|
for (final CupertinoButtonSize size in CupertinoButtonSize.values) {
|
||||||
|
expect(kCupertinoButtonPadding[size], isNotNull);
|
||||||
|
expect(kCupertinoButtonSizeBorderRadius[size], isNotNull);
|
||||||
|
expect(kCupertinoButtonMinSize[size], isNotNull);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('Hovering over Cupertino button updates cursor to clickable on Web', (WidgetTester tester) async {
|
testWidgets('Hovering over Cupertino button updates cursor to clickable on Web', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -612,32 +679,57 @@ void main() {
|
|||||||
expect(focusNode.hasFocus, isFalse);
|
expect(focusNode.hasFocus, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('IconThemeData is not replaced by CupertinoButton', (WidgetTester tester) async {
|
testWidgets('IconThemeData falls back to default value when the TextStyle has a null size', (WidgetTester tester) async {
|
||||||
const IconThemeData givenIconTheme = IconThemeData(size: 12.0);
|
const IconThemeData defaultIconTheme = IconThemeData(size: kCupertinoButtonDefaultIconSize);
|
||||||
|
|
||||||
IconThemeData? actualIconTheme;
|
IconThemeData? actualIconTheme;
|
||||||
|
|
||||||
|
// Large size.
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
|
theme: const CupertinoThemeData(
|
||||||
|
textTheme: CupertinoTextThemeData(
|
||||||
|
actionTextStyle: TextStyle(),
|
||||||
|
),
|
||||||
|
),
|
||||||
home: Center(
|
home: Center(
|
||||||
child: IconTheme(
|
child: CupertinoButton(
|
||||||
data: givenIconTheme,
|
onPressed: () {},
|
||||||
child: CupertinoButton(
|
child: Builder(
|
||||||
onPressed: () {},
|
builder: (BuildContext context) {
|
||||||
child: Builder(
|
actualIconTheme = IconTheme.of(context);
|
||||||
builder: (BuildContext context) {
|
|
||||||
actualIconTheme = IconTheme.of(context);
|
|
||||||
|
|
||||||
return const Placeholder();
|
return const Placeholder();
|
||||||
}
|
}
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
expect(actualIconTheme?.size, defaultIconTheme.size);
|
||||||
|
|
||||||
expect(actualIconTheme?.size, givenIconTheme.size);
|
// Small size.
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
theme: const CupertinoThemeData(
|
||||||
|
textTheme: CupertinoTextThemeData(
|
||||||
|
actionSmallTextStyle: TextStyle(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
home: Center(
|
||||||
|
child: CupertinoButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: Builder(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
actualIconTheme = IconTheme.of(context);
|
||||||
|
|
||||||
|
return const Placeholder();
|
||||||
|
}
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@ void main() {
|
|||||||
expect(theme.actionTextStyle.letterSpacing, -0.41);
|
expect(theme.actionTextStyle.letterSpacing, -0.41);
|
||||||
expect(theme.actionTextStyle.fontWeight, null);
|
expect(theme.actionTextStyle.fontWeight, null);
|
||||||
|
|
||||||
|
// ActionSmallTextStyle 15 -0.23 (aka "Subheadline/Regular")
|
||||||
|
expect(theme.actionSmallTextStyle.fontSize, 15);
|
||||||
|
expect(theme.actionSmallTextStyle.fontFamily, 'CupertinoSystemText');
|
||||||
|
expect(theme.actionSmallTextStyle.letterSpacing, -0.23);
|
||||||
|
expect(theme.actionSmallTextStyle.fontWeight, null);
|
||||||
|
|
||||||
// TextStyle 17 -0.41
|
// TextStyle 17 -0.41
|
||||||
expect(theme.tabLabelTextStyle.fontSize, 10);
|
expect(theme.tabLabelTextStyle.fontSize, 10);
|
||||||
expect(theme.tabLabelTextStyle.fontFamily, 'CupertinoSystemText');
|
expect(theme.tabLabelTextStyle.fontFamily, 'CupertinoSystemText');
|
||||||
|
@ -189,6 +189,7 @@ void main() {
|
|||||||
'applyThemeToAll',
|
'applyThemeToAll',
|
||||||
'textStyle',
|
'textStyle',
|
||||||
'actionTextStyle',
|
'actionTextStyle',
|
||||||
|
'actionSmallTextStyle',
|
||||||
'tabLabelTextStyle',
|
'tabLabelTextStyle',
|
||||||
'navTitleTextStyle',
|
'navTitleTextStyle',
|
||||||
'navLargeTitleTextStyle',
|
'navLargeTitleTextStyle',
|
||||||
|
Loading…
Reference in New Issue
Block a user