How to change the theme in flutter using darkTheme: - flutter

To manage themes in my MaterialApp(), i use :
MaterialApp(
...
theme: isDarkTheme ? darkTheme() : lightTheme(),
)
darkTheme() and lightTheme() are just simple function that return ThemeData()
So, I use an inherited Widget to change the variable isDarkTheme and then i use the setState((){}) method and all the application is rebuild
But, I saw on the Flutter documentation that we can use darkTheme:.
I'm trying to do this :
MaterialApp(
...
theme: lightTheme(),
darkTheme: darkTheme()
)
And we can change the theme during the course of the application

darkTheme property is used to define a Theme to be used when the device enters Dark mode, So you can't force your app to use darkTheme property because it depends on the value of MediaQueryData.platformBrightness which is a read-only field.
You can rather define several Themes to be used as a value for Theme property, and switching between them during the app course by using a StreamBuilder wrapped around your MaterialApp,which won't cause the app to stop and rebuild like the case when you were using setState to change theme (you'll need rxdart package to apply the below solution):
//BehaviorSubject stream any changes immediately without explicit call
var themeSubject = BehaviorSubject<ThemeData>();
//This way the app won't rebuild when the user selects the same theme
Stream<ThemeData> getTheme() => themeSubject.stream.distinct();
void setTheme (MaterialColor color){
pointsSubject.sink.add(ThemeData(primarySwatch: color) ;
}
return StreamBuilder<ThemeData>(
stream: getTheme(),
initialData: ThemeData(
primarySwatch: Colors.blue,
primaryTextTheme: TextTheme(
title: TextStyle(color: Colors.white),
),
builder: (context, themeSnapshot){
return MaterialApp(theme: themeSnapshot.data);
}
):
Then use your InheritedWidget to access setTheme and change it as you please.

Related

Flutter 3 Web App: Custom Colors or Theme

I am (very) new to Flutter, so please go easy on me. 😊 I'm using Flutter 3 and Dart 2.17.
I am making a web app and am trying to set up the color scheme for my app. In CSS, I'd normally do something like this to define a set of colors for light and dark mode:
:root {
--alpha: #FFF;
--bravo: #F5F5F6;
}
#media (prefers-color-scheme: dark) {
--alpha: #222630;
--bravo: #171920;
}
I've read about Flutter's ThemeData, and as I understand it, it's a big list of styles so that if I were making an Android app, I'd have some sensible defaults for various pieces of the mobile UI. But since I am making a web app that has a fully custom UI, it feels like a lot of extra stuff I don't want.
What is a good way to define a bunch of color names and have them automatically switch their values when I switch between light and dark mode? Should I still use ThemeData? Or is there a simpler way when my UI is custom?
I'm hoping for something like this (this probably isn't valid Dart; I'm still learning):
//My view
Container(color: MyColors.alpha)
...and the values are read somewhere like this:
//Some other class
class MyColors {
final alpha = darkMode ? const Color(0XFF222630) : const Color(0xFFFFFFFF);
final bravo = darkMode ? const Color(0xFF171920) : const Color(0xFFF5F5F6);
}
Has anyone done something like this?
I'd suggest you use an #observable ThemeMode themeMode variable (read about the mobx state management here https://pub.dev/packages/mobx) to change the state of your whole widget tree starting from MaterialApp when the user changes the app theme, for example
themeMode: themeMode != null
? _controller.themeMode!
: WidgetsBinding.instance.window.platformBrightness == Brightness.light
? ThemeMode.light
: ThemeMode.dark,
and still use ThemeData to set which colors you want your components to use, like this
darkTheme: ThemeData(
scaffoldBackgroundColor: MyColors.alphaDark,
backgroundColor: MyColors.alphaDark,
cardColor: MyColors.alphaDark,)
theme: ThemeData(
scaffoldBackgroundColor: MyColors.bravoLight,
backgroundColor: MyColors.bravoLight,
cardColor: MyColors.bravoLight,)
class MyColors {
final alphaDark = const Color(0XFF222630);
final bravoLight = const Color(0xFFF5F5F6);
}
Container(color: Theme.of(context).cardColor)
And you can always create a custom ThemeData so you can call your components whatever you want

ThemeData primaryColor is not work in flutter

I am using flutter 2.5.2 and primaryColor is not working for me, I want to use hexcode of color, what am I doing wrong here,
import 'package:flutter/material.dart';
import 'input_page.dart';
void main() => runApp(BMICalculator());
class BMICalculator extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
primaryColor: Color(0xFFCF3D10),
),
home: InputPage(),
);
}
}
This is caused by a transition(WIP) to ColorSchemes for theming. You can read about it here:
https://github.com/flutter/flutter/issues/89839#issuecomment-919437144
IMO ColorSchemes are not yet complete, you can use primarySwatch property of ThemeData to do what you're trying to achive.
Thanks to #mayank for the issue link, from reading all the comments from this official issue link I noticed
They did this intentionally as part of Theme System cleanup and to make everything more consistent and based off the ColorScheme colors.
Flutter team has mentioned clearly that they will eventually be moving all components away from ThemeData.primaryColor
and this can be fixed by providing a color scheme with the same primary color that you desire:
theme: ThemeData(
primaryColor: ColorsX.primary,
colorScheme: ColorScheme.light().copyWith(primary: ColorsX.primary),
);
for me this was the solution :
theme: ThemeData.dark().copyWith(
colorScheme: ColorScheme.light(primary: Color(0xffcf3d10)),
Now the things works as intdended for me.

Changing the font family in Flutter when using ThemeData.dark() or ThemeData.light()

I'm trying to set the font of my MaterialApp. Since I'm using the dark theme, I'd like to just use copyWith and then change the fontFamily. However, copyWith doesn't have an option to change the fontFamily.
MaterialApp(
theme: ThemeData.dark().copyWith(
fontFamily: 'MyFontFamily',
),
The named parameter 'fontFamily' isn't defined.
How do I keep the dark theme but also change the font family? (Same problem with ThemeData.light().)
I found a solution and am posting below.
If you look at the source code for ThemeData.light() and ThemeData.dark(), you can see that all it does is set the brightness value:
/// A default light blue theme.
///
/// This theme does not contain text geometry. Instead, it is expected that
/// this theme is localized using text geometry using [ThemeData.localize].
factory ThemeData.light() => ThemeData(brightness: Brightness.light);
/// A default dark theme with a teal secondary [ColorScheme] color.
///
/// This theme does not contain text geometry. Instead, it is expected that
/// this theme is localized using text geometry using [ThemeData.localize].
factory ThemeData.dark() => ThemeData(brightness: Brightness.dark);
That means to solve your problem you don't need to bother with ThemeData.light() or ThemeData.dark(). Just create a new ThemeData and set the brightness yourself in addition to the fontFamily:
MaterialApp(
theme: ThemeData(
brightness: Brightness.dark,
fontFamily: 'MyFontFamily',
),
Since, all you're doing is setting the brightness, I think the easier way would be to just use DefaultTextStyle.
DefaultTextStyle(
style: TextStyle(
fontFamily: 'YourFontFamily',
),
child: YourWidget(),
)

How to add more than 1 theme parameter to Material App Flutter?

I have a normal MaterialApp Widget in my flutter app. And I want to add more than 1 theme parameter to it...
Like so:-
theme: ThemeData(fontFamily: kGetAppFont(context, languageCode)),
theme: ThemeProvider.themeOf(themeContext).data,
If your user can change the app theme, you can store selected theme in Settings (you can use this plugin). In app you should set in by read value from Settings and detect theme class by its value:
Main class fragment:
theme: _prefs.currentTheme();
Prefs class fragment:
ThemeData currentTheme() {
return _instance.getString('theme') == 'dark' ? AppTheme.dark : AppTheme.light;
}

Flutter: programmatically cause darkTheme to be used

In Flutter, you can set a dark theme to be used, which will be used if certain contexts (e.g. Dark Mode is set on Android Q). Is there a recommended way to allow that to be overridden programmatically; e.g, in response to a user preference?
I guess this could be done at the very top level of the app:
MaterialApp(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: fromSomeState,
)
However, I'd also like to be able switch on whether or not the app is in dark mode programmatically at various points in the app (e.g. for image selection):
MediaQuery.of(context).platformBrightness == Brightness.dark;
I could try and update the MediaQueryData to override platformBrightness as well, but that can only be done inside MaterialApp, which seems awkward.
Is there a better pattern for doing this kind of thing?
You can check out dynamic_theme
How to use
Just add Dynamic Theme as the parent of your MaterialApp
DynamicTheme(
defaultBrightness: Brightness.light,
data: (brightness) => new ThemeData(
primarySwatch: Colors.indigo,
brightness: brightness,
),
themedWidgetBuilder: (context, theme) {
return new MaterialApp(
.......
);
}
)
Get the currentBrightness using
DynamicTheme.of(context).brightness;
And Set it using
DynamicTheme.of(context).setBrightness(Theme.of(context).brightness == Brightness.dark? Brightness.light: Brightness.dark);
You can read more about it or create your own, check this medium Post
Edited
You can check the current OS theme using
MediaQuery.of(context).platformBrightness;
And set the theme accordingly.