Code前端首页关于Code前端联系我们

Flutter 主题更换器 - APP 一键换皮

terry 2年前 (2023-09-22) 阅读数 79 #移动小程序

App 更漂亮。主题切换已经是必备功能,但在传统的Android和iOS上调整不同的主题相当繁琐。但这一切都是很容易在颤抖中实现的。今天我们将了解如何在 Flutter 中向应用程序添加换肤功能。我们想要实现的效果如下:

Flutter主题切换——APP一键换肤

添加依赖

本例中我使用了providerflustars❀。我们来看看这两个库:

Provider

官方推荐的State Management库,使用起来比其他状态管理库更方便。

状态管理:通俗地说,如果我们想在不同页面(组件/小部件)之间共享状态(数据),或者在一个页面(组件/小部件)上的多个子组件之间共享状态(数据),在这个这个时候我们就可以‘使用Flutter中的状态管理来管理统一的状态(数据),实现不同组件之间直接的价值传递和数据交换。

flustars

被称为“Flutter最全、最常用的Web工具”,包括SpUtil❀ ScreenUtil、 lineUtil 以及其他常用工具,有哪些我们这里使用的是SpUtil部分,用于存储用户选择的主题信息。


上面是我们使用的两个第三方库的介绍。如果我们想使用的话,需要在文件pubspec.yaml中添加如下内容:

provider: ^4.0.5
flustars: ^0.2.6+1
复制代码

准备工作完成了,继续往下,我们开始编码吧。

添加主题样式

首先我们需要考虑需要切换的主题样式列表。如果觉得烦的话,可以直接使用下面的内容:

Map<String, Color> themeColorMap = {
  'gray': Colors.grey,
  'blue': Colors.blue,
  'blueAccent': Colors.blueAccent,
  'cyan': Colors.cyan,
  'deepPurple': Colors.purple,
  'deepPurpleAccent': Colors.deepPurpleAccent,
  'deepOrange': Colors.orange,
  'green': Colors.green,
  'indigo': Colors.indigo,
  'indigoAccent': Colors.indigoAccent,
  'orange': Colors.orange,
  'purple': Colors.purple,
  'pink': Colors.pink,
  'red': Colors.red,
  'teal': Colors.teal,
  'black': Colors.black,
};
复制代码

使用provider进行全局状态管理

那么我们需要使用provider进行全局状态管理。首先创建一个 app_provider.dart 文件,然后添加以下代码:

class AppInfoProvider with ChangeNotifier {
  String _themeColor = '';

  String get themeColor => _themeColor;

  setTheme(String themeColor) {
    _themeColor = themeColor;
    notifyListeners();
  }
}
复制代码

由于是全局状态管理,接下来我们需要在 main.dart 中配置我们刚刚创建的文件创建的。 Provider,如果有MultiProvider,则使用MultiProvider,单独使用Provider.value。(考虑到以后项目的扩展,我这里直接使用MultiProvider)

class MyApp extends StatelessWidget {
  Color _themeColor;

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [ChangeNotifierProvider.value(value: AppInfoProvider())],
      child: Consumer<AppInfoProvider>(
        builder: (context, appInfo, _) {
          String colorKey = appInfo.themeColor;
          if (themeColorMap[colorKey] != null) {
            _themeColor = themeColorMap[colorKey];
          }

          return MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
              primaryColor: _themeColor,
              floatingActionButtonTheme:
                  FloatingActionButtonThemeData(backgroundColor: _themeColor),
            ),
            home: MyHomePage(title: 'Flutter Theme Change demo'),
          );
        },
      ),
    );
  }
}
复制代码

如果我们想在某个地方改变主题,只需要执行下面这行代码即可。

Provider.of<AppInfoProvider>(context).setTheme(colorKey);
复制代码

我们先来说一下上面的代码。重点是设置ThemeData: Flutter主题切换——APP一键换肤

我们看一下ThemeData部分数据定义:

ThemeData({
  Brightness brightness, //深色还是浅色
  MaterialColor primarySwatch, //主题颜色样本,见下面介绍
  Color primaryColor, //主色,决定导航栏颜色
  Color accentColor, //次级色,决定大多数Widget的颜色,如进度条、开关等。
  Color cardColor, //卡片颜色
  Color dividerColor, //分割线颜色
  ButtonThemeData buttonTheme, //按钮主题
  Color cursorColor, //输入框光标颜色
  Color dialogBackgroundColor,//对话框背景颜色
  String fontFamily, //文字字体
  TextTheme textTheme,// 字体主题,包括标题、body等文字样式
  IconThemeData iconTheme, // Icon的默认样式
  TargetPlatform platform, //指定平台,应用特定平台控件风格
  ...
})
复制代码

