I want to display dark or light mode based on the settings of the device.
I need to get the brightness of the device when building my ThemeData, something like this:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final materialLightTheme = ThemeData(
primaryColor: Colors.blueAccent,
brightness: Brightness.light,
scaffoldBackgroundColor: MyColors.backgroundColor0(Brightness.light),
appBarTheme: AppBarTheme(
color: MyColors.backgroundColor1(Brightness.light)
),
);
final materialDarkTheme = ThemeData(
primaryColor: Colors.blueAccent,
brightness: Brightness.dark,
scaffoldBackgroundColor: MyColors.backgroundColor0(Brightness.dark),
appBarTheme: AppBarTheme(
color: MyColors.backgroundColor1(Brightness.dark)
),
);
Brightness brightness = MediaQuery.of(context).platformBrightness;
return MaterialApp(
themeMode: brightness == Brightness.light
? ThemeMode.light
: ThemeMode.dark,
theme: materialLightTheme,
darkTheme: materialDarkTheme,
home: MyHomePage(),
);
}
}
But it seems, MediaQuery is not available in the build Method outside of an Material App. I get the Error
MediaQuery.of() called with a context that does not contain a
MediaQuery.
How can I achieve this behaviour?
First for your use case, if you just want to apply dark and light theme based on system's dark mode, then it is automatically handled by the Flutter, just by providing the darkTheme property in your MaterialApp widget, whenever the system's dark mode is activated, the theme supplied in the darkTheme parameter will automatically activate.
However if you do want to access MediaQuery before you apply themes and other stuff to your app via MaterialApp, from what I know you need either MaterialApp or WidgetsApp before in the widget tree in order to get the MediaQuery.of(context). However, we can workaround that by using, two MaterialApp widgets one for just getting the MediaQuery in the second you apply the theming and all other stuff as below
void main() => runApp(MaterialApp(home: MyApp()));
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final materialLightTheme = ThemeData(
primaryColor: Colors.blueAccent,
brightness: Brightness.light,
scaffoldBackgroundColor: MyColors.backgroundColor0(Brightness.light),
appBarTheme: AppBarTheme(
color: MyColors.backgroundColor1(Brightness.light)
),
);
final materialDarkTheme = ThemeData(
primaryColor: Colors.blueAccent,
brightness: Brightness.dark,
scaffoldBackgroundColor: MyColors.backgroundColor0(Brightness.dark),
appBarTheme: AppBarTheme(
color: MyColors.backgroundColor1(Brightness.dark)
),
);
Brightness brightness = MediaQuery.of(context).platformBrightness;
return MaterialApp(
themeMode: brightness == Brightness.light
? ThemeMode.light
: ThemeMode.dark,
theme: materialLightTheme,
darkTheme: materialDarkTheme,
home: MyHomePage(),
);
}
}
Related
I want to check if my Darkmode is enable or not so I did this:
#override
Widget build(BuildContext context) {
var brightness = MediaQuery.of(context).platformBrightness;
bool isDarkMode = brightness == Brightness.dark;
print(isDarkMode);
in the first widget which builds after the MaterialApp, but I always get false as print result, independently of the active Theme Mode. I also tried
var brightness = SchedulerBinding.instance.platformDispatcher.platformBrightness;
bool isDarkMode = brightness == Brightness.dark;
In the init state, but same problem
I checked if it's the fault of my project, so I created a brand-new Project and used the adaptive_theme package - still same problem
Code of the Material:
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return AdaptiveTheme(
light: ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.yellow,
backgroundColor: Colors.grey
),
dark: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.red,
backgroundColor: Colors.blue,
),
builder: (theme, darkTheme)=>MaterialApp(
title: 'Flutter Demo',
theme: theme,
darkTheme: darkTheme,
home: const MyHomePage(title: 'Flutter Demo Home Page'),
), initial: AdaptiveThemeMode.light,
);
}
}
I call MediaQuery.of(context).platformBrightness inside the MyHomePageState.
Any advices what I do wrong?
First make sure that you have added both ThemeModes in Material App itself:
Here's the example:
return MaterialApp(
title: "Dark",
debugShowCheckedModeBanner: false,
theme: ThemeData.copywith(brightness: Brightness.light),
darkTheme: ThemeData.copywith(brightness: Brightness.dark),
themeMode: ThemeMode.light,
);
Simpel answere to my question after a lot of research: In the current version ( 16.01.2022) MediaQuery.of(context).platformBrightness; is not the correct way to check if darkmode inside your app is enabled or not. This only works for checking which Theme the user uses on his system.
For checking on app level just use:
bool isDarkMode = Theme.of(context).brightness == Brightness.dark;
print(isDarkMode);
and it prints the correct value of the bool.
Let me know if you have a different information.
class BMICalculator extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.red,
),
home: InputPage(),
);
I am taking this course: https://www.udemy.com/course/flutter-bootcamp-with-dart/
and with the section on themes she uses this exact code to turn her appBar red. My code does not display any errors, however my appBar remains the default theme.
The description of primary color here: https://api.flutter.dev/flutter/material/ThemeData-class.html
It doesn't say it is depreciated, or indicate any recent changes.
My question is not "how can I make my app bar red", but rather, "why does this code not perform as expected?"
PrimaryColor won't work in themeData directly you have to declare it in colorScheme
theme: ThemeData(colorScheme: ColorScheme.light(primary: Colors.red)),
You can either use primarySwatch
theme: ThemeData(primarySwatch: Colors.red),
or you can use appBarTheme
appBarTheme: AppBarTheme(
backgroundColor: Colors.red
),
primarySwatch is not a Color. It's MaterialColor. Which means it's a the different shades of a color a material app will use.
primaryColor is one of those shades. To be exact, primaryColor is normally equal to primarySwatch[500]
ThemeData is one holding all of your theme settings, and the one controlling how the app will look, but ColorScheme is just a set of colors that you create to easily maintain the app's colors. Notice that ThemeData class has a parameter colorScheme, so you can create your own colorScheme and add it to the ThemeData object.
all of widgets styling inherits from colors or themes from ThemeData (defined in MaterialApp) not ColorScheme, colorScheme is just extra colors that you define to use whether in ThemeData or anywhere across the app.
AppBar background color comes from appBarTheme(color:..).
I prefer extending parent theme,
return MaterialApp(
primaryColor: Colors.green,// no effect on AppBar
theme: Theme.of(context).copyWith(
appBarTheme: Theme.of(context).appBarTheme.copyWith(
color: Colors.red,
),
),
More about theme.
MaterialApp(
theme: ThemeData.dark().copyWith(
primaryColor: Color(0xFF090C22),
backgroundColor: Color(0xFF090C22),
scaffoldBackgroundColor: Color(0xFF090C22),
appBarTheme: AppBarTheme(
backgroundColor: Color(0xFF090C22),
),
),
);
I am using flutter 2.8.0 to create a simple app.
But when I am trying to change the primary color for the App it does not work with me.
This is the code I am working on:
class BMICalculator extends StatelessWidget {
const BMICalculator({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
primaryColor: const Color(0xFF0A0E21),
scaffoldBackgroundColor: const Color(0xFF0A0E21),
),
home: const InputPage(),
);
}
}
#Mrinal already mentioned you to use primarySwatch. Flutter team intended to build clean up the Theme system and make everything more consistent and based off of the ColorScheme colors. They recommend using color scheme instead of primary color
theme: ThemeData(
primaryColor: ColorsX.primary,
colorScheme: ColorScheme.light().copyWith(primary: ColorsX.primary),
);
For dark theme
theme: ThemeData.dark().copyWith(
colorScheme: ColorScheme.light().copyWith(primary: Colors.tealAccent),
),
output:
For more read this article article
Use primarySwatch
theme: ThemeData(
primarySwatch: Colors.red,
),
I found a solution for me..
MaterialColor _primartSwatch = Colors.purple;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
themeMode: _themeMode,
theme: ThemeData(
primarySwatch: _primartSwatch,
),
darkTheme: ThemeData(
brightness: Brightness.dark,
primarySwatch: _primartSwatch,
),
home: SplashScreen(),
);
}
I am working with flutter projects
and I want to change the themecolor using an onpressed event
I tried some code but not working.
main.dart file
import 'package:flutter/material.dart';
import 'Screens/HomePage.dart';
void main()=> runApp(MyApp());
ThemeData _lightTheme = ThemeData(
brightness: Brightness.light,
primaryColor: Colors.white,
);
ThemeData _darkTheme = ThemeData(
brightness: Brightness.light,
primaryColor: Colors.white,
);
bool _ktheme = true;
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Wallbay',
theme: _ktheme ? _lightTheme : _darkTheme,
home: MyHomePage('Alpha Papers'),
);
}
}
HomePage.dart file
........
IconButton(
icon: Icon(Icons.brightness_medium_outlined),
onPressed: () {
setState(() {
_ktheme = !ktheme;
});
},
)
......
Your theme objects _lightTheme & _darkTheme are the same objects with different names.
They both have brightness set to Brightness.light & primaryColor as Colors.white.
ThemeData _lightTheme = ThemeData(
brightness: Brightness.light, // <----
primaryColor: Colors.white, // <----
);
ThemeData _darkTheme = ThemeData(
brightness: Brightness.light, // <--- Dark mode having light brightness
primaryColor: Colors.white, // <---- Dark mode having white color
);
Change these to the following:
ThemeData _lightTheme = ThemeData(
brightness: Brightness.light, // light mode
primaryColor: Colors.white,
);
ThemeData _darkTheme = ThemeData(
brightness: Brightness.dark, // dark mode
primaryColor: Colors.black,
);
Also, your onPressed code looks wrong.
setState(() {
_ktheme = !_ktheme; // Notice: I renamed ktheme to _ktheme
});
I want to remove the shadow from the search bar when using SearchDelegate but I can't find how to. Any tips?
This is basically all the code:
showSearch(
context: context,
delegate: CustomSearchDelegate(),
);
CustomSearchDelegate() just contains an empty search delegate widget/class.
#override
ThemeData appBarTheme(BuildContext context) {
return super.appBarTheme(context).copyWith(
appBarTheme: super.appBarTheme(context).appBarTheme.copyWith(
elevation: 0.0,
),
);
}
Add this inside the Searchdelegate class:
#override
ThemeData appBarTheme(BuildContext context){
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme.copyWith(
primaryColor: Colors.grey[50],
);
}
and this to the main app theme:
MaterialApp(
theme: ThemeData(
backgroundColor: Colors.white,
appBarTheme: AppBarTheme(elevation: 0.0), //This is important
title: 'Flutter Demo',
home: MyHomePage(),
);
Make changes accordingly in your ThemeData() and add the appBarTheme: AppBarTheme(elevation: 0.0), to remove the elevation and the SearchDelegate theme as it is your search delegate class which will ensure that the elevation defined in the ThemeData of your material app is implemented.
Note: I guess, that the elevation set in the ThemeData will affect the elevation of the appbar in other pages all over the app too.
Result:
Output image