Getx: Can't change theme mode from controller

Created on 23 Aug 2020  路  3Comments  路  Source: jonataslaw/getx

Describe the bug
I change the theme from controller but it can update, it just update when i hot reload the app.

To Reproduce
Steps to reproduce the behavior:
Get Material App

GetMaterialApp(
      title: 'Zquare',
      debugShowCheckedModeBanner: false,
      theme: ZquareTheme.light,
      darkTheme: ZquareTheme.dark,
      themeMode: ThemeMode.light,
      initialRoute: '/',
      getPages: [
        GetPage(
          name: '/',
          page: () => HomeScreen(),
          transition: Transition.zoom,
        ),
        GetPage(
          name: '/game',
          page: () => GameScreen(),
          transition: Transition.zoom,
        ),
      ],
   )

Setting Controller

import 'package:Zquare/utils/utils.dart';
import 'package:get/get.dart';

class SettingController extends GetxController {
  static SettingStorage settingStorage = SettingStorage();
  RxBool isDark = settingStorage.isDark.obs;

  void changeMode() {
    isDark.value = !isDark.value;
    if (isDark.value) {
      Get.changeTheme(ZquareTheme.dark);
    } else {
      Get.changeTheme(ZquareTheme.light);
    }
    SettingController.settingStorage.setIsDark(isDark.value);
  }
}

Home Screen

