Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
0a69e810
Unverified
Commit
0a69e810
authored
Jul 29, 2020
by
Rami
Committed by
GitHub
Jul 29, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Material] Add support for high contrast theming to Material apps (#62337)
parent
e9e36f39
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
241 additions
and
8 deletions
+241
-8
app.dart
packages/flutter/lib/src/material/app.dart
+44
-8
color_scheme.dart
packages/flutter/lib/src/material/color_scheme.dart
+61
-0
media_query.dart
packages/flutter/lib/src/widgets/media_query.dart
+11
-0
app_test.dart
packages/flutter/test/material/app_test.dart
+60
-0
color_scheme_test.dart
packages/flutter/test/material/color_scheme_test.dart
+38
-0
media_query_test.dart
packages/flutter/test/widgets/media_query_test.dart
+27
-0
No files found.
packages/flutter/lib/src/material/app.dart
View file @
0a69e810
...
...
@@ -180,6 +180,8 @@ class MaterialApp extends StatefulWidget {
this
.
color
,
this
.
theme
,
this
.
darkTheme
,
this
.
highContrastTheme
,
this
.
highContrastDarkTheme
,
this
.
themeMode
=
ThemeMode
.
system
,
this
.
locale
,
this
.
localizationsDelegates
,
...
...
@@ -294,6 +296,35 @@ class MaterialApp extends StatefulWidget {
/// [MediaQueryData.platformBrightness].
final
ThemeData
darkTheme
;
/// The [ThemeData] to use when 'high contrast' is requested by the system.
///
/// Some host platforms (for example, iOS) allow the users to increase
/// contrast through an accessibility setting.
///
/// Uses [theme] instead when null.
///
/// See also:
///
/// * [MediaQueryData.highContrast], which indicates the platform's
/// desire to increase contrast.
final
ThemeData
highContrastTheme
;
/// The [ThemeData] to use when a 'dark mode' and 'high contrast' is requested
/// by the system.
///
/// Some host platforms (for example, iOS) allow the users to increase
/// contrast through an accessibility setting.
///
/// This theme should have a [ThemeData.brightness] set to [Brightness.dark].
///
/// Uses [darkTheme] instead when null.
///
/// See also:
///
/// * [MediaQueryData.highContrast], which indicates the platform's
/// desire to increase contrast.
final
ThemeData
highContrastDarkTheme
;
/// Determines which theme will be used by the application if both [theme]
/// and [darkTheme] are provided.
///
...
...
@@ -616,17 +647,22 @@ class _MaterialAppState extends State<MaterialApp> {
onGenerateInitialRoutes:
widget
.
onGenerateInitialRoutes
,
onUnknownRoute:
widget
.
onUnknownRoute
,
builder:
(
BuildContext
context
,
Widget
child
)
{
//
Use a light theme, dark theme, or fallback theme
.
//
Resolve which theme to use based on brightness and high contrast
.
final
ThemeMode
mode
=
widget
.
themeMode
??
ThemeMode
.
system
;
final
Brightness
platformBrightness
=
MediaQuery
.
platformBrightnessOf
(
context
);
final
bool
useDarkTheme
=
mode
==
ThemeMode
.
dark
||
(
mode
==
ThemeMode
.
system
&&
platformBrightness
==
ui
.
Brightness
.
dark
);
final
bool
highContrast
=
MediaQuery
.
highContrastOf
(
context
);
ThemeData
theme
;
if
(
widget
.
darkTheme
!=
null
)
{
final
ui
.
Brightness
platformBrightness
=
MediaQuery
.
platformBrightnessOf
(
context
);
if
(
mode
==
ThemeMode
.
dark
||
(
mode
==
ThemeMode
.
system
&&
platformBrightness
==
ui
.
Brightness
.
dark
))
{
theme
=
widget
.
darkTheme
;
}
if
(
useDarkTheme
&&
highContrast
)
{
theme
=
widget
.
highContrastDarkTheme
;
}
else
if
(
useDarkTheme
)
{
theme
=
widget
.
darkTheme
;
}
else
if
(
highContrast
)
{
theme
=
widget
.
highContrastTheme
;
}
theme
??=
widget
.
theme
??
ThemeData
.
fallback
();
theme
??=
widget
.
theme
??
ThemeData
.
light
();
return
AnimatedTheme
(
data:
theme
,
...
...
packages/flutter/lib/src/material/color_scheme.dart
View file @
0a69e810
...
...
@@ -108,6 +108,67 @@ class ColorScheme with Diagnosticable {
assert
(
onError
!=
null
),
assert
(
brightness
!=
null
);
/// Create a high contrast ColorScheme based on a purple primary color that
/// matches the [baseline Material color scheme](https://material.io/design/color/the-color-system.html#color-theme-creation).
const
ColorScheme
.
highContrastLight
({
this
.
primary
=
const
Color
(
0xff0000ba
),
this
.
primaryVariant
=
const
Color
(
0xff000088
),
this
.
secondary
=
const
Color
(
0xff66fff9
),
this
.
secondaryVariant
=
const
Color
(
0xff018786
),
this
.
surface
=
Colors
.
white
,
this
.
background
=
Colors
.
white
,
this
.
error
=
const
Color
(
0xff790000
),
this
.
onPrimary
=
Colors
.
white
,
this
.
onSecondary
=
Colors
.
black
,
this
.
onSurface
=
Colors
.
black
,
this
.
onBackground
=
Colors
.
black
,
this
.
onError
=
Colors
.
white
,
this
.
brightness
=
Brightness
.
light
,
})
:
assert
(
primary
!=
null
),
assert
(
primaryVariant
!=
null
),
assert
(
secondary
!=
null
),
assert
(
secondaryVariant
!=
null
),
assert
(
surface
!=
null
),
assert
(
background
!=
null
),
assert
(
error
!=
null
),
assert
(
onPrimary
!=
null
),
assert
(
onSecondary
!=
null
),
assert
(
onSurface
!=
null
),
assert
(
onBackground
!=
null
),
assert
(
onError
!=
null
),
assert
(
brightness
!=
null
);
/// Create a high contrast ColorScheme based on the dark
/// [baseline Material color scheme](https://material.io/design/color/dark-theme.html#ui-application).
const
ColorScheme
.
highContrastDark
({
this
.
primary
=
const
Color
(
0xffefb7ff
),
this
.
primaryVariant
=
const
Color
(
0xffbe9eff
),
this
.
secondary
=
const
Color
(
0xff66fff9
),
this
.
secondaryVariant
=
const
Color
(
0xff66fff9
),
this
.
surface
=
const
Color
(
0xff121212
),
this
.
background
=
const
Color
(
0xff121212
),
this
.
error
=
const
Color
(
0xff9b374d
),
this
.
onPrimary
=
Colors
.
black
,
this
.
onSecondary
=
Colors
.
black
,
this
.
onSurface
=
Colors
.
white
,
this
.
onBackground
=
Colors
.
white
,
this
.
onError
=
Colors
.
black
,
this
.
brightness
=
Brightness
.
dark
,
})
:
assert
(
primary
!=
null
),
assert
(
primaryVariant
!=
null
),
assert
(
secondary
!=
null
),
assert
(
secondaryVariant
!=
null
),
assert
(
surface
!=
null
),
assert
(
background
!=
null
),
assert
(
error
!=
null
),
assert
(
onPrimary
!=
null
),
assert
(
onSecondary
!=
null
),
assert
(
onSurface
!=
null
),
assert
(
onBackground
!=
null
),
assert
(
onError
!=
null
),
assert
(
brightness
!=
null
);
/// Create a color scheme from a [MaterialColor] swatch.
///
/// This constructor is used by [ThemeData] to create its default
...
...
packages/flutter/lib/src/widgets/media_query.dart
View file @
0a69e810
...
...
@@ -843,6 +843,17 @@ class MediaQuery extends InheritedWidget {
return
MediaQuery
.
of
(
context
,
nullOk:
true
)?.
platformBrightness
??
Brightness
.
light
;
}
/// Returns highContrast for the nearest MediaQuery ancestor or false, if no
/// such ancestor exists.
///
/// See also:
///
/// * [MediaQueryData.highContrast], which indicates the platform's
/// desire to increase contrast.
static
bool
highContrastOf
(
BuildContext
context
)
{
return
MediaQuery
.
of
(
context
,
nullOk:
true
)?.
highContrast
??
false
;
}
/// Returns the boldText accessibility setting for the nearest MediaQuery
/// ancestor, or false if no such ancestor exists.
static
bool
boldTextOverride
(
BuildContext
context
)
{
...
...
packages/flutter/test/material/app_test.dart
View file @
0a69e810
...
...
@@ -752,6 +752,66 @@ void main() {
expect
(
appliedTheme
.
brightness
,
Brightness
.
dark
);
});
testWidgets
(
'MaterialApp uses high contrast theme when appropriate'
,
(
WidgetTester
tester
)
async
{
tester
.
binding
.
window
.
platformBrightnessTestValue
=
Brightness
.
light
;
tester
.
binding
.
window
.
accessibilityFeaturesTestValue
=
MockAccessibilityFeature
();
ThemeData
appliedTheme
;
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
(
primaryColor:
Colors
.
lightBlue
,
),
highContrastTheme:
ThemeData
(
primaryColor:
Colors
.
blue
,
),
home:
Builder
(
builder:
(
BuildContext
context
)
{
appliedTheme
=
Theme
.
of
(
context
);
return
const
SizedBox
();
},
),
),
);
expect
(
appliedTheme
.
primaryColor
,
Colors
.
blue
);
tester
.
binding
.
window
.
accessibilityFeaturesTestValue
=
null
;
});
testWidgets
(
'MaterialApp uses high contrast dark theme when appropriate'
,
(
WidgetTester
tester
)
async
{
tester
.
binding
.
window
.
platformBrightnessTestValue
=
Brightness
.
dark
;
tester
.
binding
.
window
.
accessibilityFeaturesTestValue
=
MockAccessibilityFeature
();
ThemeData
appliedTheme
;
await
tester
.
pumpWidget
(
MaterialApp
(
theme:
ThemeData
(
primaryColor:
Colors
.
lightBlue
,
),
darkTheme:
ThemeData
(
primaryColor:
Colors
.
lightGreen
,
),
highContrastTheme:
ThemeData
(
primaryColor:
Colors
.
blue
,
),
highContrastDarkTheme:
ThemeData
(
primaryColor:
Colors
.
green
,
),
home:
Builder
(
builder:
(
BuildContext
context
)
{
appliedTheme
=
Theme
.
of
(
context
);
return
const
SizedBox
();
},
),
),
);
expect
(
appliedTheme
.
primaryColor
,
Colors
.
green
);
tester
.
binding
.
window
.
accessibilityFeaturesTestValue
=
null
;
});
testWidgets
(
'MaterialApp switches themes when the Window platformBrightness changes.'
,
(
WidgetTester
tester
)
async
{
// Mock the Window to explicitly report a light platformBrightness.
final
TestWidgetsFlutterBinding
binding
=
tester
.
binding
;
...
...
packages/flutter/test/material/color_scheme_test.dart
View file @
0a69e810
...
...
@@ -45,4 +45,42 @@ void main() {
expect
(
scheme
.
onError
,
const
Color
(
0xff000000
));
expect
(
scheme
.
brightness
,
Brightness
.
dark
);
});
test
(
'high contrast light scheme matches the spec'
,
()
{
// Colors are based off of the Material Design baseline default theme:
// https://material.io/design/color/dark-theme.html#ui-application
const
ColorScheme
scheme
=
ColorScheme
.
highContrastLight
();
expect
(
scheme
.
primary
,
const
Color
(
0xff0000ba
));
expect
(
scheme
.
primaryVariant
,
const
Color
(
0xff000088
));
expect
(
scheme
.
secondary
,
const
Color
(
0xff66fff9
));
expect
(
scheme
.
secondaryVariant
,
const
Color
(
0xff018786
));
expect
(
scheme
.
background
,
const
Color
(
0xffffffff
));
expect
(
scheme
.
surface
,
const
Color
(
0xffffffff
));
expect
(
scheme
.
error
,
const
Color
(
0xff790000
));
expect
(
scheme
.
onPrimary
,
const
Color
(
0xffffffff
));
expect
(
scheme
.
onSecondary
,
const
Color
(
0xff000000
));
expect
(
scheme
.
onBackground
,
const
Color
(
0xff000000
));
expect
(
scheme
.
onSurface
,
const
Color
(
0xff000000
));
expect
(
scheme
.
onError
,
const
Color
(
0xffffffff
));
expect
(
scheme
.
brightness
,
Brightness
.
light
);
});
test
(
'high contrast dark scheme matches the spec'
,
()
{
// Colors are based off of the Material Design baseline dark theme:
// https://material.io/design/color/dark-theme.html#ui-application
const
ColorScheme
scheme
=
ColorScheme
.
highContrastDark
();
expect
(
scheme
.
primary
,
const
Color
(
0xffefb7ff
));
expect
(
scheme
.
primaryVariant
,
const
Color
(
0xffbe9eff
));
expect
(
scheme
.
secondary
,
const
Color
(
0xff66fff9
));
expect
(
scheme
.
secondaryVariant
,
const
Color
(
0xff66fff9
));
expect
(
scheme
.
background
,
const
Color
(
0xff121212
));
expect
(
scheme
.
surface
,
const
Color
(
0xff121212
));
expect
(
scheme
.
error
,
const
Color
(
0xff9b374d
));
expect
(
scheme
.
onPrimary
,
const
Color
(
0xff000000
));
expect
(
scheme
.
onSecondary
,
const
Color
(
0xff000000
));
expect
(
scheme
.
onBackground
,
const
Color
(
0xffffffff
));
expect
(
scheme
.
onSurface
,
const
Color
(
0xffffffff
));
expect
(
scheme
.
onError
,
const
Color
(
0xff000000
));
expect
(
scheme
.
brightness
,
Brightness
.
dark
);
});
}
packages/flutter/test/widgets/media_query_test.dart
View file @
0a69e810
...
...
@@ -535,6 +535,33 @@ void main() {
expect
(
insideBrightness
,
Brightness
.
dark
);
});
testWidgets
(
'MediaQuery.highContrastOf'
,
(
WidgetTester
tester
)
async
{
bool
outsideHighContrast
;
bool
insideHighContrast
;
await
tester
.
pumpWidget
(
Builder
(
builder:
(
BuildContext
context
)
{
outsideHighContrast
=
MediaQuery
.
highContrastOf
(
context
);
return
MediaQuery
(
data:
const
MediaQueryData
(
highContrast:
true
,
),
child:
Builder
(
builder:
(
BuildContext
context
)
{
insideHighContrast
=
MediaQuery
.
highContrastOf
(
context
);
return
Container
();
},
),
);
},
),
);
expect
(
outsideHighContrast
,
false
);
expect
(
insideHighContrast
,
true
);
});
testWidgets
(
'MediaQuery.boldTextOverride'
,
(
WidgetTester
tester
)
async
{
bool
outsideBoldTextOverride
;
bool
insideBoldTextOverride
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment