Flutter ColorScheme CopyWith brightness not working - flutter

In my Flutter project app_theme.dart file I have this code:
class AppTheme {
static const primaryColor = Color.fromARGB(255, 106, 49, 185);
static ThemeData lightTheme() {
return ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: primaryColor,
brightness: Brightness.light,
),
);
}
static ThemeData darkTheme() {
return ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: primaryColor,
brightness: Brightness.dark,
),
);
}
Then in main.dart, my Material App widget implements this like so:
theme: AppTheme.lightTheme(),
darkTheme: AppTheme.darkTheme(),
This works correctly, so that in the Android emulator, when I switch between dark and light mode (within settings), the app automatically changes.
But what I wanted to do was declare the ColorScheme separately (so I can override certain colors etc) and then just use copyWith to declare the brightness in the ThemeData:
class AppTheme {
static const primaryColor = Color.fromARGB(255, 106, 49, 185);
static ColorScheme colorScheme = ColorScheme.fromSeed(
seedColor: primaryColor,
// Customisation goes here
);
static ThemeData lightTheme() {
return ThemeData(
useMaterial3: true,
colorScheme: colorScheme.copyWith(
brightness: Brightness.light,
),
);
}
static ThemeData darkTheme() {
return ThemeData(
useMaterial3: true,
colorScheme: colorScheme.copyWith(
brightness: Brightness.dark,
),
);
}
But this does not work. It just stays in light mode all the time, although no errors are thrown.
Any ideas what I'm doing wrong?

ColorScheme.fromSeed constructor generates a ColorScheme derived from the given seedColor. Copying the generated object obviously does not generate colours again. Something like this would work:
class AppTheme {
static const primaryColor = Color.fromARGB(255, 106, 49, 185);
static ColorScheme fromBrightness({required Brightness brightness}) {
return ColorScheme.fromSeed(
brightness: brightness,
seedColor: primaryColor,
// Customisation goes here
);
}
static ThemeData lightTheme() {
return ThemeData(
useMaterial3: true,
colorScheme: AppTheme.fromBrightness(
brightness: Brightness.light,
),
);
}
static ThemeData darkTheme() {
return ThemeData(
useMaterial3: true,
colorScheme: AppTheme.fromBrightness(
brightness: Brightness.dark,
),
);
}
}

Related

ThemeData primaryColor not changing appBar background color

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),
),
),
);

accentColor is deprecated flutter 2.5

I use accentColor property, i get that this attribute is deprecated. how can i create an specific accent color using the new way?
the code is:
theme: ThemeData(
accentColor: const Color(accentColor),
),
use this
theme: ThemeData(
colorScheme: Theme.of(context).colorScheme.copyWith(secondary: Color(accentColor))
),
for more info check their doc
https://flutter.dev/docs/release/breaking-changes/theme-data-accent-properties
final ThemeData theme = ThemeData();
MaterialApp(
theme: theme.copyWith(
colorScheme: theme.colorScheme.copyWith(secondary: myColor),
),
//...
)
Code before migration:
Color myColor = Theme.of(context).accentColor;
Code after migration:
Color myColor = Theme.of(context).colorScheme.secondary;

Flutter ThemeData Primary color not changing from theme when trying to add a primary color