import 'package:Zquare/controller/game_controller.dart';
import 'package:Zquare/controller/setting_controller.dart';
import 'package:Zquare/utils/utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class HomeScreen extends StatelessWidget {
  final GameController gameController = GetInstance().find<GameController>();
  final SettingController settingController =
      GetInstance().find<SettingController>();

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;

    return Scaffold(
      body: Container(
        height: size.height,
        width: size.width,
        color: Get.theme.backgroundColor,
        alignment: Alignment.center,
        child: _playBoard(),
      ),
    );
  }

  Center _playBoard() {
    return Center(
      child: Container(
        height: 515,
        width: 515,
        padding: EdgeInsets.all(15),
        decoration: BoxDecoration(
          color: Get.theme.cardColor,
          borderRadius: BorderRadius.circular(5),
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Column(
              children: [
                Text(
                  "Zquare",
                  style: Get.textTheme.headline1,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      "High score: ",
                      style: Get.textTheme.bodyText1,
                    ),
                    Text(
                      gameController.gameStorage.highscore.toString(),
                      style: Get.textTheme.bodyText1,
                    ),
                  ],
                ),
              ],
            ),
            SizedBox(height: 60),
            Column(
              children: [
                Container(
                  height: 80,
                  width: 250,
                  decoration: BoxDecoration(
                    color: ZquareColors.pinkBold,
                    borderRadius: BorderRadius.circular(5),
                  ),
                  child: InkWell(
                    onTap: () => Get.toNamed('/game'),
                    child: Center(
                      child: Text(
                        "Play",
                        style: Get.textTheme.button,
                      ),
                    ),
                  ),
                ),
                Obx(
                  () => CupertinoSwitch(
                    onChanged: (bool _) => settingController.changeMode(),
                    value: settingController.isDark.value,
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

Expected behavior
When i click the button it change the app theme.

Screenshots
!(https://i.ibb.co/dK1vPBp/Screenshot-from-2020-08-23-13-00-14.png)
!(https://i.ibb.co/NVBKYzg/Screenshot-from-2020-08-23-13-00-11.png)
Flutter Version:
1.21.0-1.0.pre

Get Version:
3.4.6

Most helpful comment

Hi, the theme is being changed, but his background is not, because he is using Get.theme which is immutable. Get has extensions in context for a smaller syntax, which gives a changeable theme, in this case, context.theme, you should use it

 return Scaffold(
      body: Container(
        height: size.height,
        width: size.width,
        color: context.theme.backgroundColor, // Use context extension, Get.theme is Immutable
        alignment: Alignment.center,
        child: _playBoard(),
      ),
    );

Code working:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(GetMaterialApp(
    title: 'Zquare',
    debugShowCheckedModeBanner: false,
    theme: ThemeData.light(),
    darkTheme: ThemeData.dark(),
    themeMode: ThemeMode.light,
    initialRoute: '/',
    getPages: [
      GetPage(
        name: '/',
        page: () => HomeScreen(),
        transition: Transition.zoom,
      ),
    ],
  ));
}

class SettingController extends GetxController {
  RxBool isDark = false.obs;

  void changeMode() {
    isDark.value = !isDark.value;
    print(isDark.value);
    if (isDark.value) {
      Get.changeTheme(ThemeData.dark());
    } else {
      Get.changeTheme(ThemeData.light());
    }
  }
}

class HomeScreen extends StatelessWidget {
  final SettingController settingController =
      GetInstance().put<SettingController>(SettingController());

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;

    return Scaffold(
      body: Container(
        height: size.height,
        width: size.width,
        color: context.theme.backgroundColor,
        alignment: Alignment.center,
        child: _playBoard(),
      ),
    );
  }

  Center _playBoard() {
    return Center(
      child: Container(
        height: 515,
        width: 515,
        padding: EdgeInsets.all(15),
        decoration: BoxDecoration(
          color: Get.theme.cardColor,
          borderRadius: BorderRadius.circular(5),
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Column(
              children: [
                Text(
                  "Zquare",
                  style: Get.textTheme.headline1,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      "High score: ",
                      style: Get.textTheme.bodyText1,
                    ),
                  ],
                ),
              ],
            ),
            SizedBox(height: 60),
            Column(
              children: [
                Container(
                  height: 80,
                  width: 250,
                  decoration: BoxDecoration(
                    color: Colors.pink,
                    borderRadius: BorderRadius.circular(5),
                  ),
                  child: InkWell(
                    onTap: () => Get.toNamed('/game'),
                    child: Center(
                      child: Text(
                        "Play",
                        style: Get.textTheme.button,
                      ),
                    ),
                  ),
                ),
                Obx(
                  () => CupertinoSwitch(
                    onChanged: (bool _) => settingController.changeMode(),
                    value: settingController.isDark.value,
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

As this is not a problem, it is just a question of the documentation that you may not have read, I am closing this.

All 3 comments

Hi, the theme is being changed, but his background is not, because he is using Get.theme which is immutable. Get has extensions in context for a smaller syntax, which gives a changeable theme, in this case, context.theme, you should use it

 return Scaffold(
      body: Container(
        height: size.height,
        width: size.width,
        color: context.theme.backgroundColor, // Use context extension, Get.theme is Immutable
        alignment: Alignment.center,
        child: _playBoard(),
      ),
    );

Code working:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
  runApp(GetMaterialApp(
    title: 'Zquare',
    debugShowCheckedModeBanner: false,
    theme: ThemeData.light(),
    darkTheme: ThemeData.dark(),
    themeMode: ThemeMode.light,
    initialRoute: '/',
    getPages: [
      GetPage(
        name: '/',
        page: () => HomeScreen(),
        transition: Transition.zoom,
      ),
    ],
  ));
}

class SettingController extends GetxController {
  RxBool isDark = false.obs;

  void changeMode() {
    isDark.value = !isDark.value;
    print(isDark.value);
    if (isDark.value) {
      Get.changeTheme(ThemeData.dark());
    } else {
      Get.changeTheme(ThemeData.light());
    }
  }
}

class HomeScreen extends StatelessWidget {
  final SettingController settingController =
      GetInstance().put<SettingController>(SettingController());

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;

    return Scaffold(
      body: Container(
        height: size.height,
        width: size.width,
        color: context.theme.backgroundColor,
        alignment: Alignment.center,
        child: _playBoard(),
      ),
    );
  }

  Center _playBoard() {
    return Center(
      child: Container(
        height: 515,
        width: 515,
        padding: EdgeInsets.all(15),
        decoration: BoxDecoration(
          color: Get.theme.cardColor,
          borderRadius: BorderRadius.circular(5),
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Column(
              children: [
                Text(
                  "Zquare",
                  style: Get.textTheme.headline1,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      "High score: ",
                      style: Get.textTheme.bodyText1,
                    ),
                  ],
                ),
              ],
            ),
            SizedBox(height: 60),
            Column(
              children: [
                Container(
                  height: 80,
                  width: 250,
                  decoration: BoxDecoration(
                    color: Colors.pink,
                    borderRadius: BorderRadius.circular(5),
                  ),
                  child: InkWell(
                    onTap: () => Get.toNamed('/game'),
                    child: Center(
                      child: Text(
                        "Play",
                        style: Get.textTheme.button,
                      ),
                    ),
                  ),
                ),
                Obx(
                  () => CupertinoSwitch(
                    onChanged: (bool _) => settingController.changeMode(),
                    value: settingController.isDark.value,
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

As this is not a problem, it is just a question of the documentation that you may not have read, I am closing this.

Thank you: +1: I realized it too and used MediaQuery.of (context) .theme to change the theme but the context extention is good, I will use this

@jonataslaw When I use context.theme.backgroundColor, to change textTheme but widget rebuild many times.
Screenshot 2020-09-21 at 10 05 32

Was this page helpful?
0 / 5 - 0 ratings