美文网首页Flutter
flutter适配iOS、Android的深色模式

flutter适配iOS、Android的深色模式

作者: xmb | 来源:发表于2020-03-19 10:21 被阅读0次

    参考文章:
    https://www.jianshu.com/p/76539f98b146
    https://www.jianshu.com/p/7b253699dbc5

    1、查看当前的黑暗模式状态

    final Brightness brightnessValue = MediaQuery.of(context).platformBrightness;
    bool isDark = brightnessValue == Brightness.dark;
    

    代码如下:
    dark_mode.dart

    /// 深色模式
    
    class DarkMode {
      // 判断当前是否为深色模式 true:深色  false:浅色
      static bool isDark({BuildContext context}) {
        // return false - 完全屏蔽深色模式功能,不开启深色模式
        return false;
    
    //    if (getDarkModeStatus() == DarkModeStatus.dark) {
    //      // 深色
    ////      LogUtils.d('模式', '深色');
    //      return true;
    //    } else if (getDarkModeStatus() == DarkModeStatus.light) {
    //      // 浅色
    ////      LogUtils.d('模式', '浅色');
    //      return false;
    //    } else {
    //      // 跟随系统
    ////      LogUtils.d('模式', '跟随系统');
    //      if (context != null) {
    //        return MediaQuery.of(context).platformBrightness == Brightness.dark;
    //      } else {
    //        return WidgetsBinding.instance.window.platformBrightness == Brightness.dark;
    //      }
    //    }
      }
    
      // 获取深色模式状态
      static DarkModeStatus getDarkModeStatus() {
        int status = App.getInstance().getInt(SPKeyConst.darkModeKey);
        if (status == null) {
          App.getInstance().setInt(SPKeyConst.darkModeKey, 0);
        }
    
        if (status == 1) {
          return DarkModeStatus.dark;
        } else if (status == 2) {
          return DarkModeStatus.light;
        } else {
          return DarkModeStatus.followSystem;
        }
      }
    }
    
    

    dark_mode_provider.dart

    class DarkModeProvider extends ChangeNotifier {
      // 同步深色模式
      void syncTheme() {
        int theme = App.getInstance().getInt(SPKeyConst.darkModeKey);
        if (theme != null && theme != 0) {
          notifyListeners();
        }
      }
    
      // 设置深色模式
      void setTheme(DarkModeStatus status) {
        if (status == DarkModeStatus.followSystem) {
          // 设置-跟随系统
          App.getInstance().setInt(SPKeyConst.darkModeKey, 0);
        } else if (status == DarkModeStatus.dark) {
          // 设置深色
          App.getInstance().setInt(SPKeyConst.darkModeKey, 1);
        } else if (status == DarkModeStatus.light) {
          // 设置浅色
          App.getInstance().setInt(SPKeyConst.darkModeKey, 2);
        }
    
        notifyListeners();
      }
    
      // 主题样式
      ThemeData getTheme({bool isDark = false}) {
        int theme = App.getInstance().getInt(SPKeyConst.darkModeKey);
        if (theme == null) {
          theme = 0;
        }
        String themeStr = theme.toString();
        switch (themeStr) {
          case "1":
            isDark = true;
            break;
          case "2":
            isDark = false;
            break;
          default:
            break;
        }
    
        return ThemeData(
          // 深色/浅色
          brightness: isDark ? Brightness.dark : Brightness.light,
          // 主题色
          primarySwatch: Colors.blue,
          // 页面背景色
          scaffoldBackgroundColor: isDark ? R.dark_scaffold_bg_color : R.color_white_F6F6F6,
          // 背景色
          backgroundColor: isDark ? R.dark_scaffold_bg_color : R.color_white,
          // 主要用于Material背景色
          canvasColor: isDark ? R.dark_bg_color : R.color_white,
          // Tab指示器颜色
          indicatorColor: isDark ? R.color_green_3CB71D : R.color_green_3CB71D,
          // 导航栏默认样式
          appBarTheme: AppBarTheme(
            elevation: 0,
            color: isDark ? R.dark_nav_bg_color : R.color_white,
            brightness: isDark ? Brightness.dark : Brightness.light,
            textTheme: TextTheme(
              headline6: TextStyle(
                fontSize: R.font_36,
                fontWeight: FontWeight.w500,
                color: isDark ? R.color_white : R.color_black_333333,
              ),
            ),
          ),
          // 文本样式
          textTheme: TextTheme(
              // text默认文字样式
              bodyText2: TextStyle(
                color: isDark ? R.color_white : R.color_black_333333,
              ),
              // TextField输入文字颜色
              subtitle1: TextStyle(
                color: isDark ? R.color_white : R.color_black_333333,
              ),
              // 小文字样式
              subtitle2: TextStyle(
                color: isDark ? R.dark_subtitle : R.color_grey_666666,
              ),
              // 说明描述
              caption: TextStyle(
                color: isDark ? R.dark_caption : R.color_grey_999999,
              )),
          // 分割线样式
          dividerTheme: DividerThemeData(
            color: isDark ? R.dark_line : R.color_grey_EEE,
            space: 0.6,
            thickness: 0.6,
          ),
        );
      }
    
      /// 项目通用适配样式 ============================================
    
      // 页面背景色: R.color_white_F6F6F6 / R.dark_scaffold_bg_color
      static Color scaffoldBackgroundColor(BuildContext context) {
        return Theme.of(context).scaffoldBackgroundColor;
      }
    
      // widget背景色: R.color_white / R.dark_bg_color
      static Color canvasColor(BuildContext context) {
        return Theme.of(context).canvasColor;
      }
    
      // 默认文本颜色: R.color_black_333333 / R.color_white
      static Color textColor(BuildContext context) {
        return Theme.of(context).textTheme.headline6.color;
      }
    
      // 默认返回按钮背景色: R.color_black_333333 / R.color_white
      static Color navBackColor(BuildContext context) {
        return Theme.of(context).textTheme.headline6.color;
      }
    
      // 默认导航栏文本样式
      static appBarTitleStyle(BuildContext context) {
        return Theme.of(context).appBarTheme.textTheme.headline6;
      }
    
      // 灰色文本颜色 666666
      static gray666666TextColor(BuildContext context) {
        return Theme.of(context).textTheme.subtitle2.color;
      }
    
      // 灰色文本颜色 999999
      static gray999999TextColor(BuildContext context) {
        return Theme.of(context).textTheme.caption.color;
      }
    }
    
    

    main.dartmain()

    runApp(ChangeNotifierProvider<DarkModeProvider>(
        create: (context) => DarkModeProvider(),
        child: MyApp(),
      ));
    

    main.dartMyApp

    class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
      @override
      void initState() {
        WidgetsBinding.instance.addObserver(this);
        super.initState();
        WidgetsBinding.instance.addPostFrameCallback((_) async {
          // 由于SpUtil未初始化,所以MaterialApp获取的为默认主题配置,这里同步一下。
          Provider.of<DarkModeProvider>(context, listen: false).syncTheme();
        });
      }
    
      @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }
    

    MyApp

      // 监听系统显示模式改变
      @override
      void didChangePlatformBrightness() {
        final Brightness brightness = WidgetsBinding.instance.window.platformBrightness;
        if (brightness == Brightness.dark) {
          LogUtils.d('tag', '当前系统显示模式:深色模式');
        } else {
          LogUtils.d('tag', '当前系统显示模式:浅色模式');
        }
        setState(() {});
      }
    
    @override
      Widget build(BuildContext context) {
        return MultiProvider(
          providers: providers,
          child: Consumer2<DarkModeProvider,SettingsProvider>(
            builder:  (_, darkModeProvider, settingsProvider, __) {
              return PlatformApp(
                theme: darkModeProvider.getTheme(),
                // 是否开启深色模式
                darkTheme: darkModeProvider.getTheme(isDark: DarkMode.isDark()),
                ...
                ...
              );
            },
          ),
        );
      }
    

    设置页

      // 进入深色模式
      void gotoDarkModeSetting() {
        NavigatorRoute.push(
          context,
          DarkModeSettingPage(),
          pageName: RouteName.darkModeSettingPageName,
        );
      }
    
      // 获取状态
      String getDarkModeStatus() {
        int status = App.getInstance().getInt(SPKeyConst.darkModeKey) ?? 0;
        if (status == 1) {
          return '深色';
        } else if (status == 2) {
          return '浅色';
        } else {
          return '跟随系统';
        }
      }
    

    深色模式设置页

    /// 深色模式
    
    // 深色模式状态
    enum DarkModeStatus {
      followSystem, // 跟随系统0
      dark, // 深色1
      light, // 浅色2
    }
    
    class DarkModeSettingPage extends StatefulWidget {
      @override
      _DarkModeSettingPageState createState() => _DarkModeSettingPageState();
    }
    
    class _DarkModeSettingPageState extends State<DarkModeSettingPage> {
      @override
      void initState() {
        super.initState();
      }
    
      @override
      void dispose() {
        super.dispose();
      }
    
      // 设置0跟随系统、1深色、2浅色
      void setDarkModeAction(BuildContext context, DarkModeStatus status) {
        Provider.of<DarkModeProvider>(context, listen: false).setTheme(status);
    
        if (status == DarkModeStatus.followSystem) {
          // 设置-跟随系统
          App.getInstance().setInt(SPKeyConst.darkModeKey, 0);
        } else if (status == DarkModeStatus.dark) {
          // 设置深色
          App.getInstance().setInt(SPKeyConst.darkModeKey, 1);
        } else if (status == DarkModeStatus.light) {
          // 设置浅色
          App.getInstance().setInt(SPKeyConst.darkModeKey, 2);
        }
    
        setState(() {});
      }
    
      // 获取状态
      DarkModeStatus getDarkModeStatus() {
        int status = App.getInstance().getInt(SPKeyConst.darkModeKey) ?? 0;
        if (status == 1) {
          return DarkModeStatus.dark;
        } else if (status == 2) {
          return DarkModeStatus.light;
        } else {
          return DarkModeStatus.followSystem;
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return PlatformScaffold(
          backgroundColor: Theme.of(context).scaffoldBackgroundColor,
          appBar: PlatformAppBar(
            preferredSizeWidget: AppBarWidget(
              elevation: 0,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  GestureDetector(
                    onTap: () {
                      Navigator.of(context).pop();
                    },
                    child: Container(
                      padding: EdgeInsets.only(right: 20),
                      color: R.color_transparent,
                      width: 64.0,
                      height: 44.0,
                      child: Image.asset(
                        'images/base/black_left_back_icon.png',
                        width: 8.5,
                        height: 14,
                        color: DarkModeProvider.navBackColor(context),
                      ),
                    ),
                  ),
                  Expanded(
                    child: Center(
                      child: Text(
                        '深色模式',
                        style: DarkModeProvider.appBarTitleStyle(context),
                        textAlign: TextAlign.center,
                      ),
                    ),
                  ),
                  SizedBox(
                    width: 64,
                  ),
                ],
              ),
            ),
          ),
          body: Container(
            child: ListView(
              children: <Widget>[
                GestureDetector(
                  onTap: () {
                    setDarkModeAction(context, DarkModeStatus.followSystem);
                  },
                  behavior: HitTestBehavior.opaque,
                  child: Container(
                    padding: EdgeInsets.symmetric(horizontal: 15),
                    color: Theme.of(context).canvasColor,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        Container(
                          width: 100,
                          padding: EdgeInsets.symmetric(vertical: 13.5),
                          child: Text(
                            '跟随系统',
                            style: TextStyle(
                              fontSize: R.font_32,
                            ),
                          ),
                        ),
                        Offstage(
                          offstage: getDarkModeStatus() != DarkModeStatus.followSystem,
                          child: Image.asset('images/base/check_mark.png'),
                        ),
                      ],
                    ),
                  ),
                ),
                Divider(
                  height: 1,
                ),
                GestureDetector(
                    onTap: () {
                      // 深色
                      setDarkModeAction(context, DarkModeStatus.dark);
                    },
                    behavior: HitTestBehavior.opaque,
                    child: Container(
                      padding: EdgeInsets.symmetric(horizontal: 15),
                      color: Theme.of(context).canvasColor,
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: <Widget>[
                          Container(
                            width: 100,
                            padding: EdgeInsets.symmetric(vertical: 13.5),
                            child: Text(
                              '深色',
                              style: TextStyle(
                                fontSize: R.font_32,
                              ),
                            ),
                          ),
                          Offstage(
                            offstage: getDarkModeStatus() != DarkModeStatus.dark,
                            child: Image.asset('images/base/check_mark.png'),
                          ),
                        ],
                      ),
                    )),
                Divider(
                  height: 1,
                ),
                GestureDetector(
                  onTap: () {
                    // 浅色
                    setDarkModeAction(context, DarkModeStatus.light);
                  },
                  behavior: HitTestBehavior.opaque,
                  child: Container(
                    padding: EdgeInsets.symmetric(horizontal: 15),
                    color: Theme.of(context).canvasColor,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: <Widget>[
                        Container(
                          width: 100,
                          padding: EdgeInsets.symmetric(vertical: 13.5),
                          child: Text(
                            '浅色',
                            style: TextStyle(
                              fontSize: R.font_32,
                            ),
                          ),
                        ),
                        Offstage(
                          offstage: getDarkModeStatus() != DarkModeStatus.light,
                          child: Image.asset('images/base/check_mark.png'),
                        ),
                      ],
                    ),
                  ),
                ),
                Divider(
    //              height: 1,
                    ),
              ],
            ),
          ),
        );
      }
    }
    
    

    适配注意事项:

    1. 导航栏返回按钮
      image添加 color: DarkModeProvider.navBackColor(context)

    2. 导航栏背景色
      AppBarWidget中的以下3行代码去掉

    backgroundColor: R.color_white,
    appBarColor: R.color_white,
    brightness: Brightness.light,
    

    导航栏的返回按钮 或 导航栏右侧的按钮,添加 color: DarkModeProvider.navBackColor(context)
    中间的居中标题样式,style替换为 style: DarkModeProvider.appBarTitleStyle(context)

    1. 背景色
      页面背景色:
      PlatformScaffold中的 backgroundColor: Colors.white,
      backgroundColor: R.color_white_F6F6F6,
      替换为 backgroundColor: Theme.of(context).scaffoldBackgroundColor

    widget白色背景:
    Colors.whiteR.color_white 替换为 DarkModeProvider.canvasColor(context)

    1. 文本颜色
      黑色文本颜色 R.color_black_333333 去掉,文本颜色会自动改变

    注意这里导航栏里的Text文本颜色R.color_black_333333在这里不适用,不要去掉,
    而是改为DarkModeProvider.textColor(context)

    灰色字体颜色
    R.color_grey_666666 替换为 DarkModeProvider.gray666666TextColor(context)
    R.color_grey_999999 替换为 DarkModeProvider.gray999999TextColor(context)

    1. 分割线
      Divider的color去掉,颜色自动改变

    相关文章

      网友评论

        本文标题:flutter适配iOS、Android的深色模式

        本文链接:https://www.haomeiwen.com/subject/nmekyhtx.html