forked from firka/flutter
High contrast color scheme based on system forced colors (#165068)
This PR introduces a `bool useSystemColors` parameter to the `ThemeData` constructor. The goal from this PR is to enable users to easily create high contrast themes that are based on system colors for their `MaterialApp`: ```dart MaterialApp( theme: ThemeData.light(), darkTheme: ThemeData.dark(), highContrastTheme: ThemeData(useSystemColors: true, ...), highContrastDarkTheme: ThemeData(useSystemColors: true, ...), ) ``` The `MaterialApp` widget will automatically pick the correct one of the 4 themes based on system settings (light/dark mode, high contrast enabled/disabled). Depends on https://github.com/flutter/flutter/pull/164933 Closes https://github.com/flutter/flutter/issues/118853
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
/// @docImport 'package:flutter/material.dart';
|
||||
library;
|
||||
|
||||
import 'dart:ui' show Color, lerpDouble;
|
||||
import 'dart:ui' show Color, SystemColor, SystemColorPalette, lerpDouble;
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -32,8 +32,10 @@ import 'dialog_theme.dart';
|
||||
import 'divider_theme.dart';
|
||||
import 'drawer_theme.dart';
|
||||
import 'dropdown_menu_theme.dart';
|
||||
import 'elevated_button.dart';
|
||||
import 'elevated_button_theme.dart';
|
||||
import 'expansion_tile_theme.dart';
|
||||
import 'filled_button.dart';
|
||||
import 'filled_button_theme.dart';
|
||||
import 'floating_action_button_theme.dart';
|
||||
import 'icon_button_theme.dart';
|
||||
@@ -50,6 +52,7 @@ import 'menu_theme.dart';
|
||||
import 'navigation_bar_theme.dart';
|
||||
import 'navigation_drawer_theme.dart';
|
||||
import 'navigation_rail_theme.dart';
|
||||
import 'outlined_button.dart';
|
||||
import 'outlined_button_theme.dart';
|
||||
import 'page_transitions_theme.dart';
|
||||
import 'popup_menu_theme.dart';
|
||||
@@ -63,6 +66,7 @@ import 'slider_theme.dart';
|
||||
import 'snack_bar_theme.dart';
|
||||
import 'switch_theme.dart';
|
||||
import 'tab_bar_theme.dart';
|
||||
import 'text_button.dart';
|
||||
import 'text_button_theme.dart';
|
||||
import 'text_selection_theme.dart';
|
||||
import 'text_theme.dart';
|
||||
@@ -246,6 +250,11 @@ class ThemeData with Diagnosticable {
|
||||
/// a component theme parameter like [sliderTheme], [toggleButtonsTheme],
|
||||
/// or [bottomNavigationBarTheme].
|
||||
///
|
||||
/// When [useSystemColors] is true and the platform supports system colors, then the system colors
|
||||
/// will be used to override certain theme colors. The [colorScheme], [textTheme],
|
||||
/// [elevatedButtonTheme], [outlinedButtonTheme], [textButtonTheme], [filledButtonTheme], and
|
||||
/// [floatingActionButtonTheme] are overriden by the system colors.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ThemeData.from], which creates a ThemeData from a [ColorScheme].
|
||||
@@ -270,6 +279,7 @@ class ThemeData with Diagnosticable {
|
||||
ScrollbarThemeData? scrollbarTheme,
|
||||
InteractiveInkFeatureFactory? splashFactory,
|
||||
bool? useMaterial3,
|
||||
bool? useSystemColors,
|
||||
VisualDensity? visualDensity,
|
||||
// COLOR
|
||||
ColorScheme? colorScheme,
|
||||
@@ -387,6 +397,7 @@ class ThemeData with Diagnosticable {
|
||||
scrollbarTheme ??= const ScrollbarThemeData();
|
||||
visualDensity ??= VisualDensity.defaultDensityForPlatform(platform);
|
||||
useMaterial3 ??= true;
|
||||
useSystemColors ??= false;
|
||||
final bool useInkSparkle = platform == TargetPlatform.android && !kIsWeb;
|
||||
splashFactory ??=
|
||||
useMaterial3
|
||||
@@ -557,7 +568,8 @@ class ThemeData with Diagnosticable {
|
||||
buttonBarTheme ??= const ButtonBarThemeData();
|
||||
dialogBackgroundColor ??= isDark ? Colors.grey[800]! : Colors.white;
|
||||
indicatorColor ??= colorScheme.secondary == primaryColor ? Colors.white : colorScheme.secondary;
|
||||
return ThemeData.raw(
|
||||
|
||||
ThemeData theme = ThemeData.raw(
|
||||
// For the sanity of the reader, make sure these properties are in the same
|
||||
// order in every place that they are separated by section comments (e.g.
|
||||
// GENERAL CONFIGURATION). Each section except for deprecations should be
|
||||
@@ -651,6 +663,11 @@ class ThemeData with Diagnosticable {
|
||||
dialogBackgroundColor: dialogBackgroundColor,
|
||||
indicatorColor: indicatorColor,
|
||||
);
|
||||
|
||||
if (useSystemColors) {
|
||||
theme = theme._overrideWithSystemColors();
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
/// Create a [ThemeData] given a set of exact values. Most values must be
|
||||
@@ -1763,6 +1780,115 @@ class ThemeData with Diagnosticable {
|
||||
});
|
||||
}
|
||||
|
||||
ThemeData _overrideWithSystemColors() {
|
||||
if (!SystemColor.platformProvidesSystemColors) {
|
||||
return this;
|
||||
}
|
||||
|
||||
final SystemColorPalette systemColors =
|
||||
brightness == Brightness.dark ? SystemColor.dark : SystemColor.light;
|
||||
|
||||
ThemeData theme = this;
|
||||
|
||||
theme = theme.copyWith(
|
||||
colorScheme: colorScheme.copyWith(
|
||||
secondary: systemColors.accentColor.value,
|
||||
onSecondary: systemColors.accentColorText.value,
|
||||
surface: systemColors.canvas.value,
|
||||
onSurface: systemColors.canvasText.value,
|
||||
),
|
||||
textTheme: textTheme.apply(
|
||||
displayColor: systemColors.canvasText.value,
|
||||
bodyColor: systemColors.canvasText.value,
|
||||
),
|
||||
);
|
||||
|
||||
final bool overrideButtons =
|
||||
systemColors.buttonFace.value != null ||
|
||||
systemColors.buttonBorder.value != null ||
|
||||
systemColors.buttonText.value != null;
|
||||
|
||||
if (overrideButtons) {
|
||||
theme = theme.copyWith(
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: systemColors.buttonText.value,
|
||||
backgroundColor: systemColors.buttonFace.value,
|
||||
side:
|
||||
systemColors.buttonBorder.value == null
|
||||
? null
|
||||
: BorderSide(color: systemColors.buttonBorder.value!),
|
||||
),
|
||||
),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: systemColors.buttonText.value,
|
||||
backgroundColor: systemColors.buttonFace.value,
|
||||
side:
|
||||
systemColors.buttonBorder.value == null
|
||||
? null
|
||||
: BorderSide(color: systemColors.buttonBorder.value!),
|
||||
),
|
||||
),
|
||||
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: systemColors.buttonText.value,
|
||||
backgroundColor: systemColors.buttonFace.value,
|
||||
side:
|
||||
systemColors.buttonBorder.value == null
|
||||
? null
|
||||
: BorderSide(color: systemColors.buttonBorder.value!),
|
||||
),
|
||||
),
|
||||
filledButtonTheme: FilledButtonThemeData(
|
||||
style: FilledButton.styleFrom(
|
||||
foregroundColor: systemColors.buttonText.value,
|
||||
backgroundColor: systemColors.buttonFace.value,
|
||||
side:
|
||||
systemColors.buttonBorder.value == null
|
||||
? null
|
||||
: BorderSide(color: systemColors.buttonBorder.value!),
|
||||
),
|
||||
),
|
||||
floatingActionButtonTheme: FloatingActionButtonThemeData(
|
||||
backgroundColor: systemColors.buttonFace.value,
|
||||
foregroundColor: systemColors.buttonText.value,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final bool overrideInputDecoration =
|
||||
systemColors.field.value != null || systemColors.fieldText.value != null;
|
||||
|
||||
if (overrideInputDecoration) {
|
||||
theme = theme.copyWith(
|
||||
inputDecorationTheme: inputDecorationTheme.copyWith(
|
||||
fillColor: systemColors.field.value,
|
||||
labelStyle:
|
||||
inputDecorationTheme.labelStyle?.copyWith(color: systemColors.fieldText.value) ??
|
||||
TextStyle(color: systemColors.fieldText.value),
|
||||
hintStyle:
|
||||
inputDecorationTheme.hintStyle?.copyWith(color: systemColors.fieldText.value) ??
|
||||
TextStyle(color: systemColors.fieldText.value),
|
||||
helperStyle:
|
||||
inputDecorationTheme.helperStyle?.copyWith(color: systemColors.fieldText.value) ??
|
||||
TextStyle(color: systemColors.fieldText.value),
|
||||
prefixStyle:
|
||||
inputDecorationTheme.prefixStyle?.copyWith(color: systemColors.fieldText.value) ??
|
||||
TextStyle(color: systemColors.fieldText.value),
|
||||
suffixStyle:
|
||||
inputDecorationTheme.suffixStyle?.copyWith(color: systemColors.fieldText.value) ??
|
||||
TextStyle(color: systemColors.fieldText.value),
|
||||
counterStyle:
|
||||
inputDecorationTheme.counterStyle?.copyWith(color: systemColors.fieldText.value) ??
|
||||
TextStyle(color: systemColors.fieldText.value),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return theme;
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two themes.
|
||||
///
|
||||
/// {@macro dart.ui.shadow.lerp}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
@@ -377,6 +379,418 @@ void main() {
|
||||
expect(theme.applyElevationOverlayColor, false);
|
||||
});
|
||||
|
||||
test(
|
||||
'ThemeData applies light system colors when useSystemColors is true',
|
||||
() {
|
||||
final ThemeData theme = ThemeData(
|
||||
colorSchemeSeed: Colors.orange,
|
||||
brightness: Brightness.light,
|
||||
useSystemColors: true,
|
||||
);
|
||||
|
||||
expect(
|
||||
theme.colorScheme.secondary,
|
||||
SystemColor.light.accentColor.value,
|
||||
skip: !SystemColor.light.accentColor.isSupported, // Color not always supported.
|
||||
reason: 'Theme secondary color did not match system accent color',
|
||||
);
|
||||
expect(
|
||||
theme.colorScheme.onSecondary,
|
||||
SystemColor.light.accentColorText.value,
|
||||
skip: !SystemColor.light.accentColorText.isSupported, // Color not always supported.
|
||||
reason: 'Theme onSecondary color did not match system accent color text',
|
||||
);
|
||||
expect(
|
||||
theme.colorScheme.surface,
|
||||
SystemColor.light.canvas.value,
|
||||
skip: !SystemColor.light.canvas.isSupported, // Color not always supported.
|
||||
reason: 'Theme surface color did not match system canvas color',
|
||||
);
|
||||
expect(
|
||||
theme.colorScheme.onSurface,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'Theme onSurface color did not match system canvas color text',
|
||||
);
|
||||
|
||||
// Text theme
|
||||
|
||||
expect(
|
||||
theme.textTheme.displayLarge?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme displayLarge color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.displayMedium?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme displayMedium color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.displaySmall?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme displaySmall color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.headlineLarge?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme headlineLarge color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.headlineMedium?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme headlineMedium color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.headlineSmall?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme headlineSmall color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.titleLarge?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme titleLarge color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.titleMedium?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme titleMedium color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.titleSmall?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme titleSmall color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.bodyLarge?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme bodyLarge color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.bodyMedium?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme bodyMedium color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.bodySmall?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme bodySmall color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.labelLarge?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme labelLarge color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.labelMedium?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme labelMedium color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.labelSmall?.color,
|
||||
SystemColor.light.canvasText.value,
|
||||
skip: !SystemColor.light.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme labelSmall color did not match system text color',
|
||||
);
|
||||
|
||||
// Button themes
|
||||
|
||||
expect(
|
||||
theme.elevatedButtonTheme.style?.foregroundColor?.resolve(<WidgetState>{
|
||||
WidgetState.pressed,
|
||||
}),
|
||||
SystemColor.light.buttonText.value,
|
||||
skip: !SystemColor.light.buttonText.isSupported, // Color not always supported.
|
||||
reason: 'ElevatedButtonTheme foregroundColor did not match system button text color',
|
||||
);
|
||||
expect(
|
||||
theme.elevatedButtonTheme.style?.backgroundColor?.resolve(<WidgetState>{
|
||||
WidgetState.pressed,
|
||||
}),
|
||||
SystemColor.light.buttonFace.value,
|
||||
skip: !SystemColor.light.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'ElevatedButtonTheme backgroundColor did not match system button face color',
|
||||
);
|
||||
|
||||
expect(
|
||||
theme.textButtonTheme.style?.foregroundColor?.resolve(<WidgetState>{WidgetState.pressed}),
|
||||
SystemColor.light.buttonText.value,
|
||||
skip: !SystemColor.light.buttonText.isSupported, // Color not always supported.
|
||||
reason: 'TextButtonTheme foregroundColor did not match system button text color',
|
||||
);
|
||||
expect(
|
||||
theme.textButtonTheme.style?.backgroundColor?.resolve(<WidgetState>{WidgetState.pressed}),
|
||||
SystemColor.light.buttonFace.value,
|
||||
skip: !SystemColor.light.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'TextButtonTheme backgroundColor did not match system button face color',
|
||||
);
|
||||
|
||||
expect(
|
||||
theme.outlinedButtonTheme.style?.foregroundColor?.resolve(<WidgetState>{
|
||||
WidgetState.pressed,
|
||||
}),
|
||||
SystemColor.light.buttonText.value,
|
||||
skip: !SystemColor.light.buttonText.isSupported, // Color not always supported.
|
||||
reason: 'OutlinedButtonTheme foregroundColor did not match system button text color',
|
||||
);
|
||||
expect(
|
||||
theme.outlinedButtonTheme.style?.backgroundColor?.resolve(<WidgetState>{
|
||||
WidgetState.pressed,
|
||||
}),
|
||||
SystemColor.light.buttonFace.value,
|
||||
skip: !SystemColor.light.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'OutlinedButtonTheme backgroundColor did not match system button face color',
|
||||
);
|
||||
|
||||
expect(
|
||||
theme.filledButtonTheme.style?.foregroundColor?.resolve(<WidgetState>{WidgetState.pressed}),
|
||||
SystemColor.light.buttonText.value,
|
||||
skip: !SystemColor.light.buttonText.isSupported, // Color not always supported.
|
||||
reason: 'FilledButtonTheme foregroundColor did not match system button text color',
|
||||
);
|
||||
expect(
|
||||
theme.filledButtonTheme.style?.backgroundColor?.resolve(<WidgetState>{WidgetState.pressed}),
|
||||
SystemColor.light.buttonFace.value,
|
||||
skip: !SystemColor.light.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'FilledButtonTheme backgroundColor did not match system button face color',
|
||||
);
|
||||
|
||||
expect(
|
||||
theme.floatingActionButtonTheme.foregroundColor,
|
||||
SystemColor.light.buttonText.value,
|
||||
skip: !SystemColor.light.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'FloatingActionButtonTheme foregroundColor did not match system button text color',
|
||||
);
|
||||
expect(
|
||||
theme.floatingActionButtonTheme.backgroundColor,
|
||||
SystemColor.light.buttonFace.value,
|
||||
skip: !SystemColor.light.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'FloatingActionButtonTheme backgroundColor did not match system button face color',
|
||||
);
|
||||
},
|
||||
// Only run this test on platforms that provide system colors.
|
||||
skip: !SystemColor.platformProvidesSystemColors,
|
||||
);
|
||||
|
||||
test(
|
||||
'ThemeData applies dark system colors when useSystemColors is true',
|
||||
() {
|
||||
final ThemeData theme = ThemeData(
|
||||
colorSchemeSeed: Colors.orange,
|
||||
brightness: Brightness.dark,
|
||||
useSystemColors: true,
|
||||
);
|
||||
|
||||
expect(
|
||||
theme.colorScheme.secondary,
|
||||
SystemColor.dark.accentColor.value,
|
||||
skip: !SystemColor.dark.accentColor.isSupported, // Color not always supported.
|
||||
reason: 'Theme secondary color did not match system accent color',
|
||||
);
|
||||
expect(
|
||||
theme.colorScheme.onSecondary,
|
||||
SystemColor.dark.accentColorText.value,
|
||||
skip: !SystemColor.dark.accentColorText.isSupported, // Color not always supported.
|
||||
reason: 'Theme onSecondary color did not match system accent color text',
|
||||
);
|
||||
expect(
|
||||
theme.colorScheme.surface,
|
||||
SystemColor.dark.canvas.value,
|
||||
skip: !SystemColor.dark.canvas.isSupported, // Color not always supported.
|
||||
reason: 'Theme surface color did not match system canvas color',
|
||||
);
|
||||
expect(
|
||||
theme.colorScheme.onSurface,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'Theme onSurface color did not match system canvas color text',
|
||||
);
|
||||
|
||||
// Text theme
|
||||
|
||||
expect(
|
||||
theme.textTheme.displayLarge?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme displayLarge color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.displayMedium?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme displayMedium color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.displaySmall?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme displaySmall color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.headlineLarge?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme headlineLarge color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.headlineMedium?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme headlineMedium color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.headlineSmall?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme headlineSmall color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.titleLarge?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme titleLarge color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.titleMedium?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme titleMedium color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.titleSmall?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme titleSmall color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.bodyLarge?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme bodyLarge color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.bodyMedium?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme bodyMedium color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.bodySmall?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme bodySmall color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.labelLarge?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme labelLarge color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.labelMedium?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme labelMedium color did not match system text color',
|
||||
);
|
||||
expect(
|
||||
theme.textTheme.labelSmall?.color,
|
||||
SystemColor.dark.canvasText.value,
|
||||
skip: !SystemColor.dark.canvasText.isSupported, // Color not always supported.
|
||||
reason: 'TextTheme labelSmall color did not match system text color',
|
||||
);
|
||||
|
||||
// Button themes
|
||||
|
||||
expect(
|
||||
theme.elevatedButtonTheme.style?.foregroundColor?.resolve(<WidgetState>{
|
||||
WidgetState.pressed,
|
||||
}),
|
||||
SystemColor.dark.buttonText.value,
|
||||
skip: !SystemColor.dark.buttonText.isSupported, // Color not always supported.
|
||||
reason: 'ElevatedButtonTheme foregroundColor did not match system button text color',
|
||||
);
|
||||
expect(
|
||||
theme.elevatedButtonTheme.style?.backgroundColor?.resolve(<WidgetState>{
|
||||
WidgetState.pressed,
|
||||
}),
|
||||
SystemColor.dark.buttonFace.value,
|
||||
skip: !SystemColor.dark.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'ElevatedButtonTheme backgroundColor did not match system button face color',
|
||||
);
|
||||
|
||||
expect(
|
||||
theme.textButtonTheme.style?.foregroundColor?.resolve(<WidgetState>{WidgetState.pressed}),
|
||||
SystemColor.dark.buttonText.value,
|
||||
skip: !SystemColor.dark.buttonText.isSupported, // Color not always supported.
|
||||
reason: 'TextButtonTheme foregroundColor did not match system button text color',
|
||||
);
|
||||
expect(
|
||||
theme.textButtonTheme.style?.backgroundColor?.resolve(<WidgetState>{WidgetState.pressed}),
|
||||
SystemColor.dark.buttonFace.value,
|
||||
skip: !SystemColor.dark.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'TextButtonTheme backgroundColor did not match system button face color',
|
||||
);
|
||||
|
||||
expect(
|
||||
theme.outlinedButtonTheme.style?.foregroundColor?.resolve(<WidgetState>{
|
||||
WidgetState.pressed,
|
||||
}),
|
||||
SystemColor.dark.buttonText.value,
|
||||
skip: !SystemColor.dark.buttonText.isSupported, // Color not always supported.
|
||||
reason: 'OutlinedButtonTheme foregroundColor did not match system button text color',
|
||||
);
|
||||
expect(
|
||||
theme.outlinedButtonTheme.style?.backgroundColor?.resolve(<WidgetState>{
|
||||
WidgetState.pressed,
|
||||
}),
|
||||
SystemColor.dark.buttonFace.value,
|
||||
skip: !SystemColor.dark.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'OutlinedButtonTheme backgroundColor did not match system button face color',
|
||||
);
|
||||
|
||||
expect(
|
||||
theme.filledButtonTheme.style?.foregroundColor?.resolve(<WidgetState>{WidgetState.pressed}),
|
||||
SystemColor.dark.buttonText.value,
|
||||
skip: !SystemColor.dark.buttonText.isSupported, // Color not always supported.
|
||||
reason: 'FilledButtonTheme foregroundColor did not match system button text color',
|
||||
);
|
||||
expect(
|
||||
theme.filledButtonTheme.style?.backgroundColor?.resolve(<WidgetState>{WidgetState.pressed}),
|
||||
SystemColor.dark.buttonFace.value,
|
||||
skip: !SystemColor.dark.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'FilledButtonTheme backgroundColor did not match system button face color',
|
||||
);
|
||||
|
||||
expect(
|
||||
theme.floatingActionButtonTheme.foregroundColor,
|
||||
SystemColor.dark.buttonText.value,
|
||||
skip: !SystemColor.dark.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'FloatingActionButtonTheme foregroundColor did not match system button text color',
|
||||
);
|
||||
expect(
|
||||
theme.floatingActionButtonTheme.backgroundColor,
|
||||
SystemColor.dark.buttonFace.value,
|
||||
skip: !SystemColor.dark.buttonFace.isSupported, // Color not always supported.
|
||||
reason: 'FloatingActionButtonTheme backgroundColor did not match system button face color',
|
||||
);
|
||||
},
|
||||
// Only run this test on platforms that provide system colors.
|
||||
skip: !SystemColor.platformProvidesSystemColors,
|
||||
);
|
||||
|
||||
test(
|
||||
'ThemeData.light() can generate a default M3 light colorScheme when useMaterial3 is true',
|
||||
() {
|
||||
|
||||
Reference in New Issue
Block a user