换肤-基础 - (Obj-C)

简单的界面搭建:

两张图片,一个Switch开关,用来切换图片,用来演示换肤功能

换肤-基础 - (Obj-C)_第1张图片
搭建UI.png

示例代码:

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView_1;
@property (weak, nonatomic) IBOutlet UIImageView *imageView_2;
@property (weak, nonatomic) IBOutlet UISwitch *nightSwitch;

@end

@implementation ViewController

// 切换夜间模式
- (IBAction)clickNightSwitch:(UISwitch *)sender {
    
    if (sender.isOn) { // switch开启,代表夜间模式
        self.imageView_1.image = [UIImage imageNamed:@"baby_night"];
        self.imageView_2.image = [UIImage imageNamed:@"girl_night"];
    } else {
        self.imageView_1.image = [UIImage imageNamed:@"baby"];
        self.imageView_2.image = [UIImage imageNamed:@"girl"];
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 默认关闭  日间模式
    [self.nightSwitch setOn:NO];
    
    self.imageView_1.image = [UIImage imageNamed:@"baby"];
    self.imageView_2.image = [UIImage imageNamed:@"girl"];
    
    
}

@end

实现效果图:

换肤-基础 - (Obj-C)_第2张图片
日间.png
换肤-基础 - (Obj-C)_第3张图片
夜间.png

从效果上来看,可以满足基本需求,但是换肤一般针对多界面进行切换,这样只能完成单个界面的换肤,比如再添加一个界面:

换肤-基础 - (Obj-C)_第4张图片
多界面.png

默认的ViewController下,是根据一个Switch开关状态来判断日间/夜间模式的,在ViewController重新设置图片后,影响不到其他视图,因为这里使用的是设置图片,所以需要将设置图片操作做处理,模仿imageNamed方法,根据当前的皮肤来做一个判断

实现方式:创建一个UIImage的分类,创建一个设置图片的方法,通过皮肤的标识来设置对应状态下的图片

Switch在ViewController视图下,所以在ViewController中先声明一个全局变量,用作换肤的标识

// 声明全局变量
bool isNight;

在点击Switch开关的时候去给isNight标识赋值

// 赋值
isNight = sender.isOn;

这里演示的换肤只是设置不同的图片,所以需要的结果是UIImage,所以给UIImage添加一个分类,自定义一个设置图片的方法,因为分类中不好添加属性,所以需要使用到上面的全局变量isNight

+ (UIImage *)JSImageNamed:(NSString *)name{
    
    // 判断当前的皮肤
    if (isNight) { // 夜间
        
        // 夜间图片命名:日间+_night
        name = [NSString stringWithFormat:@"%@_night",name];
    }
    return [UIImage imageNamed:name];
}

在分类中,根据不同皮肤状态设置图片就需要用到isNight这个标识,在声明以外的类下使用全局变量时,先引用这个全局变量

// 引用全局变量
extern bool isNight;

这样外界设置图片的时候,只需要使用自定义的方法即可:

换肤-基础 - (Obj-C)_第5张图片
同步换肤.png

但目前还有一个问题,当第一次切换到夜间模式后,点击到了Page2页面,图片成功切换,切换Page1页面换回日间模式,再进入到Page2页面,仍然显示夜间模式图片

原因是从Page2切换到Page1界面,Page2 控制器并没有释放,再次切换回Page2时并不会调用ViewDidLoad方法,所以需要将代码写在viewWillAppear中

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.imageVIew_3.image = [UIImage JSImageNamed:@"girl"];
}

接下来,需要做本地化处理,记录换肤设置,继续在UIImage分类中封装一个类方法,为了使用更便捷,在做本地化存储的时候,直接将皮肤的标识isNight传递过来,这样就不再需要引用外界的全局变量了,直接在分类中声明一个内部的静态全局部变量标识就可以了

