Flutter 主题设置一种实现方法(通过provider状态共享)

主题设置

 效果如下图

 

 

实现方法

核心:通过跨组件状态共享provider,更改MaterialAPP的theme属性。

Flutter 官方鼓励我们在写 Flutter 应用的时候直接从 MaterialApp 开始,原因是 MaterialApp
为我们集成好了很多 Material Design 所必须的控件,如AnimatedThemen、GridPager 等,另外还通过MaterialApp 配置了全局路由,方便进行页面的切换

准备工作:pubspec.yaml中导入provider包

provider基本用法;1、新建状态管理类。 2、顶层注册状态管理类。3、状态组件绑定 。4、状态变更。

provider详细介绍

1、第一步
    新建一个themeModel.dart数据model类(即我们要共享的状态)


import 'package:flutter/material.dart';

/*1.创建theme数据Model
    这里的 Model 实际上就是我们的状态,它不仅储存了我们的数据模型,而且还包含了更改数据的方法,并暴露出它想要暴露出的数据
*/
class ThemeModel with ChangeNotifier {

      String _theme = 'blue';
      String get value => _theme;

      void setTheme(color) async
      {
          _theme = color;
          print(_theme);    
          notifyListeners(); //通知依赖的Widget更新      
      }
}

2、第二步

在main.dart文件main方法里注册顶层共享数据。注意导入provider包和新建的themeModel类

void main() {
  //2、注册顶层共享数据
  return runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context)=>ThemeModel()),//此是主题状态注册
      ],
      child: MyApp(),
    )
  );
}

MultiProvider用来注册你需要共享的状态,。

3、第三步

新建一个theme类,我们改变主题其产生对应的设置。当然也可以不这样改变整个theme,而只对theme属性下的primaryColor进行改变

import 'package:flutter/material.dart';


Map materialColor = { // 主副颜色
  'purple': {
    "primaryColor": 0xFF7B1FA2,
    "primaryColorLight": 0xFF9C27B0,
  },
  'pink': {
    "primaryColor": 0xFFc2185b,
    "primaryColorLight": 0xFFd81b60,
  },
  'deeppink': {
    "primaryColor": 0xFFf50057,
    "primaryColorLight": 0xFFe91e63,
  },
  'blue': {
    "primaryColor": 0xFF1976D2,
    "primaryColorLight": 0xFF2196F3,
  },
};
 
class AppTheme {
  static Map mainColor = materialColor['blue'];   // 默认颜色
  static getThemeData(String theme) {  // 获取theme方法: getThemeData();
    mainColor = materialColor[theme];  // 设置主题颜色
    ThemeData themData = ThemeData(
      // scaffoldBackgroundColor: Colors.red, // 页面的背景颜色
 
      primaryColor: Color(mainColor["primaryColor"]), // 主颜色
      primaryColorLight: Color(mainColor["primaryColorLight"]),
      // 按钮颜色
      buttonTheme: ButtonThemeData(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(5.0),
        ),
        textTheme: ButtonTextTheme.normal,
        buttonColor: Color(mainColor["primaryColor"]),
      ),
      // 小部件的前景色(旋钮,文本,过度滚动边缘效果等)。
      accentColor: Color(mainColor["primaryColor"]),
 
      // appbar样式
      appBarTheme: AppBarTheme(
        iconTheme: IconThemeData(color: Colors.white),
        textTheme: TextTheme(
          title: TextStyle(
            color: Colors.white,
            fontSize: 20.0,
          ),
        ),
      ),
 
      // 图标样式
      iconTheme: IconThemeData(
        color: Color(mainColor["primaryColor"]),
      ),
 
      // 用于自定义对话框形状的主题。
      dialogTheme: DialogTheme(
        backgroundColor: Colors.white,
        titleTextStyle: TextStyle(
          fontSize: 18.0,
          color: Colors.black87,
        ),
      ),
    );
    return themData;
  }
}

 

themeData介绍:

4、第四步

在main.dart文件中的MyApp类中将主题状态与theme组件绑定

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //3、状态组件绑定,将主题状态与组件绑定
        return Consumer<ThemeModel>(   //主题设置1:状态获取方式
          builder: (context,themeModel,child)
          {
            return MaterialApp(
              theme: AppTheme.getThemeData(themeModel.value), //主题设置2
              title: 'Yshow',
              initialRoute: welcomeRoute,//欢迎页
              routes: routes   //注册路由
            );
          },
        );

  }
}

关键是主题设置标注的两处,Consumer是获取你注册的状态的一种方式

Consumer 使用了 Builder 模式,收到更新通知就会通过 builder 重新构建。Consumer<T> 代表了它要获取哪一个祖先中的 Model。

Consumer 的 builder 实际上就是一个 Function,它接收三个参数 (BuildContext context, T model, Widget child)

  • context: context 就是 build 方法传进来的 BuildContext 在这里就不细说了,如果有兴趣可以看我之前这篇文章 Flutter | 深入理解BuildContext
  • T:T也很简单,就是获取到的最近一个祖先节点中的数据模型。
  • child:它用来构建那些与 Model 无关的部分,在多次运行 builder 中,child 不会进行重建。

Consumer2<A,B>使用方式基本上和 Consumer<T> 一致,只不过范型改为了两个,并且 builder 方法也变成了 Function(BuildContext context, A value, B value2, Widget child)

我勒个去...假如我要获得 100 个 Model,那岂不是得搞个 Consumer100 (???黑人问号.jpg)

然而并没有 😏。

从源码里面可以看到,作者只为我们搞到了 Consumer6。emmmmm.....还要要求更多就只有自力更生喽。


作者:Vadaski
链接:https://juejin.im/post/6844903864852807694
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

作者:Vadaski
链接:https://juejin.im/post/6844903864852807694
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

5、第五步

在你需要设置主题的地方调用另一种获取状态的方式Provider.of(context)调用内部设置方法改变主题


                    if (i != null) {
                        if(i==1)
                        {               
                          Provider.of<ThemeModel>(context,listen: false).setTheme('blue');
                        }
                        else if(i==2)
                        {                
                          Provider.of<ThemeModel>(context,listen:false).setTheme('purple');
                        }
                        else if(i==3)
                        {                      
                          Provider.of<ThemeModel>(context,listen: false).setTheme('pink');
                        }
                        else if(i==4)
                        {                
                                   Provider.of<ThemeModel>(context,listen:false).setTheme('deeppink');
                        }
                    }

 

 

源码地址

https://github.com/Yimi81/Flutter-ThemeAndLang

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值