Declaring one or more custom Themes - flutter

I'm trying to create a custom theme inside a flutter project.
I've created a separate file (mycolors.dart) where i defined some colors (const myPrimaryColor = const Color(0xFFFF3900); etc etc)
Then, in main.dart i'm referring to these colors and a custom font but inside the Widget build...
How can I isolate the theme data (colors and font/text styles), let's say "separately", and to refer to it inside the class?
Can I also define 2 different themes and use them later in the project?
Many thanks.
import 'package:flutter/material.dart';
import 'package:my_repository/mycolors.dart';
import 'package:flutter_statusbarcolor/flutter_statusbarcolor.dart';
void main() {
runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
FlutterStatusbarcolor.setStatusBarColor(myPrimaryColor);
return MaterialApp(
theme: ThemeData(
fontFamily: 'Raleway',
primaryColor: myPrimaryColor,
accentColor: myAccentColor,
scaffoldBackgroundColor: myBackgroundColor,
cardColor: mySurfaceColor,
textSelectionColor: myPrimaryColor,
errorColor: myErrorColor,
),
home: Scaffold( ....

You can define your themes in a class and then call ThemeName().theme.
here is how I have a theme file in my app:
class MuskTheme {
...
ThemeData get theme => ThemeData(
brightness: Brightness.dark,
primarySwatch: musk,
accentColor: accentColor,
fontFamily: fontFamily,
backgroundColor: musk,
canvasColor:canvasColor,
textTheme: _textTheme,
iconTheme: _iconTheme,
cardColor: Color(0xff313A49),
appBarTheme: AppBarTheme(color: canvasColor,elevation: 0),
dialogBackgroundColor: canvasColor,
snackBarTheme: SnackBarThemeData(
backgroundColor: musk[800],
actionTextColor: accentColor,
),
);
...
}
for changing your theme during runtime you need to rebuild the MaterialApp widget by implementing a stateful widget that is higher than MaterialApp and can rebuild it upon request.
example implementation:
class ThemeChanger extends StatefulWidget {
final ThemeData initialTheme;
final MaterialApp Function(BuildContext context, ThemeData theme)
materialAppBuilder;
const ThemeChanger({Key key, this.initialTheme, this.materialAppBuilder})
: super(key: key);
#override
_ThemeChangerState createState() => _ThemeChangerState();
static void setTheme(BuildContext context, ThemeData theme) {
var state = context.ancestorStateOfType(TypeMatcher<_ThemeChangerState>())
as _ThemeChangerState;
state.setState(() {
state.theme = theme;
});
}
}
class _ThemeChangerState extends State<ThemeChanger> {
ThemeData theme;
#override
void initState() {
super.initState();
theme = widget.initialTheme;
}
#override
Widget build(BuildContext context) {
return widget.materialAppBuilder(context, theme);
}
}
then you'll need to build your MaterialApp with it:
class ThemeChangingApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ThemeChanger(
initialTheme: ThemeData(
primarySwatch: Colors.blue,
),
materialAppBuilder: (context, theme) {
return MaterialApp(
theme: theme,
home: StartingPage(),
);
},
);
}
}
and in your app you can change the theme like this:
class StartingPage extends StatefulWidget {
#override
_StartingPageState createState() => _StartingPageState();
}
class _StartingPageState extends State<StartingPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: Center(
child: FlatButton(
child: Text('change theme to orange'),
onPressed: () {
ThemeChanger.setTheme(
context,
ThemeData(
primarySwatch: Colors.orange,
));
},
),
),
),
);
}
}
this package does a similar thing.

You can build a scaffold with a different theme just by warpping it with a Theme widget:
class StartingPage extends StatefulWidget {
#override
_StartingPageState createState() => _StartingPageState();
}
class _StartingPageState extends State<StartingPage> {
#override
Widget build(BuildContext context) {
return Theme(
data: ThemeData.dark(),
child: Scaffold(
appBar: AppBar(),
body: Container(
child: Center(
child: Text('test'),
),
),
),
);
}
}

final ThemeData customTheme = _buildcustomTheme();
ThemeData _buildcustomTheme() {
return customThemeFoundation;
}
ThemeData customThemeFoundation =ThemeData(
brightness: Brightness.dark,
primaryColor: Color.fromRGBO(40, 204, 86, 1),
accentColor: Colors.cyan[600],
fontFamily: 'Georgia',
textTheme: TextTheme(
headline1: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold),
headline6: TextStyle(fontSize: 36.0, fontStyle: FontStyle.italic),
bodyText2: TextStyle(fontSize: 14.0, fontFamily: 'Hind'),
),
and in main.dart just call it by
import 'theme.dart';
and just relpace theme:{.....} with theme: customTheme,

Related

How to change theme to dark on click on IconButton?

