4

So I'm trying here to get the current theme, if it's light or dark. So I can change widget color accordingly.. However, it doesn't work, I used if statment to know when it's dark mode.. but it's always False .. This is the code.. btw it switch between dark & light theme.. but when i try to get current theme.. even if the theme changed to dark.. the if statments always show false...

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {

    bool darkModeOn = MediaQuery.of(context).platformBrightness == Brightness.dark;
    Color containerColor;
    if (darkModeOn == true) {
      containerColor = Colors.blueGrey;
      print("----------------");
      print("dark mode ON");
      print("----------------");
    } else {
      containerColor = Colors.deepPurple;
      print("LIGHT mode ON");
    }

    return Scaffold(
      floatingActionButton: FloatingActionButton.extended(
          onPressed: () {
            //----switch theme---
            currentTheme.switchTheme();
          },
          label: Text(
            "Switch theme",
            style: TextStyle(
            ),
          ),
        icon: Icon(Icons.color_lens_outlined),
      ),
      appBar: AppBar(
        title: Text("DarkXLight"),
      ),
      body: Container(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Expanded(child: Container(
              color: containerColor,
            ),
            ),
            Expanded(child: Container(
              color: Colors.amber,
            ),
            ),
          ],
        ),
      ),
    );
  }
}
Silent Fairy
  • 53
  • 1
  • 1
  • 8

4 Answers4

6

You can't switch themes like that. You will need to handle the logic in the MaterialApp otherwise

MediaQuery.of(context).platformBrightness == Brightness.dark;

will always return true/false based on what was provided to the MaterialApp.themeMode.

Here's a sample code to get started. I used ValueListenableBuilder but you can also use provider.

enter image description here


Full code:

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  final ValueNotifier<ThemeMode> _notifier = ValueNotifier(ThemeMode.light);

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<ThemeMode>(
      valueListenable: _notifier,
      builder: (_, mode, __) {
        return MaterialApp(
          theme: ThemeData.light(),
          darkTheme: ThemeData.dark(),
          themeMode: mode, // Decides which theme to show, light or dark.
          home: Scaffold(
            body: Center(
              child: ElevatedButton(
                onPressed: () => _notifier.value = mode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light,
                child: Text('Toggle Theme'),
              ),
            ),
          ),
        );
      },
    );
  }
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
  • thank you, I'm able to switch themes.. now I'm trying to get the current theme ( light or dark ), from another class.. so I can change the container color when the theme change – Silent Fairy Jun 02 '21 at 04:09
  • @SilentFairy "I'm able to switch themes" -- Can you tell me what your `bool darkModeOn` returns on changing themes? Your question title needs to be changed otherwise it would become a duplicate of [this question](https://stackoverflow.com/q/56304215/6618622) – CopsOnRoad Jun 02 '21 at 06:44
  • 1
    my main question is how to get current theme from anywhere in app. `bool darkModeOn` returns false. Always! – Silent Fairy Jun 02 '21 at 06:48
  • @SilentFairy That means you were not able to change the theme, which is why your question should be "How to change theme". – CopsOnRoad Jun 02 '21 at 06:49
  • Thank you, I changed it.. but now I'm confused.. I know I can change the theme from MaterialApp the main page. (Which works because scaffold & button color changed ) but when I try to get current theme from any other class.. it doesn't work ^^ – Silent Fairy Jun 02 '21 at 06:52
  • @SilentFairy Can you post a minimal code of your issue, I can definitely help you better. – CopsOnRoad Jun 02 '21 at 06:52
  • you were right! the switch theme functions wasn't working as expected thats why `bool darkModeOn` return always false. So ! I searched on YT the right way to switch themes, then it works! I added full code here – Silent Fairy Jun 02 '21 at 17:43
1

So, I was able to solve my problem.. I will put the code so if someone faced the same issue.. I simply, changed the way I used to switch themes. It was wrong.. However, here I'm posting the Correct way & this way solved the problem..

MAIN PAGE

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:practice_darkmode/theme_provider.dart';
import 'package:provider/provider.dart';

import 'MyHomePage.dart';

Future<void> main() async {

  runApp(MyApp());
}

class MyApp extends StatefulWidget {

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => ThemeProvider(),
      builder: (context, _) {
        final themeProvider = Provider.of<ThemeProvider>(context);
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          theme: MyThemes.lightTheme,
          darkTheme: MyThemes.darkTheme,
          themeMode: themeProvider.themeMode,
          home: MyHomePage(),
        );
      },
    );

  }
}

Theme Provider class

import 'package:flutter/material.dart';

//---This to switch theme from Switch button----
class ThemeProvider extends ChangeNotifier {

  //-----Store the theme of our app--
  ThemeMode themeMode = ThemeMode.dark;

  //----If theme mode is equal to dark then we return True----
  //-----isDarkMode--is the field we will use in our switch---
  bool get isDarkMode => themeMode == ThemeMode.dark;

  //---implement ToggleTheme function----
  void toggleTheme(bool isOn) {

  themeMode = isOn ? ThemeMode.dark : ThemeMode.light;

  //---notify material app to update UI----
  notifyListeners();
}

}

