作為一個iOS搬磚新人,上個月主要在做應用的主題切換。現在有點時間,想分享一下主題切換的方法。
思路:
1、已經加載出來的界面,例如TabBarController中的子控制器。未顯示的Controller上面的變化可以放在
- (void)viewWillAppear:(BOOL)animated
已經顯示的Controller可以用通知改變,如果其上有需要改變的view對象,則也需要用通知改變的view的.m文件的相對應的控件。
2、沒有加載的Controller和view完全随意
准备:
1、将主题名,主题所需要的颜色RGB值,保存到一个文件中
2、主题所用切片命名必须带有@2x或者@3x (我的命名:主题名_切片名@2x.png)
3、打包成Zip,压缩后省了好多空间。也可以根据手机型号把@2x和@3x单独打包,包括所需要的颜色rgb也一起打包(例如我的主色和副色:0,0,0-255.251,1 写在一个info文件中也一起打包在一起)
4、写一个主题单例来保存当前选择主题,其中有方法:
1.返回主色
2.返回副色
3.返回UIImage对象,如果是默认主题用[UIImage imageNamed:imageName];
非默认主题图片用[UIImage imageWithContentsOfFile:]
因为主题所需切片在沙盒下
5、替换调所有需要变化图片的地方以及颜色需要变化的地方,全用以上写的方法替换
过程:
1、把打包好的主题文件上传到服务器。
2、下载到沙盒中
3、解压zip(这里我用的是ZipArchive)
4、读取所写的保存颜色信息的文件,并保存到写的一个单例对象中
5、删除zip包
6、如果准备工作全部完成,就可以发送通知了!
小心的坑:
1、切片名一定要带@2x或者@3x可以分开,可以放一起,分开则判断客户端需要2x还是3x下载对应图片包
2、navigationBar上面控件更换可以会遇到问题,我用的是UIButton创建 BarItem。(返回箭头本人没有更换成功,所以改用默认的返回箭头,单纯替换颜色,如有好的方法请指点在下)
写了一个工具来提取包中的所有切片:
#import <Foundation/Foundation.h>
/**
* 复制所有PNG文件,并改名,分开为2x 3x
*
* @param sourse 原路径
* @param path 目的路径
*/
void copyPNG(NSString *sourse,NSString *path);
void copyAllPng(NSString *sourse,NSString *path);
/**
* 压缩主题包
*
* @param path 主题包路径
*/
void zipThemePackage(NSString *path);
int main(int argc, const char * argv[]) {
@autoreleasepool {
//原始路径 Images.xcassets
NSString *path = @"/Users/apple/Desktop/xxx//Images.xcassets/测试主题";
//目标地址 目录下 2x 3x 两个文件夹(没有会自动创建)
NSString *destPath = @"/Users/apple/Desktop/主题文件/yb/";
// 拷贝并分开
copyPNG(path, destPath);
//拷贝不分开
copyAllPng(path, destPath);
}
return 0;
}
void copyPNG(NSString *sourse,NSString *path){
// NSString *appDocDir = [[[[NSFileManager defaultManager] URLsForDirectory: NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] relativePath];
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *contentOfFolder = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:sourse error:NULL];
NSString *themeName = [[path componentsSeparatedByString:@"/"] lastObject];
int count = 0;
for (NSString *aPath in contentOfFolder) {
NSString * fullPath = [sourse stringByAppendingPathComponent:aPath];
BOOL isDir = NO;
if ([fm fileExistsAtPath:fullPath isDirectory:&isDir])
{
NSArray *contentOfFolder = [fm contentsOfDirectoryAtPath:fullPath error:NULL];
for (NSString *aPath in contentOfFolder) {
NSString * fullPath2 = [fullPath stringByAppendingPathComponent:aPath];
if ([fm fileExistsAtPath:fullPath2 isDirectory:&isDir])
{
if (isDir == NO &&([[fullPath2 pathExtension] isEqualToString:@"png"])) {
//2x 3x 标志文件名
NSArray *arr = [fullPath2 componentsSeparatedByString:@"@"];
NSString *flag = [arr lastObject];
NSMutableString *newFileName = [aPath mutableCopy];
if ([flag isEqualToString:@"2x.png"]) {
[newFileName deleteCharactersInRange:[aPath rangeOfString:@"@2x"]];
if (![fm fileExistsAtPath:[NSString stringWithFormat:@"%@/2x/%@",path,themeName]]) {
[fm createDirectoryAtPath:[NSString stringWithFormat:@"%@/2x/%@",path,themeName]withIntermediateDirectories:YES attributes:nil error:nil];
}
NSString *newPath = [NSString stringWithFormat:@"%@/2x/%@/%@",path,themeName,newFileName];
[fm copyItemAtPath:fullPath2 toPath:newPath error:nil];
NSLog(@"file:%@",newFileName);
}else if ([flag isEqualToString:@"3x.png"]){
if (![fm fileExistsAtPath:[NSString stringWithFormat:@"%@/3x/%@",path,themeName]]) {
[fm createDirectoryAtPath:[NSString stringWithFormat:@"%@/3x/%@",path,themeName]withIntermediateDirectories:YES attributes:nil error:nil];
}
// [newFileName deleteCharactersInRange:[aPath rangeOfString:@"@3x"]];
NSString *newPath = [NSString stringWithFormat:@"%@/3x/%@/%@",path,themeName,newFileName];
[fm copyItemAtPath:fullPath2 toPath:newPath error:nil];
NSLog(@"file:%@",newFileName);
count ++;
}
}
}
}
}
}
NSLog(@"文件个数:%d",count);
}
void copyAllPng(NSString *sourse,NSString *path){
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *contentOfFolder = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:sourse error:NULL];
NSString *themeName = [[path componentsSeparatedByString:@"/"] lastObject];
int count = 0;
for (NSString *aPath in contentOfFolder) {
NSString * fullPath = [sourse stringByAppendingPathComponent:aPath];
BOOL isDir = NO;
if ([fm fileExistsAtPath:fullPath isDirectory:&isDir])
{
NSArray *contentOfFolder = [fm contentsOfDirectoryAtPath:fullPath error:NULL];
for (NSString *aPath in contentOfFolder) {
NSString * fullPath2 = [fullPath stringByAppendingPathComponent:aPath];
if ([fm fileExistsAtPath:fullPath2 isDirectory:&isDir])
{
if (isDir == NO &&([[fullPath2 pathExtension] isEqualToString:@"png"])) {
//2x 3x 标志文件名
NSArray *arr = [fullPath2 componentsSeparatedByString:@"@"];
NSString *flag = [arr lastObject];
NSMutableString *newFileName = [aPath mutableCopy];
NSString *newPath = [NSString stringWithFormat:@"%@/%@",path,newFileName];
[fm copyItemAtPath:fullPath2 toPath:newPath error:nil];
NSLog(@"file:%@",newFileName);
}
}
}
}
}
NSLog(@"文件个数:%d",count);
}
我写的主题工具类:
#import "ThemeTool.h"
#import "SSZipArchive.h"
@implementation ThemeTool
+ (NSString *)themeWithImageName:(NSString *)imageName{
ThemeTool *theme = [ThemeTool mainTheme];
//默认返回名字
if ([theme.currentTheme isEqualToString:@"default"]) {
return imageName;
}else{
//非默认返回主题名称_切片名
return [NSString stringWithFormat:@"%@_%@",theme.currentTheme,imageName];
}
}
+ (UIImage *)themeImageWithImageName:(NSString *)imageName{
ThemeTool *theme = [ThemeTool mainTheme];
if ([theme.currentTheme isEqualToString:@"default"]) {
return [UIImage imageNamed:imageName];
}else{
//压缩包解压到library 文件名(主题名)/主题名_图片名.png
return [UIImage imageWithContentsOfFile:[DOCUMENT_PATH stringByAppendingPathComponent:[NSString stringWithFormat:@"themes/%@/%@_%@.png",theme.currentTheme,theme.currentTheme,imageName]]];
}
}
+(BOOL)archiveThemeZipByZipName:(NSString *)name{
NSString *zippath = [NSString stringWithFormat:@"%@/themes/%@.zip",DOCUMENT_PATH,name];
NSString *destination = [NSString stringWithFormat:@"%@/themes/",DOCUMENT_PATH];
NSLog(@"%@",DOCUMENT_PATH);
if ([SSZipArchive unzipFileAtPath:zippath toDestination:destination]) {
NSLog(@"主题包解压成功");
NSString *path = [NSString stringWithFormat:@"%@/themes/%@/info",DOCUMENT_PATH,name];
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSArray *arr = [str componentsSeparatedByString:@"-"];
if (arr.count == 2) {
// NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"themes" ofType:@"plist"];
// NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
NSUserDefaults *usdefu = [NSUserDefaults standardUserDefaults];
[usdefu setObject:arr[0] forKey:[NSString stringWithFormat:@"%@_color",name]];
[usdefu setObject:arr[1] forKey:[NSString stringWithFormat:@"%@_vicecolor",name]];
[usdefu synchronize];
NSLog(@"保存颜色成功");
dispatch_async(dispatch_get_main_queue(), ^{
// 更UI
[ZYNotificationCenter postNotificationName:@"downloadthemesuccess" object:nil];
});
if ([[NSFileManager defaultManager] removeItemAtPath:zippath error:nil]) {
NSLog(@"删除压缩包成功");
}else{
NSLog(@"删除压缩包失败");
}
}
return YES;
}else{
NSLog(@"主题包解压失败!!!");
return NO;
}
}
+ (UIColor *)themeColor{
ThemeTool *theme = [ThemeTool mainTheme];
NSArray *rgb = [theme.currentMainColor componentsSeparatedByString:@","];
if (rgb.count == 3) {
return ZYRGBColor([rgb[0] floatValue], [rgb[1] floatValue], [rgb[2] floatValue]);
}
return mainColor;
}
+ (UIColor *)themeViceColor{
ThemeTool *theme = [ThemeTool mainTheme];
NSArray *rgb = [theme.currentViceColor componentsSeparatedByString:@","];
if (rgb.count == 3) {
return ZYRGBColor([rgb[0] floatValue], [rgb[1] floatValue], [rgb[2] floatValue]);
}
return [UIColor whiteColor];
}
+ (UIColor *)themeViceColorWithAlph:(float)alph{
ThemeTool *theme = [ThemeTool mainTheme];
NSArray *rgb = [theme.currentViceColor componentsSeparatedByString:@","];
if (rgb.count == 3) {
return ZYARGBColor([rgb[0] floatValue], [rgb[1] floatValue], [rgb[2] floatValue],alph);
}
return [UIColor whiteColor];
}
-(NSString *)libraryPath{
return [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];
}
+(void)changeThemeName:(NSString *)name color:(NSString *)color vicecolor:(NSString *)vicecolor{
ThemeTool *theme = [ThemeTool mainTheme];
theme.currentTheme = name;
theme.currentMainColor = color;
theme.currentViceColor = vicecolor;
}
+ (instancetype)mainTheme{
static ThemeTool *theme = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
theme = [[ThemeTool alloc] init];
});
return theme;
}
- (NSString *)currentTheme{
if (!_currentTheme) {
NSDictionary *data = [NSBundle mainBundle].infoDictionary;
NSDictionary *themeDict = data[@"Theme"];
if (![[NSUserDefaults standardUserDefaults] valueForKey:@"cname"]) {
[[NSUserDefaults standardUserDefaults] setObject:themeDict[@"color"] forKey:@"default_color"];
[[NSUserDefaults standardUserDefaults] setObject:themeDict[@"vicecolor"] forKey:@"default_vicecolor"];
_currentTheme = themeDict[@"name"];
}else{
_currentTheme =[[NSUserDefaults standardUserDefaults] valueForKey:@"cname"];
}
}
return _currentTheme;
}
- (NSString *)currentMainColor{
if (! _currentMainColor) {
NSDictionary *data = [NSBundle mainBundle].infoDictionary;
NSDictionary *themeDict = data[@"Theme"];
if (![[NSUserDefaults standardUserDefaults] valueForKey:@"cname"]) {
_currentMainColor = themeDict[@"color"];
}else{
NSString *name = [[NSUserDefaults standardUserDefaults] valueForKey:@"cname"];
_currentMainColor = [[NSUserDefaults standardUserDefaults] valueForKey:[NSString stringWithFormat:@"%@_color",name]];
}
}
return _currentMainColor;
}
- (NSString *)currentViceColor{
if (!_currentViceColor) {
NSDictionary *data = [NSBundle mainBundle].infoDictionary;
NSDictionary *themeDict = data[@"Theme"];
if (![[NSUserDefaults standardUserDefaults] valueForKey:@"cname"]) {
_currentViceColor = themeDict[@"vicecolor"];
}else{
NSString *name = [[NSUserDefaults standardUserDefaults] valueForKey:@"cname"];
_currentViceColor = [[NSUserDefaults standardUserDefaults] valueForKey:[NSString stringWithFormat:@"%@_vicecolor",name]];
}
}
return _currentViceColor;
}
+ (void)saveCurrentTheme{
ThemeTool *theme = [ThemeTool mainTheme];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:theme.currentTheme forKey:@"cname"];
// NSLog(@"%@",data);
}
本人愚钝,有错误或者有好的方法,欢迎指教和讨论。