| // Copyright 2014 The Flutter 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/foundation.dart'; |
| import 'package:flutter/widgets.dart'; |
| |
| import 'colors.dart'; |
| |
| // 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/. |
| const TextStyle _kDefaultTextStyle = TextStyle( |
| inherit: false, |
| fontFamily: '.SF Pro Text', |
| fontSize: 17.0, |
| letterSpacing: -0.41, |
| color: CupertinoColors.label, |
| 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/. |
| const TextStyle _kDefaultActionTextStyle = TextStyle( |
| inherit: false, |
| fontFamily: '.SF Pro Text', |
| fontSize: 17.0, |
| letterSpacing: -0.41, |
| color: CupertinoColors.activeBlue, |
| 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/. |
| const TextStyle _kDefaultTabLabelTextStyle = TextStyle( |
| inherit: false, |
| fontFamily: '.SF Pro Text', |
| fontSize: 10.0, |
| fontWeight: FontWeight.w500, |
| letterSpacing: -0.24, |
| color: CupertinoColors.inactiveGray, |
| ); |
| |
| const TextStyle _kDefaultMiddleTitleTextStyle = TextStyle( |
| inherit: false, |
| fontFamily: '.SF Pro Text', |
| fontSize: 17.0, |
| fontWeight: FontWeight.w600, |
| letterSpacing: -0.41, |
| color: CupertinoColors.label, |
| ); |
| |
| const TextStyle _kDefaultLargeTitleTextStyle = TextStyle( |
| inherit: false, |
| fontFamily: '.SF Pro Display', |
| fontSize: 34.0, |
| fontWeight: FontWeight.w700, |
| letterSpacing: 0.41, |
| color: CupertinoColors.label, |
| ); |
| |
| // Please update _TextThemeDefaultsBuilder 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. |
| // |
| // The letterSpacing sourced from iOS 14 simulator screenshots for comparison. |
| // See also: |
| // |
| // * https://github.com/flutter/flutter/pull/65501#discussion_r486557093 |
| const TextStyle _kDefaultPickerTextStyle = TextStyle( |
| inherit: false, |
| fontFamily: '.SF Pro Display', |
| fontSize: 21.0, |
| fontWeight: FontWeight.w400, |
| letterSpacing: -0.6, |
| color: CupertinoColors.label, |
| ); |
| |
| // Please update _TextThemeDefaultsBuilder 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, |
| fontFamily: '.SF Pro Display', |
| fontSize: 21, |
| fontWeight: FontWeight.normal, |
| color: CupertinoColors.label, |
| ); |
| |
| TextStyle? _resolveTextStyle(TextStyle? style, BuildContext context) { |
| // This does not resolve the shadow color, foreground, background, etc. |
| return style?.copyWith( |
| color: CupertinoDynamicColor.maybeResolve(style.color, context), |
| backgroundColor: CupertinoDynamicColor.maybeResolve(style.backgroundColor, context), |
| decorationColor: CupertinoDynamicColor.maybeResolve(style.decorationColor, context), |
| ); |
| } |
| |
| /// Cupertino typography theme in a [CupertinoThemeData]. |
| @immutable |
| class CupertinoTextThemeData with Diagnosticable { |
| /// Create a [CupertinoTextThemeData]. |
| /// |
| /// The [primaryColor] is used to derive TextStyle defaults of other attributes |
| /// such as [navActionTextStyle] and [actionTextStyle], it must not be null when |
| /// either [navActionTextStyle] or [actionTextStyle] is null. Defaults to |
| /// [CupertinoColors.systemBlue]. |
| /// |
| /// Other [TextStyle] parameters default to default iOS text styles when |
| /// unspecified. |
| const CupertinoTextThemeData({ |
| Color primaryColor = CupertinoColors.systemBlue, |
| TextStyle? textStyle, |
| TextStyle? actionTextStyle, |
| TextStyle? tabLabelTextStyle, |
| TextStyle? navTitleTextStyle, |
| TextStyle? navLargeTitleTextStyle, |
| TextStyle? navActionTextStyle, |
| TextStyle? pickerTextStyle, |
| TextStyle? dateTimePickerTextStyle, |
| }) : this._raw( |
| const _TextThemeDefaultsBuilder(CupertinoColors.label, CupertinoColors.inactiveGray), |
| primaryColor, |
| textStyle, |
| actionTextStyle, |
| tabLabelTextStyle, |
| navTitleTextStyle, |
| navLargeTitleTextStyle, |
| navActionTextStyle, |
| 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 _TextThemeDefaultsBuilder _defaults; |
| final Color? _primaryColor; |
| |
| final TextStyle? _textStyle; |
| /// The [TextStyle] of general text content for Cupertino widgets. |
| TextStyle get textStyle => _textStyle ?? _defaults.textStyle; |
| |
| final TextStyle? _actionTextStyle; |
| /// The [TextStyle] of interactive text content such as text in a button without background. |
| TextStyle get actionTextStyle { |
| return _actionTextStyle ?? _defaults.actionTextStyle(primaryColor: _primaryColor); |
| } |
| |
| final TextStyle? _tabLabelTextStyle; |
| /// The [TextStyle] of unselected tabs. |
| TextStyle get tabLabelTextStyle => _tabLabelTextStyle ?? _defaults.tabLabelTextStyle; |
| |
| final TextStyle? _navTitleTextStyle; |
| /// The [TextStyle] of titles in standard navigation bars. |
| TextStyle get navTitleTextStyle => _navTitleTextStyle ?? _defaults.navTitleTextStyle; |
| |
| final TextStyle? _navLargeTitleTextStyle; |
| /// The [TextStyle] of large titles in sliver navigation bars. |
| TextStyle get navLargeTitleTextStyle => _navLargeTitleTextStyle ?? _defaults.navLargeTitleTextStyle; |
| |
| final TextStyle? _navActionTextStyle; |
| /// The [TextStyle] of interactive text content in navigation bars. |
| TextStyle get navActionTextStyle { |
| return _navActionTextStyle ?? _defaults.navActionTextStyle(primaryColor: _primaryColor); |
| } |
| |
| final TextStyle? _pickerTextStyle; |
| /// The [TextStyle] of pickers. |
| TextStyle get pickerTextStyle => _pickerTextStyle ?? _defaults.pickerTextStyle; |
| |
| final TextStyle? _dateTimePickerTextStyle; |
| /// The [TextStyle] of date time pickers. |
| TextStyle get dateTimePickerTextStyle => _dateTimePickerTextStyle ?? _defaults.dateTimePickerTextStyle; |
| |
| /// Returns a copy of the current [CupertinoTextThemeData] with all the colors |
| /// resolved against the given [BuildContext]. |
| /// |
| /// If any of the [InheritedWidget]s required to resolve this |
| /// [CupertinoTextThemeData] is not found in [context], any unresolved |
| /// [CupertinoDynamicColor]s will use the default trait value |
| /// ([Brightness.light] platform brightness, normal contrast, |
| /// [CupertinoUserInterfaceLevelData.base] elevation level). |
| CupertinoTextThemeData resolveFrom(BuildContext context) { |
| return CupertinoTextThemeData._raw( |
| _defaults.resolveFrom(context), |
| CupertinoDynamicColor.maybeResolve(_primaryColor, context), |
| _resolveTextStyle(_textStyle, context), |
| _resolveTextStyle(_actionTextStyle, context), |
| _resolveTextStyle(_tabLabelTextStyle, context), |
| _resolveTextStyle(_navTitleTextStyle, context), |
| _resolveTextStyle(_navLargeTitleTextStyle, context), |
| _resolveTextStyle(_navActionTextStyle, context), |
| _resolveTextStyle(_pickerTextStyle, context), |
| _resolveTextStyle(_dateTimePickerTextStyle, context), |
| ); |
| } |
| |
| /// Returns a copy of the current [CupertinoTextThemeData] instance with |
| /// specified overrides. |
| CupertinoTextThemeData copyWith({ |
| Color? primaryColor, |
| TextStyle? textStyle, |
| TextStyle? actionTextStyle, |
| TextStyle? tabLabelTextStyle, |
| TextStyle? navTitleTextStyle, |
| TextStyle? navLargeTitleTextStyle, |
| TextStyle? navActionTextStyle, |
| TextStyle? pickerTextStyle, |
| TextStyle? dateTimePickerTextStyle, |
| }) { |
| return CupertinoTextThemeData._raw( |
| _defaults, |
| primaryColor ?? _primaryColor, |
| textStyle ?? _textStyle, |
| actionTextStyle ?? _actionTextStyle, |
| tabLabelTextStyle ?? _tabLabelTextStyle, |
| navTitleTextStyle ?? _navTitleTextStyle, |
| navLargeTitleTextStyle ?? _navLargeTitleTextStyle, |
| navActionTextStyle ?? _navActionTextStyle, |
| pickerTextStyle ?? _pickerTextStyle, |
| dateTimePickerTextStyle ?? _dateTimePickerTextStyle, |
| ); |
| } |
| |
| @override |
| void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
| super.debugFillProperties(properties); |
| const CupertinoTextThemeData defaultData = CupertinoTextThemeData(); |
| properties.add(DiagnosticsProperty<TextStyle>('textStyle', textStyle, defaultValue: defaultData.textStyle)); |
| properties.add(DiagnosticsProperty<TextStyle>('actionTextStyle', actionTextStyle, defaultValue: defaultData.actionTextStyle)); |
| properties.add(DiagnosticsProperty<TextStyle>('tabLabelTextStyle', tabLabelTextStyle, defaultValue: defaultData.tabLabelTextStyle)); |
| properties.add(DiagnosticsProperty<TextStyle>('navTitleTextStyle', navTitleTextStyle, defaultValue: defaultData.navTitleTextStyle)); |
| properties.add(DiagnosticsProperty<TextStyle>('navLargeTitleTextStyle', navLargeTitleTextStyle, defaultValue: defaultData.navLargeTitleTextStyle)); |
| properties.add(DiagnosticsProperty<TextStyle>('navActionTextStyle', navActionTextStyle, defaultValue: defaultData.navActionTextStyle)); |
| properties.add(DiagnosticsProperty<TextStyle>('pickerTextStyle', pickerTextStyle, defaultValue: defaultData.pickerTextStyle)); |
| properties.add(DiagnosticsProperty<TextStyle>('dateTimePickerTextStyle', dateTimePickerTextStyle, defaultValue: defaultData.dateTimePickerTextStyle)); |
| } |
| |
| @override |
| bool operator == (Object other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| return other is CupertinoTextThemeData |
| && other._defaults == _defaults |
| && other._primaryColor == _primaryColor |
| && other._textStyle == _textStyle |
| && other._actionTextStyle == _actionTextStyle |
| && other._tabLabelTextStyle == _tabLabelTextStyle |
| && other._navTitleTextStyle == _navTitleTextStyle |
| && other._navLargeTitleTextStyle == _navLargeTitleTextStyle |
| && other._navActionTextStyle == _navActionTextStyle |
| && other._pickerTextStyle == _pickerTextStyle |
| && other._dateTimePickerTextStyle == _dateTimePickerTextStyle; |
| } |
| |
| @override |
| int get hashCode => Object.hash( |
| _defaults, |
| _primaryColor, |
| _textStyle, |
| _actionTextStyle, |
| _tabLabelTextStyle, |
| _navTitleTextStyle, |
| _navLargeTitleTextStyle, |
| _navActionTextStyle, |
| _pickerTextStyle, |
| _dateTimePickerTextStyle, |
| ); |
| } |
| |
| |
| @immutable |
| class _TextThemeDefaultsBuilder { |
| const _TextThemeDefaultsBuilder( |
| this.labelColor, |
| this.inactiveGrayColor, |
| ); |
| |
| 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); |
| |
| _TextThemeDefaultsBuilder resolveFrom(BuildContext context) { |
| final Color resolvedLabelColor = CupertinoDynamicColor.resolve(labelColor, context); |
| final Color resolvedInactiveGray = CupertinoDynamicColor.resolve(inactiveGrayColor, context); |
| return resolvedLabelColor == labelColor && resolvedInactiveGray == CupertinoColors.inactiveGray |
| ? this |
| : _TextThemeDefaultsBuilder(resolvedLabelColor, resolvedInactiveGray); |
| } |
| |
| @override |
| bool operator == (Object other) { |
| if (identical(this, other)) { |
| return true; |
| } |
| if (other.runtimeType != runtimeType) { |
| return false; |
| } |
| return other is _TextThemeDefaultsBuilder |
| && other.labelColor == labelColor |
| && other.inactiveGrayColor == inactiveGrayColor; |
| } |
| |
| @override |
| int get hashCode => Object.hash(labelColor, inactiveGrayColor); |
| } |