Reputation: 156
Okay, So I've done a fair bit of research on this particular topic previously, and I'm aware that it is a feature that the Flutter devs have not yet implemented to function automatically (setting the light and dark themes to change dynamically checking upon opening the app) but I know it IS possible. I don't want my users to need to make this choice, and I know I'm close, but I'm missing something important. I'll explain:
final Brightness brightnessValue = MediaQuery.of(context).platformBrightness;
bool isDark = brightnessValue == Brightness.dark;
Those two lines of code SHOULD pass through a boolean (dark theme true or false) into my code. Those lines of code ARE running, but they throw an error.
MediaQuery.of() called with a context that does not contain a MediaQuery. No MediaQuery ancestor could be found starting from the context that was passed to MediaQuery.of(). This can happen because you do not have a WidgetsApp or MaterialApp widget (those widgets introduce a MediaQuery), or it can happen if the context you use comes from a widget above those widgets.). The context used was: MyApp see also: https://flutter.dev/docs/testing/errors
Now I've seen some people implement this line of code and it works for them, so I know it's not a syntax thing. And I actually AM placing this line of code underneath a widgets app like they ask, (as far as I understand these things, so I'm stymied.
Pertinent Code:
CupertinoThemeData currentTheme;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final Brightness brightnessValue = MediaQuery.of(context).platformBrightness;
bool isDark = brightnessValue == Brightness.dark;
<CODE TO SELECT THEME DEPENDING ON PHONE'S THEME. Setting parameters of currentTheme>
return CupertinoApp(
<CODE FOR APP>
),
}
}
Now I WOULD put it inside the CupertinoApp Widget, but that doesn't work either, as you can't really make a function-call inside there, and I NEED to pass a theme into there, as that effects the entirety of the programs theming.
In essence, it looks like a chicken and the egg scenario, where I can't set the theme until I have the media-query, and I can't do the media-query until I've already set the theme, which negates the entire purpose of the query.
Any ideas?
Upvotes: 0
Views: 1438
Reputation: 36373
Placing a DefaultTextStyle widget somewhere near the top of the widget tree is a good workaround. Just remember it needs to be one level lower than the CupertinoApp, or else it cannot find the inherited theme using its build context.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoApp(
home: Builder(
builder: (BuildContext context) {
return DefaultTextStyle(
style: CupertinoTheme.of(context).textTheme.textStyle,
child: MyHomePage(),
);
},
),
);
}
}
This way, any default Text will automatically resolve to white or black, depending on the platform brightness settings.
Sample result:
Upvotes: 0
Reputation: 156
After banging my head against a brick wall for a few hours, finally figured it out (For anyone else having a similar issue).
The trick is that yes, you do in fact need to place the code that selects the theme inside the line
return CupertinoApp( <Here> )
You can do this through:
builder: (BuildContext context, Widget child) {
final Brightness brightnessValue = MediaQuery.of(context).platformBrightness;
bool isDark = brightnessValue == Brightness.dark;
// All your code to set your two themes, light and dark can go here.
}
In this way, instead of the chicken&egg scenario I was imagining, you are setting the theme state at the moment you need it.
Hope this helps someone.
Upvotes: 1