Im following the BMI Calculator app from the London App Brewery on LinkedIn Learning.
when attempting to set the primaryColor to red, my emulator still shows the Light Blue default AppBar even though i am overriding the Primary Color. here's the code
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.red,
),
home: const InputPage(),
);
}
}
class InputPage extends StatefulWidget {
const InputPage({Key? key}) : super(key: key);
#override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BMI CALCULATOR'),
),
body: const Center(
child: Text('Body Text'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
);
}
}
Use primarySwatch
theme: ThemeData(
primarySwatch: Colors.red,
),
I am also attending same training from LondonAppBrewery. This code fixed the problem.
Widget build(BuildContext context) {
return MaterialApp(
title: "BMI Calculator",
debugShowCheckedModeBanner: false,
theme: ThemeData.dark().copyWith(
appBarTheme:AppBarTheme(
backgroundColor: Color(0xff0a0e21),
),
scaffoldBackgroundColor: Color(0xff0a0e21),
),
home: InputPage(),
);
This issue has been pointed at flutter github page. They say
We will eventually be moving all components away from ThemeData.primaryColor
So you can use
theme: ThemeData(
colorScheme: ColorScheme.light().copyWith(primary: Colors.red),
);
Using the following approach you can have full control over the individual properties in Themedata
class BMICalculator extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.pink,
appBarTheme: AppBarTheme(
backgroundColor: Colors.orangeAccent,
),
),
home: InputPage(),
);
}
}
I'm undergoing the same training program. As Mohtashim mentioned above, I tried to tweak the background app theme code and it worked as expected.
theme: ThemeData(
primarySwatch: Colors.pink,
appBarTheme: AppBarTheme(
backgroundColor: Color(0xFF101427), //use your hex code here
),
)
I also figured out just like you guys answered above. However, in dark design there was a shadowColor missing, so I added it.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
appBarTheme: const AppBarTheme(
backgroundColor: Color(0xFF0a0e21),
elevation: 5.0,
shadowColor: Colors.black87,
),
primaryColor: const Color(0xFF0A0E21),
colorScheme: ColorScheme.fromSwatch().copyWith(
secondary: const Color(0xFF101427),
),
scaffoldBackgroundColor: const Color(0xFF0A0E21),
),
home: const MainPage(),
);
}
}
If you want to add default colors that provide by flutter you can change like this.
theme: ThemeData(
primaryColor: Colors.red,
primarySwatch: Colors.red,
),
If you want to use custom colors, you can use like this
static const Color primaryColor = Color(0xFF623CEA);
static MaterialColor primaryColorSwatch = MaterialColor(
primaryColor.value,
const <int, Color>{
50: Color(0xFF623CEA),
100: Color(0xFF623CEA),
200: Color(0xFF623CEA),
300: Color(0xFF623CEA),
400: Color(0xFF623CEA),
500: Color(0xFF623CEA),
600: Color(0xFF623CEA),
700: Color(0xFF623CEA),
800: Color(0xFF623CEA),
900: Color(0xFF623CEA),
},
);
MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: primaryColor,
primarySwatch: primaryColorSwatch,
),
home: Demo(),
);
theme: ThemeData.dark().copyWith(
colorScheme: ColorScheme.light(
primary: Color(0xFF0A0E21),
),
scaffoldBackgroundColor: Color(0xFF0A0D22),
),
U can Use :
theme: ThemeData(
colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.red,
)
)
Try this code for changing app bar color worked for me,replace the color code as per ur need
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.red,
appBarTheme: AppBarTheme(
backgroundColor: Color(0xFF0A0E21),
),
accentColor: Colors.purple,
),
home: InputPage(),
);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.light()
.copyWith(primary: Colors.red, secondary: Colors.red))),
home: InputPage(),
);
}
This worked for me.
class BMICalculator extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(appBarTheme: AppBarTheme(color: Color(0xff0a0e21))),
home: InputPage(),
);
}
}
So for hex color, we need to use MaterialColor() of primarySwatch. And for Material color, there are two arguments required, hex color and Map data for the shades of the color.
First create a Map variable, color, outside the stateless widget:
Map<int, Color> color =
{
50:Color.fromRGBO(136,14,79, .1),
100:Color.fromRGBO(136,14,79, .2),
200:Color.fromRGBO(136,14,79, .3),
300:Color.fromRGBO(136,14,79, .4),
400:Color.fromRGBO(136,14,79, .5),
500:Color.fromRGBO(136,14,79, .6),
600:Color.fromRGBO(136,14,79, .7),
700:Color.fromRGBO(136,14,79, .8),
800:Color.fromRGBO(136,14,79, .9),
900:Color.fromRGBO(136,14,79, 1),
};
And then:
primarySwatch: MaterialColor(0xFF0A0E21,color),
This will work.
The most complete way to do it would be to set the colorScheme property inside ThemeData().
In the ColorScheme class itself you can either decide to set manually all of the color groups, like so:
theme: ThemeData(
colorScheme: ColorScheme(
brightness: Brightness.light,
primary: Colors.red,
onPrimary: Colors.white,
secondary: Colors.green,
onSecondary: Colors.white,
error: Colors.yellow,
onError: Colors.black,
background: Colors.white,
onBackground: Colors.black,
surface: Colors.grey,
onSurface: Colors.black,
),
),
Or you can decide to use the ColorScheme.fromSwatch() constructor to create a swatch:
theme: ThemeData(
colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.green,
accentColor: Colors.amber,
),
),
I follow the same course. This is the code that helped me. Also thank you guys for answering the questions above. I nearly pulled out my hair. If anyone knows why flutter changes and deprecates syntax so dramatically please explain. It would be nice to know.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
appBarTheme: AppBarTheme(
backgroundColor: Color(0xff0a0e21),
),
primaryColor: Color(0xFF0A0E21),
scaffoldBackgroundColor: Color(0xFF0A0E21),
colorScheme: ColorScheme.fromSwatch().copyWith(
secondary: Colors.purple,
),
),
home: InputPage(),
);
}
}

Flutter Theme Changing dark to light using onpress event

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
});

Get Device Brightness when building ThemeData, outside of Material App with MediaQuery

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(),
);
}
}