dynamic_theme
dynamic_theme copied to clipboard
master
Add PlatformBrightness widget to allow automatic updating of the app's theme when the platform changes it's brightness.
How does the app get notified when the system brightness changes? And how is the PlatformBrightness
integrated with the DynamicTheme
? I can't seem to find a connection.
@Norbert515 , There was an API to be notified via callback, however, it required platform integrations and it only worked on Android Q. This was a complex solution, so I found out that there's a way to check for brightness. It's a simple builder that always rebuilds with the current platform Brightness setting. There's no notification, it just stays current anytime the widget tree rebuilds. I couldn't find anything to listen to unless I created my own stream, but it would only be updated during a build.
I tested it by putting a breakpoint in the builder of the PlatformBrightness
widget and then went to settings and changed the theme. The builder runs immediately after opening the app again and it contains the new value.
The only other way to test this without switching screens is if you did split-screen and changed it, but I still believe that this widget is called.
And how is the PlatformBrightness integrated with the DynamicTheme? I can't seem to find a connection.
What do you mean by that? I didn't make it a part of the existing widget because of separation of concerns. DynamicTheme
is for controlling the app's theme, and PlatformBrightness
is for having awareness of the system setting, which is different from the app's theme
Sounds good! But should the DynamicTheme
also adapt to the platform brightness (maybe with a flag to toggle that behavior)?
That should be up to the user. I believe it's only job should be to provide the current value, like orientation builders
What about didChangePlatformBrightness and onPlatformBrightnessChanged?
~~didPlatformChangeBrightness does look like the official way to do this actually~~
Oh, Nevermind. These are all methods. We're trying to provide a widget with the most recent value
Sure, you can use onPlatformBrightnessChanged
to get the most recent value.
I don't see how it's better than my suggestion solution. When the platformBrightness changes, MediaQuery rebuilds its descendants with that, which my widget depends on, so it works. No callbacks needed
Okay so if I understand this correctly, the PlatformBrightness
widget gets placed somewhere and provides the brightness. Right now, I'm thinking of apps like Gmail that let you choose between the system theme and dark and light mode. Would that be possible with this change?
Okay so if I understand this correctly, the
PlatformBrightness
widget gets placed somewhere and provides the brightness. Right now, I'm thinking of apps like Gmail that let you choose between the system theme and dark and light mode. Would that be possible with this change?
That's what the original DynamicTheme
offers already. The ability to change the apps's theme manually and dynamically. The new widget I'm proposing taps into the system's brightness mode and returns that. You can use this to make your app switch themes based on the system brightness instead of manually. There are some apps, like Google search, that automatically turn to dark mode if the system UI is dark. or they have manual modes too.
I forked the repo and added your changes to it. I also added to the example. I think I'm doing it wrong but your builder always returned Brightness.light
. It would be great if you could check it out and run it when you get time :)
What are you doing to view the changes? You have to go into system settings on the phone and change the theme to dark mode . This is an android pie or q thing
I'm running an emulator w/ Android 10 and changing the theme to dark mode.
I'm running an emulator w/ Android 10 and changing the theme to dark mode.
OK, let me retest
Here's my test on a pixel physical device on Q.
Can I see your code?
Sure, I just pushed another commit with the example added https://github.com/Norbert515/dynamic_theme/blob/0cedc2233014ca9f74aa7b1a37ce1fb0c0bb5fe0/example/lib/main.dart is the example file
Alright, I see. Only issue I see is that it doesn't work above MaterialApp so users are going to have to wrap all of their routes with a consumer or the PlatformBrightness
widget
It works for me ...
Not for me:
OK, I was expecting to see an error. It does show Light for me as well. One sec
I don't know how to resolve this cause it requires a WidgetsApp class above it.
How does Flutter do it with ThemeMode
(property of MaterialApp) then?
Because they access the variable you set there or default it to ThemeMode.system. Inside the widget, it uses MediaQuery.platformBrightnessOf(context); which works because this is separated by a builder and the MediaQuery is already in the widget tree by that time.
builder: (BuildContext context, Widget child) {
// Use a light theme, dark theme, or fallback theme.
final ThemeMode mode = widget.themeMode ?? ThemeMode.system;
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;
}
}
@Reprevise best thing I can do is make a warning or throw an error if it's put above the MaterialApp, mentioning that there's no ancestor found, since MediaQuery by default returns Brightness.light if it can't find the value
Alright, sounds like the best option
@ThinkDigitalSoftware Conflicting files