introduce localized text geometry in MaterialLocalizations (#11829)
* introduce localized text geometry in MaterialLocalizations * remove geometry from color text themes * fix merge conflict * optional Localizations * fix fallback; test; docs
This commit is contained in:
parent
f4f20c2909
commit
b9e1be9ace
@ -12,6 +12,7 @@
|
||||
/// This variable is used by [MaterialLocalizations].
|
||||
const Map<String, Map<String, String>> localizations = const <String, Map<String, String>> {
|
||||
"ar": const <String, String>{
|
||||
"scriptCategory": r"tall",
|
||||
"timeOfDayFormat": r"h:mm a",
|
||||
"openAppDrawerTooltip": r"افتح قائمة التنقل",
|
||||
"backButtonTooltip": r"الى الخلف",
|
||||
@ -40,6 +41,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"postMeridiemAbbreviation": r"م",
|
||||
},
|
||||
"de": const <String, String>{
|
||||
"scriptCategory": r"English-like",
|
||||
"timeOfDayFormat": r"HH:mm",
|
||||
"openAppDrawerTooltip": r"Navigationsmenü öffnen",
|
||||
"backButtonTooltip": r"Zurück",
|
||||
@ -68,6 +70,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"viewLicensesButtonLabel": r"LIZENZEN ANZEIGEN",
|
||||
},
|
||||
"en": const <String, String>{
|
||||
"scriptCategory": r"English-like",
|
||||
"timeOfDayFormat": r"h:mm a",
|
||||
"openAppDrawerTooltip": r"Open navigation menu",
|
||||
"backButtonTooltip": r"Back",
|
||||
@ -107,6 +110,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"timeOfDayFormat": r"HH:mm",
|
||||
},
|
||||
"es": const <String, String>{
|
||||
"scriptCategory": r"English-like",
|
||||
"timeOfDayFormat": r"H:mm",
|
||||
"openAppDrawerTooltip": r"Abrir el menú de navegación",
|
||||
"backButtonTooltip": r"Espalda",
|
||||
@ -140,6 +144,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"postMeridiemAbbreviation": r"PM",
|
||||
},
|
||||
"fa": const <String, String>{
|
||||
"scriptCategory": r"tall",
|
||||
"timeOfDayFormat": r"H:mm",
|
||||
"openAppDrawerTooltip": r"منوی ناوبری را باز کنید",
|
||||
"backButtonTooltip": r"بازگشت",
|
||||
@ -166,6 +171,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"viewLicensesButtonLabel": r"مشاهده مجوز",
|
||||
},
|
||||
"fr": const <String, String>{
|
||||
"scriptCategory": r"English-like",
|
||||
"timeOfDayFormat": r"HH:mm",
|
||||
"openAppDrawerTooltip": r"Ouvrir le menu de navigation",
|
||||
"backButtonTooltip": r"Retour",
|
||||
@ -197,6 +203,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"timeOfDayFormat": r"HH 'h' mm",
|
||||
},
|
||||
"he": const <String, String>{
|
||||
"scriptCategory": r"English-like",
|
||||
"timeOfDayFormat": r"H:mm",
|
||||
"openAppDrawerTooltip": r"פתח תפריט ניווט",
|
||||
"backButtonTooltip": r"אחורה",
|
||||
@ -223,6 +230,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"viewLicensesButtonLabel": r"ראה רישיונות",
|
||||
},
|
||||
"it": const <String, String>{
|
||||
"scriptCategory": r"English-like",
|
||||
"timeOfDayFormat": r"HH:mm",
|
||||
"openAppDrawerTooltip": r"Apri il menu di navigazione",
|
||||
"backButtonTooltip": r"Indietro",
|
||||
@ -249,6 +257,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"viewLicensesButtonLabel": r"VEDI LE LICENZE",
|
||||
},
|
||||
"ja": const <String, String>{
|
||||
"scriptCategory": r"dense",
|
||||
"timeOfDayFormat": r"H:mm",
|
||||
"openAppDrawerTooltip": r"ナビゲーションメニューを開く",
|
||||
"backButtonTooltip": r"戻る",
|
||||
@ -275,6 +284,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"viewLicensesButtonLabel": r"ライセンス表記",
|
||||
},
|
||||
"ps": const <String, String>{
|
||||
"scriptCategory": r"tall",
|
||||
"timeOfDayFormat": r"HH:mm",
|
||||
"openAppDrawerTooltip": r"د پرانیستی نیینګ مینو",
|
||||
"backButtonTooltip": r"شاته",
|
||||
@ -301,6 +311,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"viewLicensesButtonLabel": r"لیدلس وګورئ",
|
||||
},
|
||||
"pt": const <String, String>{
|
||||
"scriptCategory": r"English-like",
|
||||
"timeOfDayFormat": r"HH:mm",
|
||||
"openAppDrawerTooltip": r"Abrir menu de navegação",
|
||||
"backButtonTooltip": r"Costas",
|
||||
@ -327,6 +338,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"viewLicensesButtonLabel": r"VER LICENÇAS",
|
||||
},
|
||||
"ru": const <String, String>{
|
||||
"scriptCategory": r"English-like",
|
||||
"timeOfDayFormat": r"H:mm",
|
||||
"openAppDrawerTooltip": r"Открыть меню навигации",
|
||||
"backButtonTooltip": r"Назад",
|
||||
@ -355,6 +367,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"viewLicensesButtonLabel": r"ПРОСМОТРЕТЬ ЛИЦЕНЗИИ",
|
||||
},
|
||||
"sd": const <String, String>{
|
||||
"scriptCategory": r"tall",
|
||||
"timeOfDayFormat": r"HH:mm",
|
||||
"openAppDrawerTooltip": r"اوپن جي مينڊيٽ مينيو",
|
||||
"backButtonTooltip": r"پوئتي",
|
||||
@ -381,6 +394,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"viewLicensesButtonLabel": r"لائسنس ڏسو",
|
||||
},
|
||||
"ur": const <String, String>{
|
||||
"scriptCategory": r"tall",
|
||||
"timeOfDayFormat": r"h:mm a",
|
||||
"openAppDrawerTooltip": r"کھولیں نیویگیشن مینو",
|
||||
"backButtonTooltip": r"واپس",
|
||||
@ -409,6 +423,7 @@ const Map<String, Map<String, String>> localizations = const <String, Map<String
|
||||
"postMeridiemAbbreviation": r"PM",
|
||||
},
|
||||
"zh": const <String, String>{
|
||||
"scriptCategory": r"dense",
|
||||
"timeOfDayFormat": r"ah:mm",
|
||||
"openAppDrawerTooltip": r"打开导航菜单",
|
||||
"backButtonTooltip": r"返回",
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "tall",
|
||||
"timeOfDayFormat": "h:mm a",
|
||||
"openAppDrawerTooltip": "افتح قائمة التنقل",
|
||||
"backButtonTooltip": "الى الخلف",
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "English-like",
|
||||
"timeOfDayFormat": "HH:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "German time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "German time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,10 @@
|
||||
{
|
||||
"scriptCategory": "English-like",
|
||||
"@scriptCategory": {
|
||||
"description": "The name of the language's script category (see https://material.io/guidelines/style/typography.html#typography-language-categories-reference)",
|
||||
"type": "text"
|
||||
},
|
||||
|
||||
"timeOfDayFormat": "h:mm a",
|
||||
"@timeOfDayFormat": {
|
||||
"description": "The ICU 'Short Time' pattern, such as 'HH:mm', 'h:mm a', 'H:mm'. See: http://demo.icu-project.org/icu-bin/locexp?d_=en&_=en_US",
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "English-like",
|
||||
"timeOfDayFormat": "H:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "Standard Spanish time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "Standard Spanish time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "tall",
|
||||
"timeOfDayFormat": "H:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "Farsi time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "Farsi time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "English-like",
|
||||
"timeOfDayFormat": "HH:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "French time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "French time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "English-like",
|
||||
"timeOfDayFormat": "H:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "Hebrew time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "Hebrew time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "English-like",
|
||||
"timeOfDayFormat": "HH:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "Italian time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "Italian time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "dense",
|
||||
"timeOfDayFormat": "H:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "Japanese time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "Japanese time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "tall",
|
||||
"timeOfDayFormat": "HH:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "Pashto time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "Pashto time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "English-like",
|
||||
"timeOfDayFormat": "HH:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "Portuguese time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "Portuguese time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "English-like",
|
||||
"timeOfDayFormat": "H:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "Russian time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "Russian time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "tall",
|
||||
"timeOfDayFormat": "HH:mm",
|
||||
"@anteMeridiemAbbreviation": { "notUsed": "Sindhi time format does not use a.m. indicator" },
|
||||
"@postMeridiemAbbreviation": { "notUsed": "Sindhi time format does not use p.m. indicator" },
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "tall",
|
||||
"timeOfDayFormat": "h:mm a",
|
||||
"openAppDrawerTooltip": "کھولیں نیویگیشن مینو",
|
||||
"backButtonTooltip": "واپس",
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"scriptCategory": "dense",
|
||||
"timeOfDayFormat": "ah:mm",
|
||||
"openAppDrawerTooltip": "打开导航菜单",
|
||||
"backButtonTooltip": "返回",
|
||||
|
@ -9,6 +9,7 @@ import 'package:flutter/widgets.dart';
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
|
||||
import 'i18n/localizations.dart';
|
||||
import 'typography.dart';
|
||||
|
||||
/// Defines the localized resource values used by the Material widgets.
|
||||
///
|
||||
@ -95,6 +96,19 @@ abstract class MaterialLocalizations {
|
||||
/// each supported layout.
|
||||
TimeOfDayFormat get timeOfDayFormat;
|
||||
|
||||
/// Provides geometric text preferences for the current locale.
|
||||
///
|
||||
/// This text theme is incomplete. For example, it lacks text color
|
||||
/// information. This theme must be merged with another text theme that
|
||||
/// provides the missing values. The text styles provided by this theme have
|
||||
/// their [TextStyle.inherit] property set to `true`.
|
||||
///
|
||||
/// Typically a complete theme is obtained via [Theme.of], which can be
|
||||
/// localized using the [Localizations] widget.
|
||||
///
|
||||
/// See also: https://material.io/guidelines/style/typography.html
|
||||
TextTheme get localTextGeometry;
|
||||
|
||||
/// The `MaterialLocalizations` from the closest [Localizations] instance
|
||||
/// that encloses the given context.
|
||||
///
|
||||
@ -287,6 +301,10 @@ class DefaultMaterialLocalizations implements MaterialLocalizations {
|
||||
return _icuTimeOfDayToEnum[icuShortTimePattern];
|
||||
}
|
||||
|
||||
/// Looks up text geometry defined in [MaterialTextGeometry].
|
||||
@override
|
||||
TextTheme get localTextGeometry => MaterialTextGeometry.forScriptCategory(_nameToValue["scriptCategory"]);
|
||||
|
||||
/// Creates an object that provides localized resource values for the
|
||||
/// for the widgets of the material library.
|
||||
///
|
||||
|
@ -5,7 +5,9 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'material_localizations.dart';
|
||||
import 'theme_data.dart';
|
||||
import 'typography.dart';
|
||||
|
||||
export 'theme_data.dart' show Brightness, ThemeData;
|
||||
|
||||
@ -65,6 +67,10 @@ class Theme extends StatelessWidget {
|
||||
/// The data from the closest [Theme] instance that encloses the given
|
||||
/// context.
|
||||
///
|
||||
/// If the given context is enclosed in a [Localizations] widget providing
|
||||
/// [MaterialLocalizations], the returned data is localized according to the
|
||||
/// nearest available [MaterialLocalizations].
|
||||
///
|
||||
/// Defaults to [new ThemeData.fallback] if there is no [Theme] in the given
|
||||
/// build context.
|
||||
///
|
||||
@ -123,7 +129,11 @@ class Theme extends StatelessWidget {
|
||||
return null;
|
||||
return inheritedTheme.theme.data;
|
||||
}
|
||||
return (inheritedTheme != null) ? inheritedTheme.theme.data : _kFallbackTheme;
|
||||
|
||||
final ThemeData colorTheme = (inheritedTheme != null) ? inheritedTheme.theme.data : _kFallbackTheme;
|
||||
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
|
||||
final TextTheme geometryTheme = localizations?.localTextGeometry ?? MaterialTextGeometry.englishLike;
|
||||
return ThemeData.localize(colorTheme, geometryTheme);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -48,7 +48,6 @@ const Color _kDarkThemeSplashColor = const Color(0x40CCCCCC);
|
||||
/// Use this class to configure a [Theme] widget.
|
||||
///
|
||||
/// To obtain the current theme, use [Theme.of].
|
||||
@immutable
|
||||
class ThemeData {
|
||||
/// Create a ThemeData given a set of preferred values.
|
||||
///
|
||||
@ -248,14 +247,26 @@ class ThemeData {
|
||||
assert(platform != null);
|
||||
|
||||
/// A default light blue theme.
|
||||
///
|
||||
/// This theme does not contain text geometry. Instead, it is expected that
|
||||
/// this theme is localized using text geometry using [ThemeData.localize].
|
||||
factory ThemeData.light() => new ThemeData(brightness: Brightness.light);
|
||||
|
||||
/// A default dark theme with a teal accent color.
|
||||
///
|
||||
/// This theme does not contain text geometry. Instead, it is expected that
|
||||
/// this theme is localized using text geometry using [ThemeData.localize].
|
||||
factory ThemeData.dark() => new ThemeData(brightness: Brightness.dark);
|
||||
|
||||
/// The default theme. Same as [new ThemeData.light].
|
||||
/// The default color theme. Same as [new ThemeData.light].
|
||||
///
|
||||
/// This is used by [Theme.of] when no theme has been specified.
|
||||
///
|
||||
/// This theme does not contain text geometry. Instead, it is expected that
|
||||
/// this theme is localized using text geometry using [ThemeData.localize].
|
||||
///
|
||||
/// Most applications would use [Theme.of], which provides correct localized
|
||||
/// text geometry.
|
||||
factory ThemeData.fallback() => new ThemeData.light();
|
||||
|
||||
/// The brightness of the overall theme of the application. Used by widgets
|
||||
@ -407,40 +418,52 @@ class ThemeData {
|
||||
IconThemeData accentIconTheme,
|
||||
TargetPlatform platform,
|
||||
}) {
|
||||
return new ThemeData.raw(
|
||||
brightness: brightness ?? this.brightness,
|
||||
primaryColor: primaryColor ?? this.primaryColor,
|
||||
primaryColorBrightness: primaryColorBrightness ?? this.primaryColorBrightness,
|
||||
accentColor: accentColor ?? this.accentColor,
|
||||
accentColorBrightness: accentColorBrightness ?? this.accentColorBrightness,
|
||||
canvasColor: canvasColor ?? this.canvasColor,
|
||||
scaffoldBackgroundColor: scaffoldBackgroundColor ?? this.scaffoldBackgroundColor,
|
||||
cardColor: cardColor ?? this.cardColor,
|
||||
dividerColor: dividerColor ?? this.dividerColor,
|
||||
highlightColor: highlightColor ?? this.highlightColor,
|
||||
splashColor: splashColor ?? this.splashColor,
|
||||
selectedRowColor: selectedRowColor ?? this.selectedRowColor,
|
||||
unselectedWidgetColor: unselectedWidgetColor ?? this.unselectedWidgetColor,
|
||||
disabledColor: disabledColor ?? this.disabledColor,
|
||||
buttonColor: buttonColor ?? this.buttonColor,
|
||||
secondaryHeaderColor: secondaryHeaderColor ?? this.secondaryHeaderColor,
|
||||
textSelectionColor: textSelectionColor ?? this.textSelectionColor,
|
||||
textSelectionHandleColor: textSelectionHandleColor ?? this.textSelectionHandleColor,
|
||||
backgroundColor: backgroundColor ?? this.backgroundColor,
|
||||
dialogBackgroundColor: dialogBackgroundColor ?? this.dialogBackgroundColor,
|
||||
indicatorColor: indicatorColor ?? this.indicatorColor,
|
||||
hintColor: hintColor ?? this.hintColor,
|
||||
errorColor: errorColor ?? this.errorColor,
|
||||
textTheme: textTheme ?? this.textTheme,
|
||||
primaryTextTheme: primaryTextTheme ?? this.primaryTextTheme,
|
||||
accentTextTheme: accentTextTheme ?? this.accentTextTheme,
|
||||
iconTheme: iconTheme ?? this.iconTheme,
|
||||
primaryIconTheme: primaryIconTheme ?? this.primaryIconTheme,
|
||||
accentIconTheme: accentIconTheme ?? this.accentIconTheme,
|
||||
platform: platform ?? this.platform,
|
||||
return _copyThemeDataWith(
|
||||
this,
|
||||
brightness: brightness,
|
||||
primaryColor: primaryColor,
|
||||
primaryColorBrightness: primaryColorBrightness,
|
||||
accentColor: accentColor,
|
||||
accentColorBrightness: accentColorBrightness,
|
||||
canvasColor: canvasColor,
|
||||
scaffoldBackgroundColor: scaffoldBackgroundColor,
|
||||
cardColor: cardColor,
|
||||
dividerColor: dividerColor,
|
||||
highlightColor: highlightColor,
|
||||
splashColor: splashColor,
|
||||
selectedRowColor: selectedRowColor,
|
||||
unselectedWidgetColor: unselectedWidgetColor,
|
||||
disabledColor: disabledColor,
|
||||
buttonColor: buttonColor,
|
||||
secondaryHeaderColor: secondaryHeaderColor,
|
||||
textSelectionColor: textSelectionColor,
|
||||
textSelectionHandleColor: textSelectionHandleColor,
|
||||
backgroundColor: backgroundColor,
|
||||
dialogBackgroundColor: dialogBackgroundColor,
|
||||
indicatorColor: indicatorColor,
|
||||
hintColor: hintColor,
|
||||
errorColor: errorColor,
|
||||
textTheme: textTheme,
|
||||
primaryTextTheme: primaryTextTheme,
|
||||
accentTextTheme: accentTextTheme,
|
||||
iconTheme: iconTheme,
|
||||
primaryIconTheme: primaryIconTheme,
|
||||
accentIconTheme: accentIconTheme,
|
||||
platform: platform,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns a new theme built by merging [baseTheme] into the text geometry
|
||||
/// provided by the [localTextGeometry].
|
||||
///
|
||||
/// The [TextStyle.inherit] field in the text styles provided by
|
||||
/// [localTextGeometry] must be set to `true`.
|
||||
static ThemeData localize(ThemeData baseTheme, TextTheme localTextGeometry) {
|
||||
assert(baseTheme != null);
|
||||
assert(localTextGeometry != null);
|
||||
return new _LocalizedThemeData(baseTheme, localTextGeometry);
|
||||
}
|
||||
|
||||
// See <https://www.w3.org/TR/WCAG20/#relativeluminancedef>
|
||||
static double _linearizeColorComponent(double component) {
|
||||
if (component <= 0.03928)
|
||||
@ -590,3 +613,246 @@ class ThemeData {
|
||||
@override
|
||||
String toString() => '$runtimeType(${ platform != defaultTargetPlatform ? "$platform " : ''}$brightness $primaryColor etc...)';
|
||||
}
|
||||
|
||||
/// A lazily evaluated theme that provides the properties of the given
|
||||
/// [delegate] theme localized using the properties of the given
|
||||
/// [localTextGeometry].
|
||||
///
|
||||
/// The localization is done by merging of the [TextTheme] fields of the
|
||||
/// [delegate] into the [localTextGeometry] and caching the results.
|
||||
class _LocalizedThemeData implements ThemeData {
|
||||
_LocalizedThemeData(this.delegate, this.localTextGeometry);
|
||||
|
||||
final ThemeData delegate;
|
||||
final TextTheme localTextGeometry;
|
||||
|
||||
@override
|
||||
Color get accentColor => delegate.accentColor;
|
||||
|
||||
@override
|
||||
Brightness get accentColorBrightness => delegate.accentColorBrightness;
|
||||
|
||||
@override
|
||||
IconThemeData get accentIconTheme => delegate.accentIconTheme;
|
||||
|
||||
@override
|
||||
Color get backgroundColor => delegate.backgroundColor;
|
||||
|
||||
@override
|
||||
Brightness get brightness => delegate.brightness;
|
||||
|
||||
@override
|
||||
Color get buttonColor => delegate.buttonColor;
|
||||
|
||||
@override
|
||||
Color get canvasColor => delegate.canvasColor;
|
||||
|
||||
@override
|
||||
Color get cardColor => delegate.cardColor;
|
||||
|
||||
@override
|
||||
Color get dialogBackgroundColor => delegate.dialogBackgroundColor;
|
||||
|
||||
@override
|
||||
Color get disabledColor => delegate.disabledColor;
|
||||
|
||||
@override
|
||||
Color get dividerColor => delegate.dividerColor;
|
||||
|
||||
@override
|
||||
Color get errorColor => delegate.errorColor;
|
||||
|
||||
@override
|
||||
Color get highlightColor => delegate.highlightColor;
|
||||
|
||||
@override
|
||||
Color get hintColor => delegate.hintColor;
|
||||
|
||||
@override
|
||||
IconThemeData get iconTheme => delegate.iconTheme;
|
||||
|
||||
@override
|
||||
Color get indicatorColor => delegate.indicatorColor;
|
||||
|
||||
@override
|
||||
TargetPlatform get platform => delegate.platform;
|
||||
|
||||
@override
|
||||
Color get primaryColor => delegate.primaryColor;
|
||||
|
||||
@override
|
||||
Brightness get primaryColorBrightness => delegate.primaryColorBrightness;
|
||||
|
||||
@override
|
||||
IconThemeData get primaryIconTheme => delegate.primaryIconTheme;
|
||||
|
||||
@override
|
||||
Color get scaffoldBackgroundColor => delegate.scaffoldBackgroundColor;
|
||||
|
||||
@override
|
||||
Color get secondaryHeaderColor => delegate.secondaryHeaderColor;
|
||||
|
||||
@override
|
||||
Color get selectedRowColor => delegate.selectedRowColor;
|
||||
|
||||
@override
|
||||
Color get splashColor => delegate.splashColor;
|
||||
|
||||
@override
|
||||
Color get textSelectionColor => delegate.textSelectionColor;
|
||||
|
||||
@override
|
||||
Color get textSelectionHandleColor => delegate.textSelectionHandleColor;
|
||||
|
||||
@override
|
||||
Color get unselectedWidgetColor => delegate.unselectedWidgetColor;
|
||||
|
||||
@override
|
||||
TextTheme get primaryTextTheme => _primaryTextTheme ??= delegate.primaryTextTheme.merge(localTextGeometry);
|
||||
TextTheme _primaryTextTheme;
|
||||
|
||||
@override
|
||||
TextTheme get accentTextTheme => _accentTextTheme ??= delegate.accentTextTheme.merge(localTextGeometry);
|
||||
TextTheme _accentTextTheme;
|
||||
|
||||
@override
|
||||
TextTheme get textTheme => _textTheme ??= delegate.textTheme.merge(localTextGeometry);
|
||||
TextTheme _textTheme;
|
||||
|
||||
/// This should be identical to [ThemeData.copyWith].
|
||||
@override
|
||||
ThemeData copyWith({
|
||||
Brightness brightness,
|
||||
Color primaryColor,
|
||||
Brightness primaryColorBrightness,
|
||||
Color accentColor,
|
||||
Brightness accentColorBrightness,
|
||||
Color canvasColor,
|
||||
Color scaffoldBackgroundColor,
|
||||
Color cardColor,
|
||||
Color dividerColor,
|
||||
Color highlightColor,
|
||||
Color splashColor,
|
||||
Color selectedRowColor,
|
||||
Color unselectedWidgetColor,
|
||||
Color disabledColor,
|
||||
Color buttonColor,
|
||||
Color secondaryHeaderColor,
|
||||
Color textSelectionColor,
|
||||
Color textSelectionHandleColor,
|
||||
Color backgroundColor,
|
||||
Color dialogBackgroundColor,
|
||||
Color indicatorColor,
|
||||
Color hintColor,
|
||||
Color errorColor,
|
||||
TextTheme textTheme,
|
||||
TextTheme primaryTextTheme,
|
||||
TextTheme accentTextTheme,
|
||||
IconThemeData iconTheme,
|
||||
IconThemeData primaryIconTheme,
|
||||
IconThemeData accentIconTheme,
|
||||
TargetPlatform platform,
|
||||
}) {
|
||||
return _copyThemeDataWith(
|
||||
this,
|
||||
brightness: brightness,
|
||||
primaryColor: primaryColor,
|
||||
primaryColorBrightness: primaryColorBrightness,
|
||||
accentColor: accentColor,
|
||||
accentColorBrightness: accentColorBrightness,
|
||||
canvasColor: canvasColor,
|
||||
scaffoldBackgroundColor: scaffoldBackgroundColor,
|
||||
cardColor: cardColor,
|
||||
dividerColor: dividerColor,
|
||||
highlightColor: highlightColor,
|
||||
splashColor: splashColor,
|
||||
selectedRowColor: selectedRowColor,
|
||||
unselectedWidgetColor: unselectedWidgetColor,
|
||||
disabledColor: disabledColor,
|
||||
buttonColor: buttonColor,
|
||||
secondaryHeaderColor: secondaryHeaderColor,
|
||||
textSelectionColor: textSelectionColor,
|
||||
textSelectionHandleColor: textSelectionHandleColor,
|
||||
backgroundColor: backgroundColor,
|
||||
dialogBackgroundColor: dialogBackgroundColor,
|
||||
indicatorColor: indicatorColor,
|
||||
hintColor: hintColor,
|
||||
errorColor: errorColor,
|
||||
textTheme: textTheme,
|
||||
primaryTextTheme: primaryTextTheme,
|
||||
accentTextTheme: accentTextTheme,
|
||||
iconTheme: iconTheme,
|
||||
primaryIconTheme: primaryIconTheme,
|
||||
accentIconTheme: accentIconTheme,
|
||||
platform: platform,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of [ThemeData.copyWith], shared with [_LocalizedThemeData.copyWith].
|
||||
ThemeData _copyThemeDataWith(
|
||||
ThemeData base, {
|
||||
@required Brightness brightness,
|
||||
@required Color primaryColor,
|
||||
@required Brightness primaryColorBrightness,
|
||||
@required Color accentColor,
|
||||
@required Brightness accentColorBrightness,
|
||||
@required Color canvasColor,
|
||||
@required Color scaffoldBackgroundColor,
|
||||
@required Color cardColor,
|
||||
@required Color dividerColor,
|
||||
@required Color highlightColor,
|
||||
@required Color splashColor,
|
||||
@required Color selectedRowColor,
|
||||
@required Color unselectedWidgetColor,
|
||||
@required Color disabledColor,
|
||||
@required Color buttonColor,
|
||||
@required Color secondaryHeaderColor,
|
||||
@required Color textSelectionColor,
|
||||
@required Color textSelectionHandleColor,
|
||||
@required Color backgroundColor,
|
||||
@required Color dialogBackgroundColor,
|
||||
@required Color indicatorColor,
|
||||
@required Color hintColor,
|
||||
@required Color errorColor,
|
||||
@required TextTheme textTheme,
|
||||
@required TextTheme primaryTextTheme,
|
||||
@required TextTheme accentTextTheme,
|
||||
@required IconThemeData iconTheme,
|
||||
@required IconThemeData primaryIconTheme,
|
||||
@required IconThemeData accentIconTheme,
|
||||
@required TargetPlatform platform,
|
||||
}) {
|
||||
return new ThemeData.raw(
|
||||
brightness: brightness ?? base.brightness,
|
||||
primaryColor: primaryColor ?? base.primaryColor,
|
||||
primaryColorBrightness: primaryColorBrightness ?? base.primaryColorBrightness,
|
||||
accentColor: accentColor ?? base.accentColor,
|
||||
accentColorBrightness: accentColorBrightness ?? base.accentColorBrightness,
|
||||
canvasColor: canvasColor ?? base.canvasColor,
|
||||
scaffoldBackgroundColor: scaffoldBackgroundColor ?? base.scaffoldBackgroundColor,
|
||||
cardColor: cardColor ?? base.cardColor,
|
||||
dividerColor: dividerColor ?? base.dividerColor,
|
||||
highlightColor: highlightColor ?? base.highlightColor,
|
||||
splashColor: splashColor ?? base.splashColor,
|
||||
selectedRowColor: selectedRowColor ?? base.selectedRowColor,
|
||||
unselectedWidgetColor: unselectedWidgetColor ?? base.unselectedWidgetColor,
|
||||
disabledColor: disabledColor ?? base.disabledColor,
|
||||
buttonColor: buttonColor ?? base.buttonColor,
|
||||
secondaryHeaderColor: secondaryHeaderColor ?? base.secondaryHeaderColor,
|
||||
textSelectionColor: textSelectionColor ?? base.textSelectionColor,
|
||||
textSelectionHandleColor: textSelectionHandleColor ?? base.textSelectionHandleColor,
|
||||
backgroundColor: backgroundColor ?? base.backgroundColor,
|
||||
dialogBackgroundColor: dialogBackgroundColor ?? base.dialogBackgroundColor,
|
||||
indicatorColor: indicatorColor ?? base.indicatorColor,
|
||||
hintColor: hintColor ?? base.hintColor,
|
||||
errorColor: errorColor ?? base.errorColor,
|
||||
textTheme: textTheme ?? base.textTheme,
|
||||
primaryTextTheme: primaryTextTheme ?? base.primaryTextTheme,
|
||||
accentTextTheme: accentTextTheme ?? base.accentTextTheme,
|
||||
iconTheme: iconTheme ?? base.iconTheme,
|
||||
primaryIconTheme: primaryIconTheme ?? base.primaryIconTheme,
|
||||
accentIconTheme: accentIconTheme ?? base.accentIconTheme,
|
||||
platform: platform ?? base.platform,
|
||||
);
|
||||
}
|
||||
|
@ -7,10 +7,6 @@ import 'package:flutter/painting.dart';
|
||||
|
||||
import 'colors.dart';
|
||||
|
||||
// TODO(eseidel): Font weights are supposed to be language relative.
|
||||
// TODO(jackson): Baseline should be language relative.
|
||||
// TODO(ianh): These values are for English-like text.
|
||||
|
||||
/// Material design text theme.
|
||||
///
|
||||
/// Definitions for the various typographical styles found in material design
|
||||
@ -62,58 +58,6 @@ class TextTheme {
|
||||
this.button,
|
||||
});
|
||||
|
||||
const TextTheme._blackMountainView()
|
||||
: 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);
|
||||
|
||||
const TextTheme._whiteMountainView()
|
||||
: 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);
|
||||
|
||||
const TextTheme._blackCupertino()
|
||||
: display4 = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w100, color: Colors.black54, textBaseline: TextBaseline.alphabetic),
|
||||
display3 = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 56.0, fontWeight: FontWeight.w400, color: Colors.black54, textBaseline: TextBaseline.alphabetic),
|
||||
display2 = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 45.0, fontWeight: FontWeight.w400, color: Colors.black54, textBaseline: TextBaseline.alphabetic),
|
||||
display1 = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 34.0, fontWeight: FontWeight.w400, color: Colors.black54, textBaseline: TextBaseline.alphabetic),
|
||||
headline = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 24.0, fontWeight: FontWeight.w400, color: Colors.black87, textBaseline: TextBaseline.alphabetic),
|
||||
title = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 20.0, fontWeight: FontWeight.w500, color: Colors.black87, textBaseline: TextBaseline.alphabetic),
|
||||
subhead = const TextStyle(fontFamily: '.SF UI Text', inherit: false, fontSize: 16.0, fontWeight: FontWeight.w400, color: Colors.black87, textBaseline: TextBaseline.alphabetic),
|
||||
body2 = const TextStyle(fontFamily: '.SF UI Text', inherit: false, fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.black87, textBaseline: TextBaseline.alphabetic),
|
||||
body1 = const TextStyle(fontFamily: '.SF UI Text', inherit: false, fontSize: 14.0, fontWeight: FontWeight.w400, color: Colors.black87, textBaseline: TextBaseline.alphabetic),
|
||||
caption = const TextStyle(fontFamily: '.SF UI Text', inherit: false, fontSize: 12.0, fontWeight: FontWeight.w400, color: Colors.black54, textBaseline: TextBaseline.alphabetic),
|
||||
button = const TextStyle(fontFamily: '.SF UI Text', inherit: false, fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.black87, textBaseline: TextBaseline.alphabetic);
|
||||
|
||||
const TextTheme._whiteCupertino()
|
||||
: display4 = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 112.0, fontWeight: FontWeight.w100, color: Colors.white70, textBaseline: TextBaseline.alphabetic),
|
||||
display3 = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 56.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic),
|
||||
display2 = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 45.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic),
|
||||
display1 = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 34.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic),
|
||||
headline = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 24.0, fontWeight: FontWeight.w400, color: Colors.white, textBaseline: TextBaseline.alphabetic),
|
||||
title = const TextStyle(fontFamily: '.SF UI Display', inherit: false, fontSize: 20.0, fontWeight: FontWeight.w500, color: Colors.white, textBaseline: TextBaseline.alphabetic),
|
||||
subhead = const TextStyle(fontFamily: '.SF UI Text', inherit: false, fontSize: 16.0, fontWeight: FontWeight.w400, color: Colors.white, textBaseline: TextBaseline.alphabetic),
|
||||
body2 = const TextStyle(fontFamily: '.SF UI Text', inherit: false, fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white, textBaseline: TextBaseline.alphabetic),
|
||||
body1 = const TextStyle(fontFamily: '.SF UI Text', inherit: false, fontSize: 14.0, fontWeight: FontWeight.w400, color: Colors.white, textBaseline: TextBaseline.alphabetic),
|
||||
caption = const TextStyle(fontFamily: '.SF UI Text', inherit: false, fontSize: 12.0, fontWeight: FontWeight.w400, color: Colors.white70, textBaseline: TextBaseline.alphabetic),
|
||||
button = const TextStyle(fontFamily: '.SF UI Text', inherit: false, fontSize: 14.0, fontWeight: FontWeight.w500, color: Colors.white, textBaseline: TextBaseline.alphabetic);
|
||||
|
||||
/// Extremely large text.
|
||||
///
|
||||
/// The font size is 112 pixels.
|
||||
@ -187,6 +131,24 @@ class TextTheme {
|
||||
);
|
||||
}
|
||||
|
||||
TextTheme merge(TextTheme other) {
|
||||
if (other == null)
|
||||
return this;
|
||||
return copyWith(
|
||||
display4: display4.merge(other.display4),
|
||||
display3: display3.merge(other.display3),
|
||||
display2: display2.merge(other.display2),
|
||||
display1: display1.merge(other.display1),
|
||||
headline: headline.merge(other.headline),
|
||||
title: title.merge(other.title),
|
||||
subhead: subhead.merge(other.subhead),
|
||||
body2: body2.merge(other.body2),
|
||||
body1: body1.merge(other.body1),
|
||||
caption: caption.merge(other.caption),
|
||||
button: button.merge(other.button),
|
||||
);
|
||||
}
|
||||
|
||||
/// Creates a copy of this text theme but with the given field replaced in
|
||||
/// each of the individual text styles.
|
||||
///
|
||||
@ -353,13 +315,13 @@ class Typography {
|
||||
case TargetPlatform.android:
|
||||
case TargetPlatform.fuchsia:
|
||||
return const Typography._(
|
||||
const TextTheme._blackMountainView(),
|
||||
const TextTheme._whiteMountainView(),
|
||||
_MaterialTextColorThemes.blackMountainView,
|
||||
_MaterialTextColorThemes.whiteMountainView,
|
||||
);
|
||||
case TargetPlatform.iOS:
|
||||
return const Typography._(
|
||||
const TextTheme._blackCupertino(),
|
||||
const TextTheme._whiteCupertino(),
|
||||
_MaterialTextColorThemes.blackCupertino,
|
||||
_MaterialTextColorThemes.whiteCupertino,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@ -373,3 +335,149 @@ class Typography {
|
||||
/// A material design text theme with light glyphs.
|
||||
final TextTheme white;
|
||||
}
|
||||
|
||||
/// Provides default text theme colors compliant with the Material Design
|
||||
/// specification.
|
||||
///
|
||||
/// The geometric font properties are missing in these color themes. App are
|
||||
/// expected to use [Theme.of] to get [TextTheme] objects fully populated with
|
||||
/// font properties.
|
||||
///
|
||||
/// See also: https://material.io/guidelines/style/typography.html
|
||||
// TODO(yjbanov): implement font fallback (see "Font stack" at https://material.io/guidelines/style/typography.html)
|
||||
class _MaterialTextColorThemes {
|
||||
static const TextTheme blackMountainView = const TextTheme(
|
||||
display4: const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black54),
|
||||
display3: const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black54),
|
||||
display2: const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black54),
|
||||
display1: const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black54),
|
||||
headline: const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black87),
|
||||
title : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black87),
|
||||
subhead : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black87),
|
||||
body2 : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black87),
|
||||
body1 : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black87),
|
||||
caption : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black54),
|
||||
button : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.black87),
|
||||
);
|
||||
|
||||
static const TextTheme whiteMountainView = const TextTheme(
|
||||
display4: const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white70),
|
||||
display3: const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white70),
|
||||
display2: const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white70),
|
||||
display1: const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white70),
|
||||
headline: const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white),
|
||||
title : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white),
|
||||
subhead : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white),
|
||||
body2 : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white),
|
||||
body1 : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white),
|
||||
caption : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white70),
|
||||
button : const TextStyle(fontFamily: 'Roboto', inherit: false, color: Colors.white),
|
||||
);
|
||||
|
||||
static const TextTheme blackCupertino = const TextTheme(
|
||||
display4: const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.black54),
|
||||
display3: const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.black54),
|
||||
display2: const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.black54),
|
||||
display1: const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.black54),
|
||||
headline: const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.black87),
|
||||
title : const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.black87),
|
||||
subhead : const TextStyle(fontFamily: '.SF UI Text', inherit: false, color: Colors.black87),
|
||||
body2 : const TextStyle(fontFamily: '.SF UI Text', inherit: false, color: Colors.black87),
|
||||
body1 : const TextStyle(fontFamily: '.SF UI Text', inherit: false, color: Colors.black87),
|
||||
caption : const TextStyle(fontFamily: '.SF UI Text', inherit: false, color: Colors.black54),
|
||||
button : const TextStyle(fontFamily: '.SF UI Text', inherit: false, color: Colors.black87),
|
||||
);
|
||||
|
||||
static const TextTheme whiteCupertino = const TextTheme(
|
||||
display4: const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.white70),
|
||||
display3: const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.white70),
|
||||
display2: const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.white70),
|
||||
display1: const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.white70),
|
||||
headline: const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.white),
|
||||
title : const TextStyle(fontFamily: '.SF UI Display', inherit: false, color: Colors.white),
|
||||
subhead : const TextStyle(fontFamily: '.SF UI Text', inherit: false, color: Colors.white),
|
||||
body2 : const TextStyle(fontFamily: '.SF UI Text', inherit: false, color: Colors.white),
|
||||
body1 : const TextStyle(fontFamily: '.SF UI Text', inherit: false, color: Colors.white),
|
||||
caption : const TextStyle(fontFamily: '.SF UI Text', inherit: false, color: Colors.white70),
|
||||
button : const TextStyle(fontFamily: '.SF UI Text', inherit: false, color: Colors.white),
|
||||
);
|
||||
}
|
||||
|
||||
/// Defines text geometries for the three language categories defined in
|
||||
/// https://material.io/guidelines/style/typography.html.
|
||||
class MaterialTextGeometry {
|
||||
/// The name of the English-like script category.
|
||||
static const String englishLikeCategory = 'English-like';
|
||||
|
||||
/// The name of the dense script category.
|
||||
static const String denseCategory = 'dense';
|
||||
|
||||
/// The name of the tall script category.
|
||||
static const String tallCategory = 'tall';
|
||||
|
||||
/// The mapping from script category names to text themes.
|
||||
static const Map<String, TextTheme> _categoryToTextTheme = const <String, TextTheme>{
|
||||
englishLikeCategory: englishLike,
|
||||
denseCategory: dense,
|
||||
tallCategory: tall,
|
||||
};
|
||||
|
||||
/// Looks up text geometry corresponding to the given [scriptCategoryName].
|
||||
///
|
||||
/// Most apps would not call this method directly, but rather call [Theme.of]
|
||||
/// and use the [TextTheme] fields of the returned [ThemeData] object.
|
||||
///
|
||||
/// [scriptCategoryName] must be one of [englishLikeCategory], [denseCategory]
|
||||
/// and [tallCategory].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [DefaultMaterialLocalizations.localTextGeometry], which uses this
|
||||
/// method to look-up text geometry for the current locale.
|
||||
static TextTheme forScriptCategory(String scriptCategoryName) => _categoryToTextTheme[scriptCategoryName];
|
||||
|
||||
/// Defines text geometry for English-like scripts, such as English, French, Russian, etc.
|
||||
static const TextTheme englishLike = const TextTheme(
|
||||
display4: const TextStyle(fontSize: 112.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.alphabetic),
|
||||
display3: const TextStyle(fontSize: 56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
display2: const TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
display1: const TextStyle(fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
headline: const TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
title : const TextStyle(fontSize: 20.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
|
||||
subhead : const TextStyle(fontSize: 16.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
body2 : const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
|
||||
body1 : const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
caption : const TextStyle(fontSize: 12.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
button : const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.alphabetic),
|
||||
);
|
||||
|
||||
/// Defines text geometry for dense scripts, such as Chinese, Japanese, Korean, etc.
|
||||
static const TextTheme dense = const TextTheme(
|
||||
display4: const TextStyle(fontSize: 112.0, fontWeight: FontWeight.w100, textBaseline: TextBaseline.ideographic),
|
||||
display3: const TextStyle(fontSize: 56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
|
||||
display2: const TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
|
||||
display1: const TextStyle(fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
|
||||
headline: const TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
|
||||
title : const TextStyle(fontSize: 21.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
|
||||
subhead : const TextStyle(fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
|
||||
body2 : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
|
||||
body1 : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
|
||||
caption : const TextStyle(fontSize: 13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.ideographic),
|
||||
button : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w500, textBaseline: TextBaseline.ideographic),
|
||||
);
|
||||
|
||||
/// Defines text geometry for tall scripts, such as Farsi, Hindi, Thai, etc.
|
||||
static const TextTheme tall = const TextTheme(
|
||||
display4: const TextStyle(fontSize: 112.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
display3: const TextStyle(fontSize: 56.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
display2: const TextStyle(fontSize: 45.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
display1: const TextStyle(fontSize: 34.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
headline: const TextStyle(fontSize: 24.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
title : const TextStyle(fontSize: 21.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
|
||||
subhead : const TextStyle(fontSize: 17.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
body2 : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
|
||||
body1 : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
caption : const TextStyle(fontSize: 13.0, fontWeight: FontWeight.w400, textBaseline: TextBaseline.alphabetic),
|
||||
button : const TextStyle(fontSize: 15.0, fontWeight: FontWeight.w700, textBaseline: TextBaseline.alphabetic),
|
||||
);
|
||||
}
|
||||
|
@ -401,10 +401,13 @@ class Localizations extends StatefulWidget {
|
||||
return new List<LocalizationsDelegate<dynamic>>.from(scope.localizationsState.widget.delegates);
|
||||
}
|
||||
|
||||
/// Returns the 'type' localized resources for the widget tree that
|
||||
/// corresponds to [BuildContext] `context`.
|
||||
/// Returns the localized resources object of the given `type` for the widget
|
||||
/// tree that corresponds to the given `context`.
|
||||
///
|
||||
/// This method is typically used by a static factory method on the 'type'
|
||||
/// Returns `null` if no resources object of the given `type` exists within
|
||||
/// the given `context`.
|
||||
///
|
||||
/// This method is typically used by a static factory method on the `type`
|
||||
/// class. For example Flutter's MaterialLocalizations class looks up Material
|
||||
/// resources with a method defined like this:
|
||||
///
|
||||
@ -417,8 +420,7 @@ class Localizations extends StatefulWidget {
|
||||
assert(context != null);
|
||||
assert(type != null);
|
||||
final _LocalizationsScope scope = context.inheritFromWidgetOfExactType(_LocalizationsScope);
|
||||
assert(scope != null, 'a Localizations ancestor was not found');
|
||||
return scope.localizationsState.resourcesFor<T>(type);
|
||||
return scope?.localizationsState?.resourcesFor<T>(type);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -0,0 +1,80 @@
|
||||
// Copyright 2017 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/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('$MaterialLocalizations localizes text inside the tree', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new MaterialApp(
|
||||
home: new ListView(
|
||||
children: <Widget>[
|
||||
new LocalizationTracker(key: const ValueKey<String>('outer')),
|
||||
new Localizations(
|
||||
locale: const Locale('zh', 'CN'),
|
||||
delegates: <LocalizationsDelegate<dynamic>>[
|
||||
new _MaterialLocalizationsDelegate(
|
||||
new DefaultMaterialLocalizations(const Locale('zh', 'CN')),
|
||||
),
|
||||
const DefaultWidgetsLocalizationsDelegate(),
|
||||
],
|
||||
child: new LocalizationTracker(key: const ValueKey<String>('inner')),
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
|
||||
final LocalizationTrackerState outerTracker = tester.state(find.byKey(const ValueKey<String>('outer')));
|
||||
expect(outerTracker.captionFontSize, 12.0);
|
||||
final LocalizationTrackerState innerTracker = tester.state(find.byKey(const ValueKey<String>('inner')));
|
||||
expect(innerTracker.captionFontSize, 13.0);
|
||||
});
|
||||
}
|
||||
|
||||
class LocalizationTracker extends StatefulWidget {
|
||||
LocalizationTracker({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => new LocalizationTrackerState();
|
||||
}
|
||||
|
||||
class LocalizationTrackerState extends State<LocalizationTracker> {
|
||||
double captionFontSize;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
captionFontSize = Theme.of(context).textTheme.caption.fontSize;
|
||||
return new Container();
|
||||
}
|
||||
}
|
||||
|
||||
// Same as _MaterialLocalizationsDelegate in widgets/app.dart
|
||||
class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
|
||||
const _MaterialLocalizationsDelegate(this.localizations);
|
||||
|
||||
final MaterialLocalizations localizations;
|
||||
|
||||
@override
|
||||
Future<MaterialLocalizations> load(Locale locale) {
|
||||
return new SynchronousFuture<MaterialLocalizations>(localizations);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldReload(_MaterialLocalizationsDelegate old) => false;
|
||||
}
|
||||
|
||||
// Same as _WidgetsLocalizationsDelegate in widgets/app.dart
|
||||
class DefaultWidgetsLocalizationsDelegate extends LocalizationsDelegate<WidgetsLocalizations> {
|
||||
const DefaultWidgetsLocalizationsDelegate();
|
||||
|
||||
@override
|
||||
Future<WidgetsLocalizations> load(Locale locale) {
|
||||
return new SynchronousFuture<WidgetsLocalizations>(new DefaultWidgetsLocalizations(locale));
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldReload(DefaultWidgetsLocalizationsDelegate old) => false;
|
||||
}
|
@ -4,8 +4,8 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
@ -789,8 +789,11 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('TextField with default helperStyle', (WidgetTester tester) async {
|
||||
final ThemeData themeData = new ThemeData(
|
||||
hintColor: Colors.blue[500],
|
||||
final ThemeData themeData = ThemeData.localize(
|
||||
new ThemeData(
|
||||
hintColor: Colors.blue[500],
|
||||
),
|
||||
MaterialTextGeometry.forScriptCategory(MaterialTextGeometry.englishLikeCategory),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
|
@ -53,7 +53,9 @@ void main() {
|
||||
)
|
||||
);
|
||||
|
||||
expect(Theme.of(capturedContext), equals(new ThemeData.fallback()));
|
||||
final dynamic localizedTheme = Theme.of(capturedContext);
|
||||
expect('${localizedTheme.runtimeType}', '_LocalizedThemeData');
|
||||
expect(localizedTheme.delegate, equals(new ThemeData.fallback()));
|
||||
expect(Theme.of(capturedContext, shadowThemeOnly: true), isNull);
|
||||
});
|
||||
|
||||
|
@ -30,23 +30,27 @@ void main() {
|
||||
|
||||
test('Typography on iOS defaults to the correct SF font family based on size', () {
|
||||
// Ref: https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography/
|
||||
final Matcher hasCorrectFont = predicate((TextStyle s) {
|
||||
return s.fontFamily == (s.fontSize <= 19.0 ? '.SF UI Text' : '.SF UI Display');
|
||||
}, 'Uses SF Display font for font sizes over 19.0, otherwise SF Text font');
|
||||
final Matcher isDisplayFont = predicate((TextStyle s) {
|
||||
return s.fontFamily == '.SF UI Display';
|
||||
}, 'Uses SF Display font');
|
||||
|
||||
final Matcher isTextFont = predicate((TextStyle s) {
|
||||
return s.fontFamily == '.SF UI Text';
|
||||
}, 'Uses SF Text font');
|
||||
|
||||
final Typography typography = new Typography(platform: TargetPlatform.iOS);
|
||||
for (TextTheme textTheme in <TextTheme>[typography.black, typography.white]) {
|
||||
expect(textTheme.display4, hasCorrectFont);
|
||||
expect(textTheme.display3, hasCorrectFont);
|
||||
expect(textTheme.display2, hasCorrectFont);
|
||||
expect(textTheme.display1, hasCorrectFont);
|
||||
expect(textTheme.headline, hasCorrectFont);
|
||||
expect(textTheme.title, hasCorrectFont);
|
||||
expect(textTheme.subhead, hasCorrectFont);
|
||||
expect(textTheme.body2, hasCorrectFont);
|
||||
expect(textTheme.body1, hasCorrectFont);
|
||||
expect(textTheme.caption, hasCorrectFont);
|
||||
expect(textTheme.button, hasCorrectFont);
|
||||
expect(textTheme.display4, isDisplayFont);
|
||||
expect(textTheme.display3, isDisplayFont);
|
||||
expect(textTheme.display2, isDisplayFont);
|
||||
expect(textTheme.display1, isDisplayFont);
|
||||
expect(textTheme.headline, isDisplayFont);
|
||||
expect(textTheme.title, isDisplayFont);
|
||||
expect(textTheme.subhead, isTextFont);
|
||||
expect(textTheme.body2, isTextFont);
|
||||
expect(textTheme.body1, isTextFont);
|
||||
expect(textTheme.caption, isTextFont);
|
||||
expect(textTheme.button, isTextFont);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user