0

I'm using provider for managing the dark and light mode along with shared preferences to save it. I have successfully managed to save the selected theme but I'm unable to change the icons and the text in ListTile of my drawer according to the selection.

Theme.dart:

class ThemeProvider extends ChangeNotifier {
  late ThemeData _selectedTheme;
  late Typography defaultTypography;
  late SharedPreferences prefs;

  ThemeData dark = ThemeData.dark().copyWith();

  ThemeData light = ThemeData.light().copyWith();

  ThemeProvider(bool darkThemeOn) {
    _selectedTheme = darkThemeOn ? dark : light;
  }

  Future<void> swapTheme() async {
    prefs = await SharedPreferences.getInstance();

    if (_selectedTheme == dark) {
      _selectedTheme = light;
      await prefs.setBool("darkTheme", false);
    } else {
      _selectedTheme = dark;
      await prefs.setBool("darkTheme", true);
    }

    notifyListeners();
  }

  ThemeData getTheme() => _selectedTheme;
}

How I want the icons to change but this code isnt working.

ListTile(
                  onTap: () {
                    Provider.of<ThemeProvider>(context, listen: false)
                        .swapTheme();
                  },
                  leading: Icon(MyApp.themeNotifier.value == ThemeMode.light
                      ? Icons.dark_mode
                      : Icons.light_mode),
                  title: MyApp.themeNotifier.value == ThemeMode.light
                      ? Text(
                          "Dark Mode",
                          style: TextStyle(
                            fontFamily: "San Francisco",
                          ),
                        )
                      : Text(
                          "Light Mode",
                          style: TextStyle(
                            fontFamily: "San Francisco",
                          ),
                        ),
                ),

The ? and : logic I want here to be used on the selected theme like if its dark mode then the icon should be sun and it should say light mode and alternate of that for light mode.

Main file code:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  SharedPreferences.getInstance().then((prefs) {
    var isDarkTheme = prefs.getBool("darkTheme") ?? false;
    SystemChrome.setPreferredOrientations(
        [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
    // await MobileAds.instance.initialize();
    return runApp(
      ChangeNotifierProvider<ThemeProvider>(
        child: MyApp(),
        create: (BuildContext context) {
          return ThemeProvider(isDarkTheme);
        },
      ),
    );
  });
}

class MyApp extends StatelessWidget {
  static final ValueNotifier<ThemeMode> themeNotifier =
      ValueNotifier(ThemeMode.light);
  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<ThemeMode>(
        valueListenable: themeNotifier,
        builder: (_, ThemeMode currentMode, __) {
          return Consumer<ThemeProvider>(builder: (context, value, child) {
            return ChangeNotifierProvider<AppProvider>(
              create: (context) => AppProvider(),
              child: MaterialApp(
                title: 'Buddies',
                darkTheme: ThemeData.dark(),
                theme: value.getTheme(),
                themeMode: currentMode,
                debugShowCheckedModeBanner: false,
                home: StreamBuilder(
                    stream: FirebaseAuth.instance.authStateChanges(),
                    builder: (context, snapshot) {
                      if (snapshot.hasData) {
                        return HomePage(
                          showPop: false,
                        );
                      }
                      return LoginScreen();
                    }),
              ),
            );
          });
        });
  }
}

Homefile :

