text_theme.dart 12.2 KB
Newer Older
xster's avatar
xster committed
1 2 3 4 5 6 7 8 9 10
// Copyright 2018 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/foundation.dart';
import 'package:flutter/services.dart' show Brightness;
import 'package:flutter/widgets.dart';

import 'colors.dart';

11 12 13
// Please update _TextThemeDefaultsBuilder accordingly after changing the default
// color here, as their implementation depends on the default value of the color
// field.
14
//
xster's avatar
xster committed
15
// Values derived from https://developer.apple.com/design/resources/.
16
const TextStyle _kDefaultTextStyle = TextStyle(
xster's avatar
xster committed
17 18 19 20
  inherit: false,
  fontFamily: '.SF Pro Text',
  fontSize: 17.0,
  letterSpacing: -0.41,
21
  color: CupertinoColors.label,
xster's avatar
xster committed
22 23 24
  decoration: TextDecoration.none,
);

25 26 27
// Please update _TextThemeDefaultsBuilder accordingly after changing the default
// color here, as their implementation depends on the default value of the color
// field.
28
//
xster's avatar
xster committed
29 30 31 32 33 34 35 36 37 38
// 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,
);

39 40 41
// Please update _TextThemeDefaultsBuilder accordingly after changing the default
// color here, as their implementation depends on the default value of the color
// field.
42
//
xster's avatar
xster committed
43 44 45 46 47 48 49 50 51
// Values derived from https://developer.apple.com/design/resources/.
const TextStyle _kDefaultTabLabelTextStyle = TextStyle(
  inherit: false,
  fontFamily: '.SF Pro Text',
  fontSize: 10.0,
  letterSpacing: -0.24,
  color: CupertinoColors.inactiveGray,
);

52
const TextStyle _kDefaultMiddleTitleTextStyle = TextStyle(
xster's avatar
xster committed
53 54 55 56 57
  inherit: false,
  fontFamily: '.SF Pro Text',
  fontSize: 17.0,
  fontWeight: FontWeight.w600,
  letterSpacing: -0.41,
58
  color: CupertinoColors.label,
xster's avatar
xster committed
59 60
);

61
const TextStyle _kDefaultLargeTitleTextStyle = TextStyle(
xster's avatar
xster committed
62 63 64 65 66
  inherit: false,
  fontFamily: '.SF Pro Display',
  fontSize: 34.0,
  fontWeight: FontWeight.w700,
  letterSpacing: 0.41,
67
  color: CupertinoColors.label,
xster's avatar
xster committed
68 69
);

70 71 72
// Please update _TextThemeDefaultsBuilder accordingly after changing the default
// color here, as their implementation depends on the default value of the color
// field.
73 74 75 76
//
// 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 _kDefaultPickerTextStyle = TextStyle(
77 78
  inherit: false,
  fontFamily: '.SF Pro Display',
79
  fontSize: 21.0,
80 81
  fontWeight: FontWeight.w400,
  letterSpacing: -0.41,
82
  color: CupertinoColors.label,
83 84
);

85 86 87
// Please update _TextThemeDefaultsBuilder accordingly after changing the default
// color here, as their implementation depends on the default value of the color
// field.
88
//
89
// Inspected on iOS 13 simulator with "Debug View Hierarchy".
90 91
// Value extracted from off-center labels. Centered labels have a font size of 25pt.
const TextStyle _kDefaultDateTimePickerTextStyle = TextStyle(
92 93 94
  inherit: false,
  fontFamily: '.SF Pro Display',
  fontSize: 21,
95
  fontWeight: FontWeight.normal,
96
  color: CupertinoColors.label,
97 98
);

99 100 101 102 103 104 105 106
TextStyle _resolveTextStyle(TextStyle style, BuildContext context, bool nullOk) {
  // This does not resolve the shadow color, foreground, background, etc.
  return style?.copyWith(
    color: CupertinoDynamicColor.resolve(style?.color, context, nullOk: nullOk),
    backgroundColor: CupertinoDynamicColor.resolve(style?.backgroundColor, context, nullOk: nullOk),
    decorationColor: CupertinoDynamicColor.resolve(style?.decorationColor, context, nullOk: nullOk),
  );
}
107

xster's avatar
xster committed
108 109 110 111 112
/// Cupertino typography theme in a [CupertinoThemeData].
@immutable
class CupertinoTextThemeData extends Diagnosticable {
  /// Create a [CupertinoTextThemeData].
  ///
113 114 115 116
  /// 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].
xster's avatar
xster committed
117 118 119 120
  ///
  /// Other [TextStyle] parameters default to default iOS text styles when
  /// unspecified.
  const CupertinoTextThemeData({
121
    Color primaryColor = CupertinoColors.systemBlue,
122 123 124 125 126 127
    // ignore: avoid_unused_constructor_parameters, the parameter is deprecated.
    @Deprecated(
      'This argument no longer does anything. You can remove it. '
      'This feature was deprecated after v1.10.14.'
    )
    Brightness brightness,
xster's avatar
xster committed
128 129 130 131 132 133
    TextStyle textStyle,
    TextStyle actionTextStyle,
    TextStyle tabLabelTextStyle,
    TextStyle navTitleTextStyle,
    TextStyle navLargeTitleTextStyle,
    TextStyle navActionTextStyle,
134 135
    TextStyle pickerTextStyle,
    TextStyle dateTimePickerTextStyle,
136
  }) : this._raw(
137
         const _TextThemeDefaultsBuilder(CupertinoColors.label, CupertinoColors.inactiveGray),
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
         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);
xster's avatar
xster committed
161

162
  final _TextThemeDefaultsBuilder _defaults;
xster's avatar
xster committed
163 164 165
  final Color _primaryColor;