//---------------Themes settings here-----------
class MyThemes {

  //-------------DARK THEME SETTINGS----
  static final darkTheme = ThemeData(
    scaffoldBackgroundColor: Colors.black45,
    // colorScheme:  ColorScheme.dark(),

  );


  //-------------light THEME SETTINGS----
  static final lightTheme = ThemeData(
    scaffoldBackgroundColor: Colors.white,
    //colorScheme:  ColorScheme.light(),
  );

}

Change Theme button widget class ( this is to create a switch button)

import 'package:flutter/material.dart';
import 'package:practice_darkmode/theme_provider.dart';
import 'package:provider/provider.dart';


class ChangeThemeButtonWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //----First we want to get the theme provider----
    final themeProvider = Provider.of<ThemeProvider>(context);

    return Switch.adaptive(
      //---isDarkMode to return if its dark or not--true or false--
      value: themeProvider.isDarkMode,
      onChanged: (value) {
        final provider = Provider.of<ThemeProvider>(context, listen: false);
        provider.toggleTheme(value);
      },
      activeColor: themeProvider.isDarkMode ? Colors.purple : Colors.green,

    );

  }
}

Home Page

import 'package:flutter/material.dart';
import 'package:practice_darkmode/theme_provider.dart';
import 'package:provider/provider.dart';

import 'ChangeThemeButtonWidget.dart';


class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {

    dynamic text;
    dynamic textColor;
    dynamic appBarColor;
    dynamic btnColor;
    dynamic appBarTextColor;

    if (Provider.of<ThemeProvider>(context).themeMode == ThemeMode.dark) {

      text = "IT'S DARK ";
      textColor = Colors.cyanAccent;
      appBarColor = Colors.black;
      btnColor = Colors.deepPurple;
      appBarTextColor = Colors.cyanAccent;

    } else if (Provider.of<ThemeProvider>(context).themeMode == ThemeMode.light) {

      text = "IT'S LIGHT ";
      textColor = Colors.red;
      appBarColor = Colors.red;
      btnColor = Colors.red;
      appBarTextColor = Colors.white;

    }

    return Scaffold(
      floatingActionButton: FloatingActionButton.extended(
          onPressed: () {
          },
          label: Text(
            "Switch theme",
            style: TextStyle(
            ),
          ),
        icon: Icon(Icons.color_lens_outlined),
        backgroundColor: btnColor,
      ),
      appBar: AppBar(
        title: Text("DarkXLight", style: TextStyle(color: appBarTextColor),),
        backgroundColor: appBarColor,
        actions: [
          ChangeThemeButtonWidget(),
        ],
      ),
      body: Container(
        child: Center(
          child: Text(
            "$text!",
            style: (
            TextStyle(
              fontSize: 27,
              color: textColor,
            )
            ),
          ),
        ),
      ),
    );
  }
}
Silent Fairy
  • 53
  • 1
  • 1
  • 8
1

Below code will to change theme via Icon Button in appBar. Steps:

  1. Create a stateful widget.
  2. Add the following variables:
bool _iconBool = false;
IconData _iconLight = Icons.wb_sunny;
IconData _iconDark = Icons.nights_stay;
  1. Create actions -> IconButton in the appBar as below:
appBar: AppBar(
          title: Text("Simple Colregs"),
          backgroundColor: Color(0xFF5B4B49).withOpacity(0.8),
          actions: [
            IconButton(icon: Icon(_iconBool ? _iconDark : _iconLight),
              },)
          ],
        ), //AppBar
  1. Add Below methods with Light and Dark themes and any custom preference is required:
// light Theme
ThemeData lightThemeData(BuildContext context) {
  return ThemeData.light().copyWith(
      primaryColor: Color(0xFF5B4B49),
      colorScheme: ColorScheme.fromSwatch().copyWith(secondary: Color(0xFF24A751)));
}

// dark Theme
ThemeData darkThemeData(BuildContext context) {
  return ThemeData.dark().copyWith(
      primaryColor: Color(0xFFFF1D00),
      colorScheme: ColorScheme.fromSwatch().copyWith(secondary: Color(0xFF24A751)));
}

Read more about ThemeData Class here.

  1. Under IconButton, create a functionality for the button as below which will toggle the theme:
              onPressed: () {
                setState(() {
                  _iconBool = !_iconBool;

                });
  1. Finally add under Material App:
theme: _iconBool ? lightThemeData(context) : darkThemeData(context),

That's all, good to go. Hope it helps.

Angad Cheema
  • 187
  • 1
  • 5
  • are you sure this works? I've done exactly this and its not switching it. The variable is switching correctly but its as if the app isn't fully rebuilding. – Lee Casey Oct 20 '22 at 11:00
0

you can use it in initState

bool darkModeOn = brightness == Brightness.dark;

or

var brightness = MediaQuery.of(context).platformBrightness;
bool darkModeOn = brightness == Brightness.dark;
S A Saharukh
  • 378
  • 1
  • 4
  • 11