typography.dart 11.7 KB
Newer Older
1 2 3 4 5
// Copyright 2015 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.


6
import 'package:flutter/painting.dart';
7 8

import 'colors.dart';
9

10 11
// TODO(eseidel): Font weights are supposed to be language relative.
// TODO(jackson): Baseline should be language relative.
12
// These values are for English-like text.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

/// Material design text theme.
///
/// Definitions for the various typographical styles found in material design
/// (e.g., headline, caption). Rather than creating a [TextTheme] directly,
/// you can obtain an instance as [Typography.black] or [Typography.white].
///
/// To obtain the current text theme, call [Theme.of] with the current
/// [BuildContext] and read the [ThemeData.textTheme] property.
///
/// See also:
///
///  * [Typography]
///  * [Theme]
///  * [ThemeData]
///  * <http://www.google.com/design/spec/style/typography.html>
29
class TextTheme {
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
  /// Create a text theme that uses the given values.
  ///
  /// Rather than creating a new text theme, consider using [Typography.black]
  /// or [Typography.white], which implement the typography styles in the
  /// material design specification:
  ///
  /// <https://material.google.com/style/typography.html#typography-styles>
  ///
  /// If you do decide to create your own text theme, consider using one of
  /// those predefined themes as a starting point for [copyWith] or [apply].
  const TextTheme({
    this.display4,
    this.display3,
    this.display2,
    this.display1,
    this.headline,
    this.title,
    this.subhead,
    this.body2,
    this.body1,
    this.caption,
    this.button
  });
53

54
  const TextTheme._black()
55 56 57 58 59 60 61 62 63 64 65
    : display4 = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w100, color: Colors.black54, textBaseline: TextBaseline.alphabetic),
      display3 = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  56.0, fontWeight: FontWeight.w400, color: Colors.black54, textBaseline: TextBaseline.alphabetic),
      display2 = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  45.0, fontWeight: FontWeight.w400, color: Colors.black54, textBaseline: TextBaseline.alphabetic),
      display1 = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  34.0, fontWeight: FontWeight.w400, color: Colors.black54, textBaseline: TextBaseline.alphabetic),
      headline = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  24.0, fontWeight: FontWeight.w400, color: Colors.black87, textBaseline: TextBaseline.alphabetic),
      title    = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  20.0, fontWeight: FontWeight.w500, color: Colors.black87, textBaseline: TextBaseline.alphabetic),
      subhead  = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  16.0, fontWeight: FontWeight.w400, color: Colors.black87, textBaseline: TextBaseline.alphabetic),
      body2    = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  14.0, fontWeight: FontWeight.w500, color: Colors.black87, textBaseline: TextBaseline.alphabetic),
      body1    = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  14.0, fontWeight: FontWeight.w400, color: Colors.black87, textBaseline: TextBaseline.alphabetic),
      caption  = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  12.0, fontWeight: FontWeight.w400, color: Colors.black54, textBaseline: TextBaseline.alphabetic),
      button   = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  14.0, fontWeight: FontWeight.w500, color: Colors.black87, textBaseline: TextBaseline.alphabetic);
66 67

  const TextTheme._white()
68 69 70 71 72 73 74 75 76 77 78
    : display4 = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w100, color: Colors.white70, textBaseline: TextBaseline.alphabetic),
      display3 = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  56.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic),
      display2 = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  45.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic),
      display1 = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  34.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic),
      headline = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  24.0, fontWeight: FontWeight.w400, color: Colors.white,   textBaseline: TextBaseline.alphabetic),
      title    = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  20.0, fontWeight: FontWeight.w500, color: Colors.white,   textBaseline: TextBaseline.alphabetic),
      subhead  = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  16.0, fontWeight: FontWeight.w400, color: Colors.white,   textBaseline: TextBaseline.alphabetic),
      body2    = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  14.0, fontWeight: FontWeight.w500, color: Colors.white,   textBaseline: TextBaseline.alphabetic),
      body1    = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  14.0, fontWeight: FontWeight.w400, color: Colors.white,   textBaseline: TextBaseline.alphabetic),
      caption  = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  12.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic),
      button   = const TextStyle(fontFamily: 'Roboto', inherit: false, fontSize:  14.0, fontWeight: FontWeight.w500, color: Colors.white,   textBaseline: TextBaseline.alphabetic);
79

80 81 82
  /// Extremely large text.
  ///
  /// The font size is 112 pixels.
83
  final TextStyle display4;
84 85 86 87

  /// Very, very large text.
  ///
  /// Used for the date in [DatePicker].
88
  final TextStyle display3;
89 90

  /// Very large text.
91
  final TextStyle display2;
92 93

  /// Large text.
94
  final TextStyle display1;
95 96

  /// Used for large text in dialogs (e.g., the month and year in [DatePicker]).
97
  final TextStyle headline;
98 99

  /// Used for the primary text in app bars and dialogs (e.g., [AppBar.title] and [Dialog.title]).