@override
  Widget build(BuildContext context) {
    Future.delayed(Duration.zero, () => showDialogIfFirstLoaded(context));
    return AdvancedDrawer(
      backdropColor: Theme.of(context).primaryColor,
      controller: _advancedDrawerController,
      animationCurve: Curves.easeInOut,
      animationDuration: const Duration(milliseconds: 300),
      animateChildDecoration: true,
      rtlOpening: false,
      disabledGestures: false,
      childDecoration: const BoxDecoration(
        borderRadius: const BorderRadius.all(Radius.circular(16)),
      ),
      drawer: SafeArea(
        child: Container(
          color: Theme.of(context).primaryColor,
          child: ListTileTheme(
            textColor: Colors.white,
            iconColor: Colors.white,
            child: Column(
              mainAxisSize: MainAxisSize.max,
              children: [
                StreamBuilder(
                  stream: FirebaseFirestore.instance
                      .collection("users")
                      .doc(currentUserUid)
                      .snapshots(),
                  builder: (context,
                      AsyncSnapshot<DocumentSnapshot<Map<String, dynamic>>>
                          snapshot) {
                    if (snapshot.connectionState == ConnectionState.waiting) {
                      return Center(
                        child: CircularProgressIndicator(),
                      );
                    }
                    if (!snapshot.hasData) {
                      return Center(
                        child: CircularProgressIndicator(),
                      );
                    }
                    return Container(
                      width: 128.0,
                      height: 128.0,
                      margin: const EdgeInsets.only(
                        top: 24.0,
                        bottom: 64.0,
                      ),
                      child: ClipOval(
                        child: SizedBox.fromSize(
                          size: Size.fromRadius(48), // Image radius
                          child: Image.network(snapshot.data!.get("image"),
                              fit: BoxFit.fill),
                        ),
                      ),
                    );
                  },
                ),
                ListTile(
                  onTap: () {
                    Provider.of<ThemeProvider>(context, listen: false)
                        .swapTheme();
                  },
                  leading: Icon(value.mode == ThemeMode.light
                      ? Icons.dark_mode
                      : Icons.light_mode),
                  title: value.mode == ThemeMode.light
                      ? Text(
                          "Dark Mode",
                          style: TextStyle(
                            fontFamily: "San Francisco",
                          ),
                        )
                      : Text(
                          "Light Mode",
                          style: TextStyle(
                            fontFamily: "San Francisco",
                          ),
                        ),
                ),
                // ListTile(
                //   onTap: () {
                //     Provider.of<ThemeProvider>(context, listen: false)
                //         .swapTheme();
                //   },
                //   leading: Icon(MyApp.themeNotifier.value == ThemeMode.light
                //       ? Icons.dark_mode
                //       : Icons.light_mode),
                //   title: MyApp.themeNotifier.value == ThemeMode.light
                //       ? Text(
                //           "Dark Mode",
                //           style: TextStyle(
                //             fontFamily: "San Francisco",
                //           ),
                //         )
                //       : Text(
                //           "Light Mode",
                //           style: TextStyle(
                //             fontFamily: "San Francisco",
                //           ),
                //         ),
                // ),
                ListTile(
                  onTap: () {
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (ctx) => HomePage(
                          showPop: false,
                        ),
                      ),
                    );
                  },
                  leading: Icon(Icons.home),
                  title: Text(
                    'Home',
                    style: TextStyle(
                      fontFamily: "San Francisco",
                    ),
                  ),
                ),
                ListTile(
                  onTap: () {
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (ctx) => ProfilePage(),
                      ),
                    );
                  },
                  leading: Icon(Icons.person),
                  title: Text(
                    'Profile',
                    style: TextStyle(
                      fontFamily: "San Francisco",
                    ),
                  ),
                ),
                ListTile(
                  onTap: () {
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (ctx) => ContactUs(),
                      ),
                    );
                  },
                  leading: Icon(Icons.email),
                  title: Text(
                    'Contact us',
                    style: TextStyle(
                      fontFamily: "San Francisco",
                    ),
                  ),
                ),
                ListTile(
                  onTap: () {
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (ctx) => ReportBug(),
                      ),
                    );
                  },
                  leading: Icon(Icons.bug_report),
                  title: Text(
                    'Report a bug',
                    style: TextStyle(
                      fontFamily: "San Francisco",
                    ),
                  ),
                ),
                ListTile(
                  onTap: () async {
                    await FirebaseAuth.instance.signOut();
                    Navigator.of(context).pushReplacement(
                      MaterialPageRoute(
                        builder: (ctx) => LoginScreen(),
                      ),
                    );
                  },
                  leading: Icon(Icons.logout),
                  title: Text(
                    'Logout',
                    style: TextStyle(
                      fontFamily: "San Francisco",
                    ),
                  ),
                ),
                Spacer(),
                DefaultTextStyle(
                  style: TextStyle(
                    fontSize: 12,
                  ),
                  child: GestureDetector(
                    onTap: () {
                      _launchURL(
                          "https://buddiesapp.co/policies/privacy-policy");
                    },
                    child: Container(
                      margin: const EdgeInsets.symmetric(
                        vertical: 16.0,
                      ),
                      child: Text(
                        'Privacy Policy',
                        style: TextStyle(
                            fontFamily: "San Francisco",
                            fontSize: 15,
                            decoration: TextDecoration.underline),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
      child: CheckDealScreen(
        home: Scaffold(
          appBar: AppBar(
            centerTitle: true,
            title: const Text(
              "Buddies",
              style: TextStyle(
                fontFamily: "San Francisco",
              ),
            ),
            automaticallyImplyLeading: false,
            leading: IconButton(
              onPressed: _handleMenuButtonPressed,
              icon: ValueListenableBuilder<AdvancedDrawerValue>(
                valueListenable: _advancedDrawerController,
                builder: (_, value, __) {
                  return AnimatedSwitcher(
                    duration: Duration(milliseconds: 250),
                    child: Icon(
                      value.visible ? Icons.clear : Icons.menu,
                      key: ValueKey<bool>(value.visible),
                    ),
                  );
                },
              ),
            ),
            backgroundColor: Theme.of(context).primaryColor,
          ),
          body: Consumer<ThemeProvider>(
            builder: (context, value, child) {
              return currentUserUid.isEmpty
                  ? Center(
                      child: CircularProgressIndicator(),
                    )
                  : StreamBuilder(
                      stream: FirebaseFirestore.instance
                          .collection("users")
                          .doc(currentUserUid)
                          .snapshots(),
                      builder: (context,
                          AsyncSnapshot<DocumentSnapshot<Map<String, dynamic>>>
                              snapshot) {
                        if (snapshot.connectionState ==
                            ConnectionState.waiting) {
                          return Center(
                            child: CircularProgressIndicator(),
                          );
                        }
                        if (!snapshot.hasData) {
                          return Center(
                            child: CircularProgressIndicator(),
                          );
                        }
                        return Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 12.0),
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Image.asset(
                                "assets/splashnew.png",
                                scale: 5,
                              ),
                              SizedBox(
                                height: 40,
                              ),
                              Container(
                                width: double.infinity,
                                height: 50,
                                decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(25),
                                  color: Theme.of(context).primaryColor,
                                ),
                                child: MaterialButton(
                                  child: Column(
                                    children: [
                                      SizedBox(
                                        height: 6.0,
                                      ),
                                      Text(
                                        "Meet & Bom",
                                        style: const TextStyle(
                                          color: Colors.white,
                                          fontFamily: "San Francisco",
                                          fontStyle: FontStyle.normal,
                                          fontSize: 18,
                                        ),
                                      ),
                                      Text(
                                        "Get 50 points for bomming",
                                        style: const TextStyle(
                                          fontFamily: "San Francisco",
                                          fontStyle: FontStyle.normal,
                                          fontSize: 12,
                                        ),
                                      ),
                                    ],
                                  ),
                                  onPressed: () {
                                    Navigator.of(context).push(
                                      MaterialPageRoute(
                                        builder: (ctx) => const DonateSnus(),
                                      ),
                                    );
                                  },
                                ),
                              ),
                              const SizedBox(
                                height: 24.0,
                              ),
                              Container(
                                width: double.infinity,
                                height: 50,
                                decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(25),
                                  color: Theme.of(context).primaryColor,
                                ),
                                child: MaterialButton(
                                  child: Column(
                                    children: [
                                      SizedBox(
                                        height: 6.0,
                                      ),
                                      Text(
                                        "Meet a Buddy",
                                        style: const TextStyle(
                                          color: Colors.white,
                                          fontFamily: "San Francisco",
                                          fontStyle: FontStyle.normal,
                                          fontSize: 18,
                                        ),
                                      ),
                                      Text(
                                        "You'll need 10 points",
                                        style: const TextStyle(
                                          fontFamily: "San Francisco",
                                          fontStyle: FontStyle.normal,
                                          fontSize: 12,
                                        ),
                                      ),
                                    ],
                                  ),
                                  onPressed: () {
                                    if (snapshot.data!.get("points") >= 10) {
                                      Navigator.of(context).push(
                                        MaterialPageRoute(
                                          builder: (ctx) => INeedSnus(),
                                        ),
                                      );
                                    } else {
                                      ScaffoldMessenger.of(context)
                                          .showSnackBar(SnackBar(
                                        content: Text(
                                          "You need 10 points to send request ",
                                          style: TextStyle(
                                            fontFamily: "San Francisco",
                                          ),
                                        ),
                                      ));
                                    }
                                  },
                                ),
                              ),
                              const SizedBox(
                                height: 24.0,
                              ),
                              isLoaded
                                  ? Center(
                                      child: CircularProgressIndicator(),
                                    )
                                  : Container(
                                      width: double.infinity,
                                      height: 50,
                                      decoration: BoxDecoration(
                                        borderRadius: BorderRadius.circular(25),
                                        color: Theme.of(context).primaryColor,
                                      ),
                                      child: MaterialButton(
                                        child: Column(
                                          children: [
                                            SizedBox(
                                              height: 6.0,
                                            ),
                                            Text(
                                              "Watch ads - Get Points ",
                                              style: const TextStyle(
                                                color: Colors.white,
                                                fontFamily: "San Francisco",
                                                fontStyle: FontStyle.normal,
                                                fontSize: 18,
                                              ),
                                            ),
                                            Text(
                                              "Get 2.5 points",
                                              style: const TextStyle(
                                                fontFamily: "San Francisco",
                                                fontStyle: FontStyle.normal,
                                                fontSize: 12,
                                              ),
                                            ),
                                          ],
                                        ),
                                        onPressed: () {
                                          loadAd(snapshot.data!.get("points"));
                                          // print(DateTime.now().toLocal());
                                        },
                                      ),
                                    ),
                              const SizedBox(
                                height: 24.0,
                              ),
                              Container(
                                width: double.infinity,
                                height: 50,
                                decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(25),
                                  color: Theme.of(context).primaryColor,
                                ),
                                child: MaterialButton(
                                  child: Column(
                                    children: [
                                      SizedBox(
                                        height: 6.0,
                                      ),
                                      Text(
                                        "Refer a friend",
                                        style: const TextStyle(
                                          color: Colors.white,
                                          fontFamily: "San Francisco",
                                          fontStyle: FontStyle.normal,
                                          fontSize: 18,
                                        ),
                                      ),
                                      Text(
                                        "Get 5 Points",
                                        style: const TextStyle(
                                          fontFamily: "San Francisco",
                                          fontStyle: FontStyle.normal,
                                          fontSize: 12,
                                        ),
                                      ),
                                    ],
                                  ),
                                  onPressed: () {
                                    Navigator.of(context).push(
                                      MaterialPageRoute(
                                        builder: (ctx) => ReferAFriend(
                                          referCode: snapshot.data!
                                              .get("myrefercode")
                                              .toString(),
                                        ),
                                      ),
                                    );
                                  },
                                ),
                              ),
                              const SizedBox(
                                height: 24.0,
                              ),
                              Container(
                                width: 150,
                                padding: const EdgeInsets.symmetric(
                                    horizontal: 12.0),
                                height: 50,
                                decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(25),
                                  color: Theme.of(context).primaryColor,
                                ),
                                child: Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment.spaceBetween,
                                  children: [
                                    Text(
                                      "Points",
                                      style: TextStyle(
                                        fontFamily: "San Francisco",
                                        fontStyle: FontStyle.normal,
                                        color: Colors.white,
                                      ),
                                    ),
                                    Text(
                                      "${snapshot.data!.get("points").toStringAsFixed(2)}",
                                      style: TextStyle(
                                        fontFamily: "San Francisco",
                                        fontStyle: FontStyle.normal,
                                        color: Colors.white,
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              const SizedBox(
                                height: 24.0,
                              ),
                            ],
                          ),
                        );
                      });
            },
          ),
        ),
      ),
    );
  }

  void _handleMenuButtonPressed() {
    _advancedDrawerController.showDrawer();
  }