  final TextStyle _textStyle;
166 167
  /// The [TextStyle] of general text content for Cupertino widgets.
  TextStyle get textStyle => _textStyle ?? _defaults.textStyle;
xster's avatar
xster committed
168 169

  final TextStyle _actionTextStyle;
170
  /// The [TextStyle] of interactive text content such as text in a button without background.
xster's avatar
xster committed
171
  TextStyle get actionTextStyle {
172
    return _actionTextStyle ?? _defaults.actionTextStyle(primaryColor: _primaryColor);
xster's avatar
xster committed
173 174 175
  }

  final TextStyle _tabLabelTextStyle;
176 177
  /// The [TextStyle] of unselected tabs.
  TextStyle get tabLabelTextStyle => _tabLabelTextStyle ?? _defaults.tabLabelTextStyle;
xster's avatar
xster committed
178 179

  final TextStyle _navTitleTextStyle;
180 181
  /// The [TextStyle] of titles in standard navigation bars.
  TextStyle get navTitleTextStyle => _navTitleTextStyle ?? _defaults.navTitleTextStyle;
xster's avatar
xster committed
182 183

  final TextStyle _navLargeTitleTextStyle;
184 185
  /// The [TextStyle] of large titles in sliver navigation bars.
  TextStyle get navLargeTitleTextStyle => _navLargeTitleTextStyle ?? _defaults.navLargeTitleTextStyle;
xster's avatar
xster committed
186 187

  final TextStyle _navActionTextStyle;
188
  /// The [TextStyle] of interactive text content in navigation bars.
xster's avatar
xster committed
189
  TextStyle get navActionTextStyle {
190
    return _navActionTextStyle ?? _defaults.navActionTextStyle(primaryColor: _primaryColor);
xster's avatar
xster committed
191 192
  }

193
  final TextStyle _pickerTextStyle;
194 195
  /// The [TextStyle] of pickers.
  TextStyle get pickerTextStyle => _pickerTextStyle ?? _defaults.pickerTextStyle;
196 197

  final TextStyle _dateTimePickerTextStyle;
198 199
  /// The [TextStyle] of date time pickers.
  TextStyle get dateTimePickerTextStyle => _dateTimePickerTextStyle ?? _defaults.dateTimePickerTextStyle;
200

201 202
  /// Returns a copy of the current [CupertinoTextThemeData] with all the colors
  /// resolved against the given [BuildContext].
203 204 205 206 207
  ///
  /// 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.
208
  CupertinoTextThemeData resolveFrom(BuildContext context, { bool nullOk = false }) {
209 210 211 212 213 214 215 216 217 218 219
    return CupertinoTextThemeData._raw(
      _defaults?.resolveFrom(context, nullOk),
      CupertinoDynamicColor.resolve(_primaryColor, context, nullOk: nullOk),
      _resolveTextStyle(_textStyle, context, nullOk),
      _resolveTextStyle(_actionTextStyle, context, nullOk),
      _resolveTextStyle(_tabLabelTextStyle, context, nullOk),
      _resolveTextStyle(_navTitleTextStyle, context, nullOk),
      _resolveTextStyle(_navLargeTitleTextStyle, context, nullOk),
      _resolveTextStyle(_navActionTextStyle, context, nullOk),
      _resolveTextStyle(_pickerTextStyle, context, nullOk),
      _resolveTextStyle(_dateTimePickerTextStyle, context, nullOk),
220 221 222
    );
  }

xster's avatar
xster committed
223 224 225 226
  /// Returns a copy of the current [CupertinoTextThemeData] instance with
  /// specified overrides.
  CupertinoTextThemeData copyWith({
    Color primaryColor,
227 228 229 230 231
    @Deprecated(
      'This argument no longer does anything. You can remove it. '
      'This feature was deprecated after v1.10.14.'
    )
    Brightness brightness,
xster's avatar
xster committed
232 233 234 235 236 237
    TextStyle textStyle,
    TextStyle actionTextStyle,
    TextStyle tabLabelTextStyle,
    TextStyle navTitleTextStyle,
    TextStyle navLargeTitleTextStyle,
    TextStyle navActionTextStyle,
238 239
    TextStyle pickerTextStyle,
    TextStyle dateTimePickerTextStyle,
xster's avatar
xster committed
240
  }) {
241 242 243 244 245 246 247 248 249 250 251
    return CupertinoTextThemeData._raw(
      _defaults,
      primaryColor ?? _primaryColor,
      textStyle ?? _textStyle,
      actionTextStyle ?? _actionTextStyle,
      tabLabelTextStyle ?? _tabLabelTextStyle,
      navTitleTextStyle ?? _navTitleTextStyle,
      navLargeTitleTextStyle ?? _navLargeTitleTextStyle,
      navActionTextStyle ?? _navActionTextStyle,
      pickerTextStyle ?? _pickerTextStyle,
      dateTimePickerTextStyle ?? _dateTimePickerTextStyle,
xster's avatar
xster committed
252 253
    );
  }
254 255 256 257 258 259 260 261 262 263 264 265 266 267

  @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));
  }
xster's avatar
xster committed
268
}
269

270

271
@immutable
272 273 274 275 276 277
class _TextThemeDefaultsBuilder {
  const _TextThemeDefaultsBuilder(
    this.labelColor,
    this.inactiveGrayColor,
  ) : assert(labelColor != null),
      assert(inactiveGrayColor != null);
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297

  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);

298
  _TextThemeDefaultsBuilder resolveFrom(BuildContext context, bool nullOk) {
299 300 301 302
    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
303
      : _TextThemeDefaultsBuilder(resolvedLabelColor, resolvedInactiveGray);
304 305
  }
}