In my application, in the appBar, there is a button that should change the theme to dark. I need to create functionality Provider. How can this be implemented? I just need to change the Scaffold color to black and the text color to white.
My main.dart:
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
textTheme: const TextTheme(
headline1: TextStyle(fontSize: 50.0, fontWeight: FontWeight.bold),
headline5: TextStyle(fontSize: 36.0, fontStyle: FontStyle.italic),
subtitle2: TextStyle(fontSize: 10.0, color: Colors.black),
bodyText1: TextStyle(fontSize: 14.0, color: Colors.black),
),
),
home: const HomeScreen(),
);
}
My switch button:
appBar: AppBar(
title: const Text('Flutter theme config'),
centerTitle: true,
actions: [
IconButton(
onPressed: () {
},
icon: const Icon(Icons.dark_mode),
)
],
),
Theme provider:
class ThemeProvider extends ChangeNotifier {
}
You can try something like this :
First we provide our Provider globally for the whole application, and then in the attribute theme: we listen for the change.
** main **
void main() async {
runApp(
MultiProvider( // create the provider
providers: [
ChangeNotifierProvider(
create: (_) => ThemeProvider(),
)
],
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Material App',
initialRoute: HomeScreen.routerName,
routes: {
},
theme: Provider.of<ThemeProvider>(context).currentTheme, // listen to the current theme
);
}
}
In the provider we will only have two functions, one to switch to LightMode and the other to DarkMode, then we add it to the currentTheme variable which is the one that listens in the main
** ThemeProvider **
class ThemeProvider extends ChangeNotifier {
ThemeData? currentTheme;
setLightMode() {
currentTheme = ThemeData(
brightness: Brightness.light, // LightMode
scaffoldBackgroundColor: Colors.red,
[...] // more attributes
);
notifyListeners();
}
setDarkmode() {
currentTheme = ThemeData(
brightness: Brightness.dark, // DarkMode
scaffoldBackgroundColor: Colors.green,
[...] // more attributes
);
notifyListeners();
}
}
Finally we create a StatefulWidget to change the isDarkMode variable to call the provider
** Button Home **
class _HomeScreenState extends State<SettingsScreen> {
bool isDarkmode = false; // new variable
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Settings"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: IconButton(
onPressed: () {
final themeProvider =
Provider.of<ThemeProvider>(context, listen: false); // get the provider, listen false is necessary cause is in a function
setState(() {
isDarkmode = !isDarkmode;
}); // change the variable
isDarkmode // call the functions
? themeProvider.setDarkmode()
: themeProvider.setLightMode();
},
icon: const Icon(Icons.dark_mode),
),
),
);
}
}

FLUTTER - How to properly upgrade this code to work with RiverPod 1.0+?

I added the libraries to pubspec.yaml. In the current project I am not using hooks, but used the package because I want to use this to build a skeleton starter project.
pubspec.yaml:
flutter_hooks: ^0.18.2+1
hooks_riverpod: ^1.0.3
Then I modified the code to the latest RiverPod syntax. This involved changing things to Consumer widgets and using the ref parameter. The app now runs but just is not switching from dark mode to light mode and vice versa!
main.dart:
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class AppThemeState extends StateNotifier<bool> {
AppThemeState(): super(false);
void setLightTheme() => state = false;
void setDarkTheme() => state = true;
}
// Theme
final appThemeStateNotifier = StateNotifierProvider((ref) => AppThemeState());
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends HookConsumerWidget {
#override
Widget build(BuildContext context, WidgetRef ref) {
final darkModeEnabled = ref.watch(appThemeStateNotifier);
return MaterialApp(
title: 'Flutter Demo',
theme: AppTheme.lightTheme,
darkTheme: AppTheme.darkTheme,
themeMode: darkModeEnabled != null ? ThemeMode.dark : ThemeMode.light,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 2.0,
title: Text("Flutter Theme Riverpod Demo"),
),
body: Column(
children: [
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Light Mode"),
DarkModeSwitch(),
Text("Dark Mode"),
],
),
),
],
),
);
}
}
class DarkModeSwitch extends ConsumerWidget {
#override
Widget build(BuildContext context, WidgetRef ref) {
final darkModeEnabled = ref.read(appThemeStateNotifier) == true;
return //Text('$darkModeEnabled');
Switch(
value: darkModeEnabled,
onChanged: (enabled) {
if (enabled) {
ref.read(appThemeStateNotifier.notifier).setDarkTheme();
} else {
ref.read(appThemeStateNotifier.notifier).setLightTheme();
}
},
);
}
}
class AppTheme {
// Private Constructor
AppTheme._();
static final lightTheme = ThemeData(
scaffoldBackgroundColor: Colors.white,
appBarTheme: AppBarTheme(
color: Colors.teal,
iconTheme: IconThemeData(
color: Colors.white,
),
),
textTheme: TextTheme(
bodyText2: TextStyle(
color: Colors.black,
),
),
);
static final darkTheme = ThemeData(
scaffoldBackgroundColor: Colors.black,
appBarTheme: AppBarTheme(
color: Colors.black,
iconTheme: IconThemeData(
color: Colors.white,
),
),
textTheme: TextTheme(
bodyText2: TextStyle(
color: Colors.white,
),
),
);
}
The problem is at this line:
themeMode: darkModeEnabled != null ? ThemeMode.dark : ThemeMode.light,
darkModeEnabled can't be null.
Use this instead:
themeMode: darkModeEnabled ? ThemeMode.dark : ThemeMode.light,

Flutter How to force Dark mode on specific screens

I'm building a news app using flutter, the app has 2 theme modes already dark and light debends on phone settings and works really great, but I need on some screens on my app to be dark whatever such as videos section or video page ...etc
I googled this and all the results about the normal theming which I did already.
I don't think there's any code I can put here to help, but if there please let me know!
You can override the current theme at any time simply by placing the desired widget in a Theme class.
I don't know if you are using Scaffold or not, but let's say you are then all you would need to do is:
// declare theme data if you don't have it already
final ThemeData specialThemeData = ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.yellow[700],
// and so on...
);
#override
Widget build(BuildContext context) {
// this the point of interest, return a Theme with desired Theme Data
return Theme(
data: specialThemeData,
child: Scaffold(
//...
It doesn't have to be Scaffold, it will work on any widegt.
Here is a fully functional example you can try out yourself:
import 'package:flutter/material.dart';
final ThemeData specialThemeData = ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.yellow[700],
accentColor: Colors.orange[500],
textTheme: TextTheme(
headline1: TextStyle(fontSize: 48.0, fontWeight: FontWeight.bold),
headline6: TextStyle(fontSize: 24.0, fontStyle: FontStyle.italic),
bodyText2: TextStyle(fontSize: 18.0),
),
);
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Home Page default theme'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void _goToSpecialPage() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MySpecialPage()
)
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Your homepage, using default theme.',),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _goToSpecialPage,
tooltip: 'Go to special page',
child: Icon(Icons.navigate_next),
),
);
}
}
class MySpecialPage extends StatefulWidget {
MySpecialPage({Key key}) : super(key: key);
#override
_MySpecialPageState createState() => _MySpecialPageState();
}
class _MySpecialPageState extends State<MySpecialPage> {
void _backToHomePage(){
Navigator.pop(context);
}
#override
Widget build(BuildContext context) {
// this the point of interest, return a Theme with desired Theme Data
return Theme(
data: specialThemeData,
child: Scaffold(
appBar: AppBar(
title: Text('Special theme page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Your special page that uses a different theme.',),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _backToHomePage,
tooltip: 'Go back to home page',
child: Icon(Icons.navigate_before),
),
),
);
}
}

Unable to override ThemeData

I want to have a different background color in MenuPage. I'm trying to override the themeData - I've followed the themeData tutorial from official flutter page but unable to get the result. do you guys have any suggestion?
void main() => runApp(MyApp());
final ThemeData _themeData = new ThemeData( // app theme
scaffoldBackgroundColor: darkNavy,
canvasColor: lightNavy,
accentColor: lightNavy,
primarySwatch: Colors.grey,
appBarTheme: AppBarTheme(
color: darkNavy,
brightness: Brightness.dark,
elevation: 10,
iconTheme: IconThemeData(
color: lightGrey,
),
textTheme: TextTheme(
headline6: GoogleFonts.crimsonPro(
color: darkGrey,
fontSize: 20,
fontWeight: FontWeight.w400))),
);
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: _themeData,
home: HomeScreen(),
);
}
}
class MenuDashBoard extends StatefulWidget {
#override
_MenuDashBoardState createState() => _MenuDashBoardState();
}
class _MenuDashBoardState extends State<MenuDashBoard> {
#override
Widget build(BuildContext context) {
return Theme(
data: ThemeData(
canvasColor: lightNavy,
scaffoldBackgroundColor: lightNavy
),
child: Scaffold(
body: Container(
padding: EdgeInsets.only(top: 30, bottom: 30, left: 20),
child: Column(
My main homeScreen has a dark navy background i want to have a light navy in my Menu page.
You can use the attribute 'scaffoldBackgroundColor' in theme data, setting to the color you want With this, if you are using the scaffold widget, your background app will have the color you want. See:
MaterialApp(
title: 'App',
theme: ThemeData(
scaffoldBackgroundColor: Colors.blue,
),
home: YourScreen()
),

CupertinoDynamicColor not working for text style within a theme in Flutter

Currently I've got a problem with the dark mode for iOS in Flutter. I'm using a CupertinoApp with a CupertinoTheme.
With CupertinoDynamicColor.withBrightness() it's possible to define colors for dark and light theme. This is working for example for the navigation bar (barBackgroundColor), but not for the textTheme.
Someone already ask a similar question in the flutter repository but I don't know how to do this with a theme. Maybe you can help me there.
Example code:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return CupertinoApp(
title: 'Flutter Demo',
theme: CupertinoThemeData(
barBackgroundColor: const CupertinoDynamicColor.withBrightness(
color: Colors.blue,
darkColor: Colors.red,
),
textTheme: CupertinoTextThemeData(
textStyle: TextStyle(
color: const CupertinoDynamicColor.withBrightness(
color: Colors.blue,
darkColor: Colors.red,
),
),
),
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(middle: Text('Test')),
child: Text('Test Text'),
);
}
}