Ali Akbar
  • 121
  • 12

2 Answers2

1

I've used ThemeMode to check the mode.

class ThemeProvider extends ChangeNotifier {
  late ThemeMode _themeMode;
  late Typography defaultTypography;
  late SharedPreferences prefs;

  ThemeData dark = ThemeData.dark().copyWith();

  ThemeData light = ThemeData.light().copyWith();

  ThemeProvider(bool darkThemeOn) {
    _themeMode = darkThemeOn ? ThemeMode.dark : ThemeMode.light;
  }

  Future<void> swapTheme() async {
    prefs = await SharedPreferences.getInstance();

    if (_themeMode == ThemeMode.light) {
      await prefs.setBool("darkTheme", false);
      _themeMode = ThemeMode.dark;
    } else {
      await prefs.setBool("darkTheme", true);
      _themeMode = ThemeMode.light;
    }
    notifyListeners();
  }

  ThemeMode get mode => _themeMode;
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  SharedPreferences.getInstance().then((prefs) {
    var isDarkTheme = prefs.getBool("darkTheme") ?? false;

    return runApp(
      ChangeNotifierProvider<ThemeProvider>(
        create: (BuildContext context) {
          return ThemeProvider(isDarkTheme);
        },
        child: const MyApp(),
      ),
    );
  });
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Consumer<ThemeProvider>(
      builder: (context, themeProvider, child) {
        return MaterialApp(
          title: 'Buddies',
          darkTheme: themeProvider.dark,
          theme: themeProvider.light,
          themeMode: themeProvider.mode,
          debugShowCheckedModeBanner: false,
          home: ThemeTester(),
        );
      },
    );
  }
}


class ThemeTester extends StatelessWidget {
  const ThemeTester({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Consumer<ThemeProvider>(
        builder: (context, value, child) {
          return Column(
            children: [
              ListTile(
                onTap: () {
                  Provider.of<ThemeProvider>(context, listen: false)
                      .swapTheme();
                },
                leading: Icon(value.mode == ThemeMode.light
                    ? Icons.dark_mode
                    : Icons.light_mode),
                title: value.mode == ThemeMode.light
                    ? Text(
                        "Dark Mode",
                        style: TextStyle(
                          fontFamily: "San Francisco",
                        ),
                      )
                    : Text(
                        "Light Mode",
                        style: TextStyle(
                          fontFamily: "San Francisco",
                        ),
                      ),
              ),
            ],
          );
        },
      ),
    );
  }
}
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
  • Code is working I want to change the icon and names in the ListTile this isn't what I want since its already done and is working – Ali Akbar Feb 18 '22 at 15:13
  • You need to use `Consumer` , check update – Md. Yeasin Sheikh Feb 18 '22 at 15:16
  • My drawer is out of body so thats why .value isnt working. I've just added my home file as well can you please tell how it will work according to it please your help is of great use – Ali Akbar Feb 18 '22 at 15:38
  • Can you test my full code and compare the approach i've made – Md. Yeasin Sheikh Feb 18 '22 at 17:17
  • I did. It gives this error Undefined name 'value'. Try correcting the name to one that is defined, or defining the name. This is coming probably because the consumer builder is on body and my drawer is out of body. I've uploaded code of my home file with drawer and other code too you can see it there – Ali Akbar Feb 18 '22 at 18:14