static bool isNight;
+ (void)saveSkinWithNight:(BOOL)night{
    
    // 赋值
    isNight = night;
    
    // 保存当前选择的皮肤
    [[NSUserDefaults standardUserDefaults]setBool:night forKey:@"night"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

在切换皮肤的时候,调用saveSkinWithNight方法,应用启动的时候,获取标识(应用启动的时候获取一次就可以了,所以在Load方法中获取偏好设置中的数据)

// 程序一起动就会执行(只运行一次)
+ (void)load{
    
    isNight = [[NSUserDefaults standardUserDefaults] boolForKey:@"night"];
    
}



在ViewController中还需要同步Switch开关的状态(设置夜间后,退出程序再打开,夜间模式图片状态保存成功,但是开关仍然关闭状态),所以在UIImage分类中提供一个类方法,将内部局部变量isNight标识的结果返回给Switch开关所在的控制器

+ (BOOL)isNight{
    
    return isNight;
}

Switch所在控制器中,在ViewDidLoad中设置Switch状态

// 默认关闭  日间模式
self.nightSwitch.on = [UIImage isNight];

完整示例代码
UIImage+JSImage.h:

.h

@interface UIImage (JSImage)

// 根据当前的皮肤设置图片
+ (UIImage *)JSImageNamed:(NSString *)name;

// 保存皮肤
+ (void)saveSkinWithNight:(BOOL)night;

// 获取当前的皮肤情况,Switch开关状态同步显示
+ (BOOL)isNight;
@end

.m

@implementation UIImage (JSImage)

// 引用全局变量
//extern bool isNight;  标识通过封装的saveSkinWithNight方法传递,不再需要引用外界全局变量,所以设置一个静态全局变量即可
static bool isNight;

// 程序一起动就会执行(只运行一次)
+ (void)load{
    
    isNight = [[NSUserDefaults standardUserDefaults] boolForKey:@"night"];
    
}

+ (UIImage *)JSImageNamed:(NSString *)name{
    
    // 判断当前的皮肤
    if (isNight) { // 夜间
        
        // 夜间图片命名:日间+_night
        name = [NSString stringWithFormat:@"%@_night",name];
        
    }
    
    return [UIImage imageNamed:name];
}

+ (void)saveSkinWithNight:(BOOL)night{
    
    // 赋值
    isNight = night;
    
    // 保存当前选择的皮肤
    [[NSUserDefaults standardUserDefaults]setBool:night forKey:@"night"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

+ (BOOL)isNight{
    
    return isNight;
}
@end

Page1控制器:

#import "ViewController.h"
#import "UIImage+JSImage.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView_1;
@property (weak, nonatomic) IBOutlet UIImageView *imageView_2;
@property (weak, nonatomic) IBOutlet UISwitch *nightSwitch;

@end

@implementation ViewController

// 声明全局变量
//bool isNight;

// 切换夜间模式
- (IBAction)clickNightSwitch:(UISwitch *)sender {
    
    // 保存皮肤
    [UIImage saveSkinWithNight:sender.isOn];
    // 赋值  通过封装的方法已经将标识传递,所以不再需要使用全局变量了
//    isNight = sender.isOn;
    
//    if (sender.isOn) { // switch开启,代表夜间模式
//        self.imageView_1.image = [UIImage imageNamed:@"baby_night"];
//        self.imageView_2.image = [UIImage imageNamed:@"girl_night"];
//    } else {
//        self.imageView_1.image = [UIImage imageNamed:@"baby"];
//        self.imageView_2.image = [UIImage imageNamed:@"girl"];
//    }
    
    // 因为判断已经放在了UIImage分类中,所以这里不再需要判断
    self.imageView_1.image = [UIImage JSImageNamed:@"baby"];
    self.imageView_2.image = [UIImage JSImageNamed:@"girl"];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 默认关闭  日间模式
    self.nightSwitch.on = [UIImage isNight];
    
//    self.imageView_1.image = [UIImage imageNamed:@"baby"];
//    self.imageView_2.image = [UIImage imageNamed:@"girl"];
    
    self.imageView_1.image = [UIImage JSImageNamed:@"baby"];
    self.imageView_2.image = [UIImage JSImageNamed:@"girl"];
    
}

@end

Page2控制器:

#import "NewViewController.h"
#import "UIImage+JSImage.h"

@interface NewViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageVIew_3;

@end

@implementation NewViewController

- (void)viewDidLoad {
    [super viewDidLoad];
//    self.imageVIew_3.image = [UIImage imageNamed:@"girl"];

}
- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.imageVIew_3.image = [UIImage JSImageNamed:@"girl"];
}


@end

你可能感兴趣的:(换肤-基础 - (Obj-C))