iOS應用主題切換

作為一個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);

}

本人愚钝,有错误或者有好的方法,欢迎指教和讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值