0

For the icon, instead of doing

MyApp.themeNotifier.value == ThemeMode.light ? Icons.dark_mode : Icons.light_mode

You will need to subscribe to the provider. You can use the same way you did in your onTap to access the provider:

Provider.of<ThemeProvider>(context, listen: true).value == ThemeMode.light ? Icons.dark_mode : Icons.light_mode

Notice listen: true so your widget subscribes to your ThemeNotifier and rebuilds every time it notifies its listeners.

Valentin Vignal
  • 6,151
  • 2
  • 33
  • 73
  • Not working it giving error on .value The getter 'value' isn't defined for the type 'ThemeProvider'. Try importing the library that defines 'value', correcting the name to the name of an existing getter, or defining a getter or field named 'value'. – Ali Akbar Feb 18 '22 at 14:47
  • then it is not `.value`. Can you share what is your class `ThemeProvider`? Basically, instead of using `.value` use the field of `ThemeProvider` that store the `ThemeMode` – Valentin Vignal Feb 18 '22 at 14:58
  • All the code releated to ThemeProvider is in the theme.dart file and all of the code I've uploaded in my question please check – Ali Akbar Feb 18 '22 at 15:13
  • Or you can do `Theme.of(context).brightness == Brightness.light ? Icons.dark_mode : Icons.light_mode` – Valentin Vignal Feb 19 '22 at 03:30