以上只是❀对于e❀♝e来说,完整的数据定义可以在SDK中查看。

为什么使用floatingActionButtonTheme来单独使用floatingActionButton而不是t有警告⚠️支持使用 ThemeData.accentIconTheme 配置 FloatingActionButtons 的前景色已被弃用。请用相反,ThemeData.floatingActionButtonTheme。请参阅 https://flutter.dev/go/remove-fab-accent-theme-dependency。此功能在 v1.13.2. 后已弃用,这意味着此属性在 1.13.2 中已弃用。但并不影响我们现在的使用。

有关主题的更多信息,请参阅向上?颜色和主题

选定主题的持久化

这里需要用到开头提到的flustarsSpUtilSpUtil平时阅读颜色页,我们通常阅读Color。初始加载完毕,所以我们需要在初始化页面配置如下代码:

String _colorKey;

@override
void initState() {
  super.initState();
  _initAsync();
}

Future<void> _initAsync() async {
  await SpUtil.getInstance();
  _colorKey = SpUtil.getString('key_theme_color', defValue: 'blue');
  // 设置初始化主题颜色
  Provider.of<AppInfoProvider>(context, listen: false).setTheme(_colorKey);
}
复制代码

await Kongfuncus.getInstance();此代码用于加载SpUtil库,通过查看源码,我们知道这个库接受单例的模式。当然,这不是本文的重点。

以上代码用于初始化主题。我们通过SpUtil.getString('key_theme_color', defValue: 'blue');获取存储的主题信息,然后使用Provider.of (context)。 (_colorKey); 只需设置主题即可。

现在初始化主题完成了,那么选择的代码该怎么写呢?

很简单,只需在适当的地方调用以下代码即可。

setState(() {
  _colorKey = key;
});
SpHelper.putString('key_theme_color', key);
Provider.of<AppInfoProvider>(context).setTheme(key);
复制代码

思路与上面类似,只不过将getString替换为putString

编写主题控件

上面的代码提供了切换主题的思路,但是对于用户来说,他们需要做的就是有一个可以直接切换主题的界面。这就是我们在下面编写 switch 主题的原因。的控制。

由于更改主题通常出现在设置界面中,所以这里我使用了一个ExpansionTile,它是一个可扩展的ListTile。代码如下:

…………
ExpansionTile(
  leading: Icon(Icons.color_lens),
  title: Text('颜色主题'),
  initiallyExpanded: false,
  children: <Widget>[
    Padding(
      padding: EdgeInsets.only(left: 10, right: 10, bottom: 10),
      child: Wrap(
        spacing: 8,
        runSpacing: 8,
        children: themeColorMap.keys.map((key) {
          Color value = themeColorMap[key];
          return InkWell(
            onTap: () {
              setState(() {
                _colorKey = key;
              });
              SpUtil.putString('key_theme_color', key);
              Provider.of<AppInfoProvider>(context, listen: false)
                  .setTheme(key);
            },
            child: Container(
              width: 40,
              height: 40,
              color: value,
              child: _colorKey == key
                  ? Icon(
                      Icons.done,
                      color: Colors.white,
                    )
                  : null,
            ),
          );
        }).toList(),
      ),
    )
  ],
),
…………
复制代码

效果如下: Flutter主题切换——APP一键换肤

上面的代码是展示我们一开始选择的一些主题themeColorMap并告诉用户一个主题可以如何更改。 onTap中的代码就是上一节中设置颜色主题的方法。 InkWell主要用于提供主题颜色的点击效果。更换为手势检测器也是可以的。

至此,我们的换皮功能就完成了。如果想获取完整代码,可以关注公众号“01二进制”,在后台回答“Flutter主题切换”。

最后

以上就是Flutter中如何切换主题的详细内容。可以看到,相比原生应用主题的适配,Flutter中的换肤功能要简单很多。

最后放个预览吧,因为iOS 13和Android 10系统都新增了“深色模式”。在文章中,我还使用了 ThemeDataHelligkeit 属性来指示深色或浅色。下一篇我会讲一下深色模式的适配。

作者:Bagmek
链接:https://juejin.im/post/5ea2b8b5e51d4546d72d5007
来源:掘金商业转载请联系求作者授权。非商业转载请来源。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门