100
  final TextStyle title;
101 102

  /// Used for the primary text in lists (e.g., [ListItem.title]).
103
  final TextStyle subhead;
104 105

  /// Used for emphasizing text that would otherwise be [body1].
106
  final TextStyle body2;
107 108

  /// Used for the default text style for [Material].
109
  final TextStyle body1;
110

Ian Hickson's avatar
Ian Hickson committed
111
  /// Used for auxillary text associated with images.
112
  final TextStyle caption;
113 114

  /// Used for text on [RaisedButton] and [FlatButton].
115 116
  final TextStyle button;

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
  /// Creates a copy of this text theme but with the given fields replaced with
  /// the new values.
  ///
  /// Consider using [Typography.black] or [Typography.white], which implement
  /// the typography styles in the material design specification, as a starting
  /// point.
  TextTheme copyWith({
    TextStyle display4,
    TextStyle display3,
    TextStyle display2,
    TextStyle display1,
    TextStyle headline,
    TextStyle title,
    TextStyle subhead,
    TextStyle body2,
    TextStyle body1,
    TextStyle caption,
    TextStyle button
  }) {
    return new TextTheme(
      display4: display4 ?? this.display4,
      display3: display3 ?? this.display3,
      display2: display2 ?? this.display2,
      display1: display1 ?? this.display1,
      headline: headline ?? this.headline,
      title: title ?? this.title,
      subhead: subhead ?? this.subhead,
      body2: body2 ?? this.body2,
      body1: body1 ?? this.body1,
      caption: caption ?? this.caption,
      button: button ?? this.button
    );
  }

  /// Creates a copy of this text theme but with the given field replaced in
  /// each of the individual text styles.
  ///
  /// The `displayColor` is applied to [display4], [display3], [display2],
  /// [display1], and [caption]. The `bodyColor` is applied to the remaining
  /// text styles.
  ///
  /// Consider using [Typography.black] or [Typography.white], which implement
  /// the typography styles in the material design specification, as a starting
  /// point.
  TextTheme apply({
    String fontFamily,
    double fontSizeFactor: 1.0,
    double fontSizeDelta: 0.0,
    Color displayColor,
    Color bodyColor
  }) {
    return new TextTheme(
      display4: display4.apply(
        color: displayColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
      display3: display3.apply(
        color: displayColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
      display2: display2.apply(
        color: displayColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
      display1: display1.apply(
        color: displayColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
      headline: headline.apply(
        color: bodyColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
      title: title.apply(
        color: bodyColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
      subhead: subhead.apply(
        color: bodyColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
      body2: body2.apply(
        color: bodyColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
      body1: body1.apply(
        color: bodyColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
      caption: caption.apply(
        color: displayColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
      button: button.apply(
        color: bodyColor,
        fontFamily: fontFamily,
        fontSizeFactor: fontSizeFactor,
        fontSizeDelta: fontSizeDelta
      ),
    );
  }

238
  /// Linearly interpolate between two text themes.
239
  static TextTheme lerp(TextTheme begin, TextTheme end, double t) {
240 241 242 243 244 245 246 247 248 249 250 251
    return new TextTheme(
      display4: TextStyle.lerp(begin.display4, end.display4, t),
      display3: TextStyle.lerp(begin.display3, end.display3, t),
      display2: TextStyle.lerp(begin.display2, end.display2, t),
      display1: TextStyle.lerp(begin.display1, end.display1, t),
      headline: TextStyle.lerp(begin.headline, end.headline, t),
      title: TextStyle.lerp(begin.title, end.title, t),
      subhead: TextStyle.lerp(begin.subhead, end.subhead, t),
      body2: TextStyle.lerp(begin.body2, end.body2, t),
      body1: TextStyle.lerp(begin.body1, end.body1, t),
      caption: TextStyle.lerp(begin.caption, end.caption, t),
      button: TextStyle.lerp(begin.button, end.button, t)
252 253
    );
  }
254
}
255

256 257 258
/// The two material design text themes.
///
/// [Typography.black] and [Typography.white] define the two text themes used in
259 260 261
/// material design. The black text theme, which uses dark glyphs, is used on
/// light backgrounds in light themes. The white text theme, which uses light
/// glyphs, is used in dark themes and on dark backgrounds in in light themes.
262 263 264 265 266 267 268 269 270
///
/// To obtain the current text theme, call [Theme.of] with the current
/// [BuildContext] and read the [ThemeData.textTheme] property.
///
/// See also:
///
///  * [Theme]
///  * [ThemeData]
///  * <http://www.google.com/design/spec/style/typography.html>
271 272
class Typography {
  Typography._();
273

274
  /// A material design text theme with dark glyphs.
275
  static const TextTheme black = const TextTheme._black();
276

277
  /// A material design text theme with light glyphs.
278 279
  static const TextTheme white = const TextTheme._white();
}