前天在做项目的时候, 遇到一个问题(夜间模式的实现),通常我们在设置夜间模式的时候,简单的做法是使用通知的设计模式,改变各个页面的背景色,然后设置一下透明的效果,可是一个真正的项目,并不能马虎,需要页面效果美观精致。本文参考了github上一个老外写的实现方案,方案参考 经过自己的理解整合,制作出了自己的页面模式的实现。
在这里我先要说明一下:在Xcode中蓝色和黄色文件夹的区别,因为本文就是使用到了蓝色的文件夹,通常蓝色文件夹在IOS中被称为folder,他在项目中只能被称为资源来使用,不能被编译代码。黄色文件夹被称为group一般在工程中是文件夹的形式,但是在本地目录里还是比较散乱的文件,为了更好地管理和规范一个工程的文件夹,请参考我的博文,一般先创建好工程的框架文件夹,然后拖入工程,选择复制和创建,这样再次新建的文件就会在对应的group文件夹中了。
将设置的夜间模式与日间模式的颜色RGB值分别写入plist文件,将日间模式定为系统的默认模式。需要创建三个plist文件。pliast A 用来存放模式(日间/夜间);pliast B 用来存放日间模式下的RGB颜色值,写入group中;plist C 用来存放夜间模式下的RGB的颜色值,写入floder中。其中 B 与 C 中相同的颜色值名字 key 对应的Value值(RGB 值)是不一样的,这样在检测到通知改变的时候,系统就根据当前的主题模式去根据路径寻找对应的plist A 或者 B文件,然后通过一个将RGB值转化为对应的颜色值的方法,进行改变页面的颜色,不仅能改变背景色,也可以通过这个方法改变一些控件的颜色值,这样就真正的实现了夜间模式,是不是有些麻烦呢?
图1.存放日间,夜间模式的路径
图2.日间模式的颜色值
图3.夜间模式的颜色值
下面我将会附上关键源代码。
//更主题的通知 #define ThemeChangeNotification @"ThemeChangeNotification" //更改主题的通知 #define ThemeName @"ThemeName" //主题名称 #import <UIKit/UIKit.h> #import <Foundation/Foundation.h> @interface ConfigurationTheme : NSObject { @private //主题配置信息 NSDictionary * _themesConfig; } @property (copy, nonatomic) NSString *themeName; //当前使用的主题名称 @property (strong, nonatomic) NSDictionary *themesConfig; //主题配置信息 @property (strong, nonatomic) NSDictionary *fontConfig; //字体的配置信息 //创建单例,确保该对象唯一 + (ConfigurationTheme *)shareInstance; //获取当前主题下的图片名称 -(UIImage *)getThemeImageName:(NSString *)imageName; //获取当前主题下的颜色 - (UIColor *)getThemeColorWithName:(NSString *)colorName;
#import "ConfigurationTheme.h" @implementation ConfigurationTheme //创建单例,确保该对象唯一 + (ConfigurationTheme *)shareInstance{ static ConfigurationTheme *configuration = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ configuration = [ConfigurationTheme new]; }); return configuration; } //重写init方法 -(id)init{ self = [super init]; if (self != nil) { //读取主题配置文件 NSString *filePlist = [[NSBundle mainBundle] pathForResource:@"theme" ofType:@"plist"]; _themesConfig = [NSDictionary dictionaryWithContentsOfFile:filePlist]; //读取字体配置文件 NSString *fontConfigPlist = [[NSBundle mainBundle] pathForResource:@"fontColor" ofType:@"plist"]; _fontConfig = [NSDictionary dictionaryWithContentsOfFile:fontConfigPlist]; self.themeName = @"默认"; } return self; } //得到当前主题名称 - (void)setThemeName:(NSString *)themeName{ if (_themeName != themeName) { _themeName = [themeName copy]; } //获取主题配置的根目录 NSString * themePath = [self getThemePath]; NSString * filePath = [themePath stringByAppendingPathComponent:@"fontColor.plist"]; _fontConfig = [NSDictionary dictionaryWithContentsOfFile:filePath]; } //获取当前主题配置的目录 - (NSString *)getThemePath{ //项目的根路径 NSString * resourcePath = [[NSBundle mainBundle] resourcePath]; if ([_themeName isEqualToString:@"默认"]) { return resourcePath; } //获取当前主题的配置路径 NSString *configurationPath = [_themesConfig objectForKey:_themeName]; //主题的完整路径 NSString *themePath = [resourcePath stringByAppendingPathComponent:configurationPath]; return themePath; } //获取当前主题下的图片 -(UIImage *)getThemeImageName:(NSString *)imageName{ if (imageName.length == 0) { return nil; } //获取当前主题配置的目录 NSString *configurationPath = [self getThemePath]; //图片名称在当前主题的文件路径 NSString *imagePath = [configurationPath stringByAppendingPathComponent:imageName]; UIImage *image = [UIImage imageWithContentsOfFile:imagePath]; return image; } //获取当前主题下的颜色 - (UIColor *)getThemeColorWithName:(NSString *)colorName{ if (colorName.length == 0){ return nil; } NSString *rgb = [self.fontConfig objectForKey:colorName]; NSArray *rgbs = [rgb componentsSeparatedByString:@","]; if (rgbs.count == 3) { float r = [rgbs[0] floatValue]; float g = [rgbs[1] floatValue]; float b = [rgbs[2] floatValue]; UIColor *color = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]; return color; } return nil; } + (id)copyWithZone:(NSZone *)zone { return self; } @end
#import "BaseNavigationController.h" @interface BaseNavigationController () @end @implementation BaseNavigationController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { //监听主题切换的通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(themeNotification:) name:ThemeChangeNotification object:nil]; } return self; } - (void)themeNotification:(NSNotification *)notification { [self loadThemeImage]; } - (void)loadThemeImage { //使用颜色设置navigationBar的背景颜色 // self.navigationBar.barTintColor = [[ConfigurationTheme shareInstance] getThemeColorWithName:@"blColor"]; //使用背景图片设置导航条 [self.navigationBar setBackgroundImage:[[ConfigurationTheme shareInstance] getThemeImageName:@"navigationbar_background.png"] forBarMetrics:UIBarMetricsDefault]; //设置导航栏字体颜色和大小 [self.navigationBar setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[[ConfigurationTheme shareInstance] getThemeColorWithName:@"ygColor"],NSForegroundColorAttributeName,[UIFont fontWithName:@"Helvetica" size:21.0],NSFontAttributeName,nil]]; } - (void)viewDidLoad{ [super viewDidLoad]; [self loadThemeImage]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; Kmemory } @end
日间模式和夜间模式: