iOS-夜间模式(换肤设置)

作者: smile丽语 | 来源:发表于2017-04-24 16:26 被阅读3380次

iOS 开发中有时候会有夜间模式(换肤设置)的需求, 其实主要是更改相关颜色操作!

思路:每次切换夜间/白天模式时,都会发出通知给所有ViewController,让它们切换到相应的主题。

  1. 创建一个管理模式主题的单例管理类ThemeManage
  1. 封装好需要做夜间模式变色处理的控件扩展:UIView (ThemeChange), UINavigationBar (ThemeChange), UITabBar (ThemeChange), UILabel (ThemeChange), UIButton (ThemeChange)
  2. 在 AppDelegate里先获取夜间模式状态, 根控制器里先设置tabBar 及 子控制器里navigationBar的夜间模式状态
  3. 添加控制白天/黑夜模式item,发通知切换相对应i模式及image
  4. 添加相关控件是否黑夜模式下已更换字色和背景色

一. 创建一个管理模式主题的单例管理类ThemeManage

ThemeManage.h 文件:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface ThemeManage : NSObject

#pragma mark - 颜色属性
@property(nonatomic, retain) UIColor *bgColor;
@property(nonatomic, retain) UIColor *color1;
@property(nonatomic, retain) UIColor *color2;
@property(nonatomic, retain) UIColor *textColor;
@property(nonatomic, retain) UIColor *textColorGray;
@property(nonatomic, retain) UIColor *navBarColor;
@property(nonatomic, retain) UIColor *colorClear;

#pragma mark -

// 是否是夜间 YES表示夜间, NO为正常
@property(nonatomic, assign) BOOL isNight;

/**
 * 模式管理单例
 */
+ (ThemeManage *)shareThemeManage;

@end

ThemeManage. m 文件

#import "ThemeManage.h"

static ThemeManage *themeManage; // 单例


@implementation ThemeManage

#pragma mark - 单例的初始化

+ (ThemeManage *)shareThemeManage {
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        themeManage = [[ThemeManage alloc] init];
    });
    return themeManage;
}

#pragma mark 重写isNight的set方法

- (void)setIsNight:(BOOL)isNight {
    
    _isNight = isNight;
    
    if (self.isNight) { // 夜间模式改变相关颜色
        
        self.bgColor = [UIColor colorWithRed:0.06 green:0.08 blue:0.1 alpha:1];
        self.textColor = [UIColor whiteColor];
        self.color1 = [UIColor colorWithRed:0.08 green:0.11 blue:0.13 alpha:1];
        self.navBarColor = [UIColor whiteColor];
        self.color2 = [UIColor colorWithRed:0.2 green:0.31 blue:0.43 alpha:1];
        self.textColorGray = [UIColor whiteColor];
    } else{
        
        self.bgColor = [UIColor whiteColor];
        self.textColor = [UIColor blackColor];
        self.color1 = [UIColor colorWithRed:0.06 green:0.25 blue:0.48 alpha:1];
        self.navBarColor = [UIColor colorWithRed:0.31 green:0.73 blue:0.58 alpha:1];
        self.color2 = [UIColor colorWithRed:0.57 green:0.66 blue:0.77 alpha:1];
        self.textColorGray = [UIColor grayColor];
    }
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        self.colorClear = [UIColor clearColor];
    });
}

@end

二. 封装好需要做夜间模式变色处理的控件扩展

一般需要UIView (ThemeChange), UINavigationBar (ThemeChange), UITabBar (ThemeChange), UILabel (ThemeChange), UIButton (ThemeChange);这里拿 UIView 做例子:

#import <UIKit/UIKit.h>

/**
 * 颜色状态枚举值 颜色的定义(一个代表一套)
 */
typedef NS_ENUM(NSInteger, UIViewColorType) {

    UIViewColorTypeNormal, // 白天白色, 夜间黑色
    UIViewColorType1, // 白天蓝色, 夜间深灰
    UIViewColorType2, // 白天浅蓝, 夜间浅蓝
    UIViewColorTypeClear // 透明状态
};

@interface UIView (ThemeChange)

// 定义颜色类型的属性, NSNumber类型
@property(nonatomic, assign) id type;

// 消息中心开始监听
- (void)startMonitor;
// 改变颜色的方法
- (void)changeColor;
// 设置颜色类型和对应颜色
- (void)NightWithType:(UIViewColorType)type;

// 设置字体颜色的方法
- (void)initTextColor;

@end
#import "UIView+ThemeChange.h"
#import "ThemeManage.h"
// 添加runtime头文件
#import <objc/runtime.h>

@implementation UIView (ThemeChange)

#pragma mark - 添加type的set,get方法

- (void)setType:(id)type {
    
    objc_setAssociatedObject(self, @selector(type), type, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (id)type {
    return objc_getAssociatedObject(self, @selector(type));
}

#pragma mark - 开始监听

- (void)startMonitor {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeColor) name:@"changeColor" object:nil];
}

#pragma mark - 改变颜色

- (void)changeColor {
    // type为NSNumber型, 变为NSInteger
    switch ([self.type integerValue]) {
        case UIViewColorTypeNormal:
            self.backgroundColor = [ThemeManage shareThemeManage].bgColor;
            break;
        case UIViewColorType1:
            self.backgroundColor = [ThemeManage shareThemeManage].color1;
            break;
        case UIViewColorType2:
            self.backgroundColor = [ThemeManage shareThemeManage].color2;
            break;
        case UIViewColorTypeClear:
            self.backgroundColor = [ThemeManage shareThemeManage].colorClear;
            break;
            
        default:
            break;
    }
    
}

#pragma mark - 设置颜色类型和对应颜色

- (void)NightWithType:(UIViewColorType)type {
    
    self.type = [NSNumber numberWithInteger:type];
    [self changeColor];
    [self startMonitor];
    
    // 调用设置字体颜色的方法
    [self initTextColor];
}

#pragma mark - 改变字体颜色的方法, 空方法, 可以在子类中重写这个方法来改变颜色(例如:Label)

- (void)initTextColor {
    
}

@end

三. 在 AppDelegate里先获取夜间模式状态, 根控制器里先设置tabBar 及 子控制器里navigationBar的夜间模式状态

#import "ThemeManage.h"
#import "UIView+ThemeChange.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    // 获取夜间模式状态
    [ThemeManage shareThemeManage].isNight = [[NSUserDefaults standardUserDefaults] boolForKey:@"night"];
    
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    
    RootViewController *rootVc = [[RootViewController alloc] init];
    self.window.rootViewController = rootVc;
    
    return YES;
}

RootViewController.m 文件:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self.view NightWithType:UIViewColorTypeNormal];
    
    HomeViewController *vc = [[HomeViewController alloc] init];
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
    // 设置navigationBar的夜间模式状态
    [nav.navigationBar NightWithType:UIViewColorTypeNormal];
    vc.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"首页" image:[UIImage imageNamed:@"home"] tag:10];
    
    SchemaViewController *secondVC = [[SchemaViewController alloc] init];
    UINavigationController *nav1 = [[UINavigationController alloc] initWithRootViewController:secondVC];
    // 设置navigationBar的夜间模式状态
    [nav1.navigationBar NightWithType:UIViewColorTypeNormal];
    secondVC.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"菜单" image:[UIImage imageNamed:@"schema"] tag:11];
    
    [self.tabBar NightWithType:UIViewColorTypeNormal];
    self.viewControllers = @[nav, nav1];
    self.tabBar.translucent = NO;
    [[UINavigationBar appearance] setTranslucent:NO];
}

四. 添加控制白天/黑夜模式item,发通知切换相对应i模式及image.

#import "ThemeManage.h"
#import "UIView+ThemeChange.h"
    [self.view NightWithType:UIViewColorTypeNormal];
    
    UIImage *barButtonImage = [ThemeManage shareThemeManage].isNight ? [UIImage imageNamed:@"night"] : [UIImage imageNamed:@"day"];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:barButtonImage style:UIBarButtonItemStylePlain target:self action:@selector(rightBarBtnAction:)];
#pragma mark  - Action点击动作事件

// 切换夜间模式
- (void)rightBarBtnAction:(UIBarButtonItem *)barButton {
    
    [ThemeManage shareThemeManage].isNight = ![ThemeManage shareThemeManage].isNight;
    [[NSNotificationCenter defaultCenter] postNotificationName:@"changeColor" object:nil];
    [[NSUserDefaults standardUserDefaults] setBool:[ThemeManage shareThemeManage].isNight forKey:@"night"];
    UIImage *barBtnImage = [ThemeManage shareThemeManage].isNight ? [UIImage imageNamed:@"night"] : [UIImage imageNamed:@"day"];
    [barButton setImage:barBtnImage];
}

发了通知不要忘记移除监听

- (void)dealloc {
    // 移除监听
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

五. 添加相关控件是否黑夜模式下已更换字色和背景色

#import "UILabel+ThemeChange.h"
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 200, 40)];
    label.text = @"测试看看字色及背景色";
    [label NightWithType:UIViewColorTypeNormal];
    [label NightTextType:LabelColorGray];
    [self.view addSubview:label];

这时候测试下, 看下效果:

夜间模式.gif

Demo 下载请移步: 夜间模式(换肤设置)

相关文章

  • iOS-夜间模式(换肤设置)

    iOS 开发中有时候会有夜间模式(换肤设置)的需求, 其实主要是更改相关颜色操作! 思路:每次切换夜间/白天模式...

  • iOS 换肤-黑夜、黑暗、夜间模式

    iOS 开发中有时候会有夜间模式(换肤设置)的需求, 其实主要是更改相关颜色操作! 思路:每次切换夜间/白天模式...

  • iOS关于换肤和夜间模式的一些思考

    iOS关于换肤和夜间模式的一些思考 iOS关于换肤和夜间模式的一些思考

  • 夜间模式实践

    现状 夜间模式是android换肤的一种,关于换肤的相关知识总结,大家可以参考这篇文章Android换肤技术总结-...

  • Android 夜间模式 换肤

    本文为原创,转载请注明出处。文章标题为夜间模式,其实我这里想说的不是什么夜间模式,而是Skin库,有了Skin库,...

  • android 皮肤换肤

    很多app都会设置夜间和白天的模式,而实现换肤的方法有很多种,有的必须重新进入才能有效果,有的是动态的,设置了就马...

  • Android一键换肤功能实现

    市面上对数的App都提供换肤功能,这里暂且不讲白天和夜间模式 下图是网易云音乐的换肤功能 换肤其实就是替换资源(文...

  • android 夜间模式(换肤)总结

    一、android 平台常见的换肤方案. Android 平台常见的额换肤方式总结起来有如下三种: 1.设置set...

  • iOS 换肤方案

    iOS换肤需求 1、由于iOS13发布的夜间模式,市场上较大型的APP都以积极的适配了夜间模式,因此我们的APP也...

  • 换肤方式实现日/夜间模式

    一、夜间模式的实现方式夜间模式的实现方式有两种,一种是本地替换,一种是用动态换肤的方案替换。但是两中方案的思想大致...

网友评论

  • 影痕残碎:为什么是在ViewController里移除啊?不是应该在View里移除吗?通知不是添加在View里的嘛?
  • 影痕残碎:有一点不明白,移除监听为什么放在ViewController里?不是View在监听吗?不是应该在View里移除吗?
    smile丽语:@影痕残碎 看第四点,我移除了!
    影痕残碎:为什么你的View添加了监听,不移除也没事
  • 阿拉斯加的狗:6
    smile丽语:@阿拉斯加的狗 谢谢
  • GF极客天涯:发一份demo呗,528096212@qq.com谢谢了!
    GF极客天涯:@smile丽语 好,谢谢
    smile丽语:@GF极客天涯 在 GitHub上下载吧
  • 小小志伟:能发下源码 2213139162@qq.com
    小小志伟:@smile丽语 嗯 好的
    smile丽语:@小小志伟 为啥不看完文章呢?最下面就是下载链接啊:sweat:
  • Xir_Guitar:给我也发个,行吗?
    root@uyhacker.com
    谢啦
    smile丽语:@Xir_Guitar 恩恩好的 已发邮箱
    Xir_Guitar:@smile丽语 很抱歉了,我是看到了地址,但是我们这边上不去git,而且科学上网管的很严,所以..
    smile丽语:@Xir_Guitar 有下载链接啊, 我放在文章最后了, 你都木有看完:sweat:
  • __silhouette:你好,请问这里面runtime的作用是什么?
  • TryToFlyHigher:亲您好 向您请教一个问题 请问重写isNight属性的setter方法中
    " static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    self.colorClear = [UIColor clearColor];
    });"
    的作用是什么啊? 这个clearColor是什么空间元素的颜色呢
  • 铮铮钱钱:分享下代码:smile:1084282875@qq.com谢谢
    铮铮钱钱:@smile丽语 能否加下QQ
    铮铮钱钱:@smile丽语 好的,谢谢
    smile丽语:@铮铮钱钱 demo链接我放上去了,看上面下载:smile:
  • liangZhen:楼主写的很不错,最近研究了网易新闻客户端的夜间模式发现新闻的图片在夜间模式下也会变暗。本人水平有限暂时没有想出实现思路,不知道楼主有没有好的实现思路?
    smile丽语:@liangZhen 以前还没注意这块,你可以更换图片这块考虑一下呢
  • 1d9c03a615a3:可否看看你的源码,学习一下709847410@qq.com
    1d9c03a615a3:@smile丽语 好的,谢了
    smile丽语:@仰望星空的摆渡人 已发邮箱
  • 黑科技百科:您好!求Demo一份,谢谢了!邮箱:763279002@qq.com
    smile丽语:@时光在变人不变 已发邮箱,客气了
  • 十萬個想知道:我也想要一份大大 908066695@qq.com:flushed:
    smile丽语:@十萬個想知道 恩已发
  • 霍素杰:求demo,1402115549@qq.com
    smile丽语:@霍素杰 发了
  • 霍素杰:求demo,1402115449@qq.com
    smile丽语:@霍素杰 已发
  • 霍素杰:求DEMO
  • d0afe70ea42f:谢谢喽,麻烦给我也发一份哟,邮箱:1473599024@qq.com
    smile丽语:@d0afe70ea42f 对你有帮助就好:smile:
    d0afe70ea42f:@smile丽语 多谢,正在看叻,看了一个小时才理清头绪叻,哈哈,还是学习了哈
    smile丽语:@d0afe70ea42f 客气了,已发邮箱
  • 京北磊哥:写的太好了! 楼主 俺也想求一份demo ,方便给吗?
    qq邮箱:944138353@qq.com
    京北磊哥:@smile丽语 谢谢楼主!!:pray: :pray: :pray:
    smile丽语:@取个名字太难了哭了 谢谢夸奖, demo 已发邮箱
  • Nicole__Zhang:大神,求Demo啊,非常非常感谢! 1208657369@qq.com
    smile丽语:@小蜗牛的梦想 客气了,demo 已发邮箱
  • MrBeave丶彬彬:1193599409@qq.com 求一份 谢谢
    smile丽语:@MrBeave丶彬彬 客气了,demo 已发邮箱
  • 未来的路就在那:给我发一份demo,谢谢分享,邮箱:601204714@qq.com
    smile丽语:@未来的路就在那 已发送邮箱
  • seasonZhu:大神,来三份demo,zhujilong1987@163.com
    seasonZhu:@smile丽语 感谢
    smile丽语:@seasonZhu 休假归来:smile: ,已发邮件
  • yyggzc521:楼主 求一份demo 谢谢啦 453645620@qq.com
    smile丽语:@yyggzc521 客气了,已发邮件
  • 堕落小怪兽:大神,来一份饺子,蟹蟹。407673005@qq.com
    smile丽语:@Jiang_2017 客气了,已发邮件
  • 天空总是很晴朗:楼主大大,demo...1192484280@qq.com...蟹蟹
    smile丽语:@justboy 客气了,已发邮件
  • 是因_也是果:求demo一份大神 545031823@qq.com谢谢啦
    smile丽语:@青春信仰者 客气了,已发邮件
  • 那一处风景ljz:求demo一份大神 1721311017@qq.com谢谢啦
    smile丽语:@那一处风景ljz 客气了,已发邮件
  • CC_blus:求一份demo学习,谢谢了,:blush:840073059@qq.com
    smile丽语:@程称称 客气了,已发邮件
  • xieyinghao:求大神提供一份demo学习。方便的话静侯佳音:2596211472@qq.com
    smile丽语:@xieyinghao 客气了:smile:
    xieyinghao:@smile丽语 感谢感谢!
  • 妖精的菩萨:写的很好,简单易懂!求一份demo哇!
    948890138@qq.com
    smile丽语:@smile丽语 客气了,已发邮件
  • 鹰眼米霍克:好东西 没准以后会用到
    smile丽语:谢谢:smile:
  • 陪伴最长情:犀利啊,学习了,自己按照你的写了个demo!
    smile丽语:@陪伴最长情 咱俩这点还挺像,所以我就闲的时候先写点 demo等需要用到的这块功能时候就再用:smile:
    陪伴最长情:谢啦!因为我太了解我自己,如果我要你把demo发我邮箱,也许我也就是看看,也许有一天我用的到的时候,我还要想想我到底有没有见过类似的!所以干脆就自己写一个,这样自己印象深刻一些,自己也懂里面的逻辑,为什么要这样写,这样写的思路!这样的话自己会更加的清晰和清楚!
    smile丽语:@陪伴最长情 不错:+1:
  • 贱精先玍丶:赞一个, 顺便说说, 楼主不放demo就好像是留图不留种的样子,:wink: 那就发我邮箱吧, ldcz6614@sina.cn 谢谢~
    smile丽语:哎,客气了, 已发邮箱
  • iOS_渔翁:大神,求Demo啊,非常非常感谢!------hbk1023@foxmail.com
    smile丽语:@iOS_渔翁 客气了, 已发邮件, 谢谢打赏!
  • MarAlves:大神求一份demo,maralves@163.com ,谢谢啦
    smile丽语:@林同 休假归来:smile: ,已发邮件
    a8304ea8f57e:1076860592@qq.com
    能发个Demo吗,谢谢了
    smile丽语:@MarAlves 客气了, 已发邮件
  • iOS_渔翁:有Demo吗? hbk1023@foxmail.com,非常感谢!!:stuck_out_tongue_winking_eye: :stuck_out_tongue_winking_eye: :stuck_out_tongue_winking_eye:
  • saman0:楼主求1975566197@qq.com
    smile丽语:@saman0 客气了,开发群供大家在里面交流, 可以在群里互相讨论学习
    如果需要可以加群:619216102
    saman0:@smile丽语 谢谢了,我已经进群了
  • Alan_yo:楼主,求一份,384884453@qq.com 谢谢
    smile丽语:@Alan_yo 客气了,已发邮件
  • 韩马小执:1095551003@qq.com 楼主给个dome看看吧
    韩马小执:@smile丽语 Many thanks!
    smile丽语:@韩马小执 客气了已发邮件
  • NateLam:求demo, 谢谢! 497115022@qq.com
    smile丽语:@NateLam 客气了,已发邮件
  • HanOBa:565868472@qq.com
    好人一生平安
    smile丽语:@HanOBa 客气了
    HanOBa:已收到。3Q
    smile丽语:@HanOBa 这....,吓到了我了
  • CnnJmh:顺道求大神demo,谢谢咯。
    159317785@.com
    smile丽语:你的邮箱不对吧,后缀?
  • DarrenZhanghaha:求一份,305178026@qq.com 谢谢啦
    smile丽语:客气了,已发邮件
  • 一只霸天犬v:楼主 求一份demo 谢谢啦 1026582705@qq.com
    smile丽语:@小仙儿v 客气了, 已发邮箱
  • A訫飛Flyme:可以把Demo放到github,贴个链接
    smile丽语:@Magic昕飞 就是小 Demo, 自己空闲整理后期自己使用的,不是很好的 demo, 所以就不放了我觉得
  • Clark_new:亲,给个demo地址呗
    smile丽语:@Clark_new 客气了,已发邮箱
    Clark_new:@smile丽语 xiannanmeng0303@sina.com 谢啦 嘿嘿
    smile丽语:还木有整理demo下载地址,我发你邮箱也行
  • Yokihr:你好,有demo可以提供么?
  • duJing:好厉害呀
    smile丽语:@duJing 谢谢

本文标题:iOS-夜间模式(换肤设置)

本文链接:https://www.haomeiwen.com/subject/qiidzttx.html