最近在想怎么做皮肤设置一块的功能,虽然近期内要离职没办法在这个app内实现了,但这个功能以前还没有认真做过,趁在缓冲期好好写一下。经验尚短,有什么不对的还望不吝指教^_^
皮肤设置一般来说有两个大的入口:
1.app提供的换肤入口,一般在设置界面,用户点击可以切换自己喜欢的皮肤
2.app的节假日自动切换成相应节日主题的皮肤,这个和后台有交互,但是应该大体思路差不多,只是配置以及资源是后台提供。
而实现换肤也有两个思路:
1.通过统一配置和通知中心,这个比较容易,但是每个需要改变的界面都需要监听通知,比较麻烦
2.通过方法调配技术,也就是在运行时改变对应的设置方法,好像大部分的开源的换肤框架都是通过这个技术实现的,这个待我钻研一下再写
1.通知方法实现
思路:
将app内需要用到的颜色,图片以及其它在换肤时需要改变的都单独配置出来,确保在使用时都在容器内取,不出现自定义的magic number,用户选择换肤后,只需要改变刷新配置容器内对应的颜色和资源,再发出通知,使有换肤需求的界面接听通知,从而重新加载界面配置。
关键代码:
首先是配置你主题需要的颜色和图片,我的demo的一个主题配置如下。
这里是使用json文件保存配置的,也可以使用plist,都差不多。这样做的好处是,当以后需要扩展时,增加相应的key就可以很方便。
"pintTheme":{
"colors":{
"theme":"#ffa8d2",
"textColor":"#1bf43a",
"labelBgColor":"#000000"
},
"images":{
"firstTabBarIcon":"tabbar_1_pint",
"secondTabBarIcon":"tabbar_2_pint",
"subImage":"subImage_pint"
}
},
上面思路里面说了,构建一个容器,每次和主题相关的数据都通过这个容器去取。这里是创建了一个单例manager,在创建的时候解析json文件,加载一个默认的主题
+(SkinSettingManager *)sharedManager {
static SkinSettingManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[SkinSettingManager alloc]init];
NSString *strPath = [[NSBundle mainBundle] pathForResource:@"skinSettings" ofType:@"json"];
NSData *data = [[NSData alloc]initWithContentsOfFile:strPath];
_colorJson = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
_ColorDic = [NSMutableDictionary dictionary];
NSDictionary *dic = (NSDictionary *)_colorJson[@"pintTheme"][@"colors"];
_imageNameDic = [NSMutableDictionary dictionaryWithDictionary:(NSDictionary *)_colorJson[@"pintTheme"][@"images"]];
[dic enumerateKeysAndObjectsUsingBlock:^(NSString * key, NSString * obj, BOOL * _Nonnull stop) {
[_ColorDic setValue:[UIColor hexStringToColor:obj alpha:1.0] forKey:key];
}];
});
return manager;
}
再就是通过manager取需要的颜色和图片
+ (UIColor *)colorForKey:(NSString *)key {
return [[SkinSettingManager sharedManager]colors][key]?:[UIColor clearColor];
}
+ (UIColor *)themeColor {
return [SkinSettingManager colorForKey:@"theme"];
}
+ (UIColor *)lbbgColor {
return [SkinSettingManager colorForKey:@"labelBgColor"];
}
+ (UIColor *)textColor {
return [SkinSettingManager colorForKey:@"textColor"];
}
当需要改变皮肤设置时,就重新加载manager对应的主题,然后通知各个界面刷新
//某个需要响应皮肤设置的界面
// 接听皮肤改变的通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(skinchange) name:@"SkinChangeNotification" object:nil];
//通知处理方法
- (void)skinchange {
[self.tableView reloadData];
}
需要使用颜色和图片就如下:
cell.backgroundColor = [SkinSettingManager themeColor];
cell.textLabel.textColor = [SkinSettingManager textColor];
cell.imageView.image = [SkinSettingManager subImage];
大概实现就是这样了,过两天再来写方法调配实现的