forked from firka/flutter
Feat: Add brightnessOf method for theme (#163733)
Feat: Add brightnessOf method for theme fixes: #163393 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing.
This commit is contained in:
@@ -161,6 +161,42 @@ class Theme extends StatelessWidget {
|
||||
.resolveFrom(context);
|
||||
}
|
||||
|
||||
/// Retrieves the [Brightness] to use for descendant Material widgets, based
|
||||
/// on the value of [ThemeData.brightness] in the given [context].
|
||||
///
|
||||
/// If no [InheritedTheme] can be found in the given [context], or its `brightness`
|
||||
/// is null, it will fall back to [MediaQueryData.platformBrightness].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [maybeBrightnessOf], which returns null if no valid [InheritedTheme] or
|
||||
/// [MediaQuery] exists.
|
||||
/// * [ThemeData.brightness], the property that takes precedence over
|
||||
/// [MediaQueryData.platformBrightness] for descendant Material widgets.
|
||||
static Brightness brightnessOf(BuildContext context) {
|
||||
final _InheritedTheme? inheritedTheme =
|
||||
context.dependOnInheritedWidgetOfExactType<_InheritedTheme>();
|
||||
return inheritedTheme?.theme.data.brightness ?? MediaQuery.platformBrightnessOf(context);
|
||||
}
|
||||
|
||||
/// Retrieves the [Brightness] to use for descendant Material widgets, based
|
||||
/// on the value of [ThemeData.brightness] in the given [context].
|
||||
///
|
||||
/// If no [InheritedTheme] or [MediaQuery] can be found in the given [context], it will
|
||||
/// return null.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [ThemeData.brightness], the property that takes precedence over
|
||||
/// [MediaQueryData.platformBrightness] for descendant Material widgets.
|
||||
/// * [brightnessOf], which return a default value if no valid [InheritedTheme] or
|
||||
/// [MediaQuery] exists, instead of returning null.
|
||||
static Brightness? maybeBrightnessOf(BuildContext context) {
|
||||
final _InheritedTheme? inheritedTheme =
|
||||
context.dependOnInheritedWidgetOfExactType<_InheritedTheme>();
|
||||
return inheritedTheme?.theme.data.brightness ?? MediaQuery.maybePlatformBrightnessOf(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _InheritedTheme(
|
||||
|
||||
@@ -47,6 +47,92 @@ void main() {
|
||||
expect(Theme.of(tester.element(find.text('menuItem'))).brightness, equals(Brightness.dark));
|
||||
});
|
||||
|
||||
group('Theme.brightnessOf', () {
|
||||
testWidgets('return correct brightness when just media query is given', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
const MediaQuery(
|
||||
data: MediaQueryData(platformBrightness: Brightness.dark),
|
||||
child: SizedBox(),
|
||||
),
|
||||
);
|
||||
|
||||
expect(Theme.brightnessOf(tester.element(find.byType(SizedBox))), equals(Brightness.dark));
|
||||
});
|
||||
|
||||
testWidgets('return correct brightness with overriding theme brightness over media query', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(platformBrightness: Brightness.dark),
|
||||
child: Theme(data: ThemeData(brightness: Brightness.light), child: const SizedBox()),
|
||||
),
|
||||
);
|
||||
|
||||
expect(Theme.brightnessOf(tester.element(find.byType(SizedBox))), equals(Brightness.light));
|
||||
});
|
||||
|
||||
testWidgets('returns Brightness.light when no theme or media query is present', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
// Prevent the implicitly added View from adding a MediaQuery
|
||||
await tester.pumpWidget(
|
||||
RawView(view: FakeFlutterView(tester.view, viewId: 77), child: const SizedBox()),
|
||||
wrapWithView: false,
|
||||
);
|
||||
|
||||
expect(Theme.brightnessOf(tester.element(find.byType(SizedBox))), equals(Brightness.light));
|
||||
});
|
||||
});
|
||||
|
||||
group('Theme.maybeBrightnessOf', () {
|
||||
testWidgets('return correct brightness when just media query is given', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
const MediaQuery(
|
||||
data: MediaQueryData(platformBrightness: Brightness.dark),
|
||||
child: SizedBox(),
|
||||
),
|
||||
);
|
||||
|
||||
expect(
|
||||
Theme.maybeBrightnessOf(tester.element(find.byType(SizedBox))),
|
||||
equals(Brightness.dark),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('return correct brightness with overriding theme brightness over media query', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
await tester.pumpWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(platformBrightness: Brightness.dark),
|
||||
child: Theme(data: ThemeData(brightness: Brightness.light), child: const SizedBox()),
|
||||
),
|
||||
);
|
||||
|
||||
expect(
|
||||
Theme.maybeBrightnessOf(tester.element(find.byType(SizedBox))),
|
||||
equals(Brightness.light),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('returns null when no theme or media query is present', (
|
||||
WidgetTester tester,
|
||||
) async {
|
||||
// Prevent the implicitly added View from adding a MediaQuery
|
||||
await tester.pumpWidget(
|
||||
RawView(view: FakeFlutterView(tester.view, viewId: 77), child: const SizedBox()),
|
||||
wrapWithView: false,
|
||||
);
|
||||
|
||||
expect(Theme.maybeBrightnessOf(tester.element(find.byType(SizedBox))), isNull);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('Theme overrides selection style', (WidgetTester tester) async {
|
||||
final Key key = UniqueKey();
|
||||
const Color defaultSelectionColor = Color(0x11111111);
|
||||
@@ -1242,3 +1328,11 @@ class _TextStyleProxy implements TextStyle {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
class FakeFlutterView extends TestFlutterView {
|
||||
FakeFlutterView(TestFlutterView view, {required this.viewId})
|
||||
: super(view: view, display: view.display, platformDispatcher: view.platformDispatcher);
|
||||
|
||||
@override
|
||||
final int viewId;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user