简体   繁体   English

flutter中如何根据主题更换图标

[英]How to change the icon according to the theme in flutter

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.我已成功保存所选主题,但无法根据选择更改抽屉的 ListTile 中的图标和文本。

Theme.dart:主题.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();
  }

I've used ThemeMode to check the mode.我使用ThemeMode来检查模式。

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",
                        ),
                      ),
              ),
            ],
          );
        },
      ),
    );
  }
}

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:您可以使用与在onTap中相同的方式来访问提供者:

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.注意listen: true所以你的小部件订阅你的ThemeNotifier并在每次通知它的听众时重建。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM