iOS 夜间模式

1,843 阅读2分钟
原文链接: www.jianshu.com

先来看看效果图


夜间模式.gif

思路

切换夜间/白天模式时,发送通知给所有ViewController,让它们切换到相应的主题。但是,由于未初始化的ViewController无法接收通知,所以,需要将主题模式保存下来(单例或数据持久化),然后在ViewController viewDidLoad时根据保存的主题模式展示相应的主题模式。当然,还需要一个默认主题模式。

开始实现夜间模式

1、首先建一个管理模式主题的单例管理类: ThemeManager

.h文件

#import 
static NSString * const kThemeManagerDidChangeThemeNotification = @"kThemeManagerDidChangeThemeNotification";
@interface ThemeManager : NSObject
@property (readonly, copy, nonatomic) NSString *currentThemeName;
+ (instancetype)defaultManager;
- (void)setThemeName:(NSString *)themeName;
@end

.m文件

#import "ThemeManager.h"
#import 

@interface ThemeManager ()
@property (readwrite, copy, nonatomic) NSString * currentThemeName;
@end
@implementation ThemeManager
+ (instancetype)defaultManager {
    static ThemeManager *DefaultManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        DefaultManager = [[ThemeManager alloc] init];
    });
    return DefaultManager;
}
- (instancetype)init {
    self = [super init];
    if (self) {
        self.currentThemeName = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppTheme"];
        if (!self.currentThemeName) {
            self.currentThemeName = @"Default";
        }
    }
    return self;
}
- (void)setThemeName:(NSString *)themeName {
    self.currentThemeName = themeName;
    [[NSUserDefaults standardUserDefaults] setObject:themeName forKey:@"AppTheme"];
    [[NSNotificationCenter defaultCenter] postNotificationName:kThemeManagerDidChangeThemeNotification object:nil];
    [UIView transitionWithView:[UIApplication sharedApplication].keyWindow duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{

    } completion:nil];
}
@end

2、再创建一个BaseViewControll(其余ViewController继承于它)

#import "BaseViewController.h"
#import "ThemeManager.h"
@interface BaseViewController ()

@end

@implementation BaseViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applyTheme) name:kThemeManagerDidChangeThemeNotification object:nil];
}
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.view.backgroundColor = [[ThemeManager defaultManager].currentThemeName isEqualToString:@"Dark"] ? [UIColor darkGrayColor] : [UIColor whiteColor];
}
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)applyTheme {
    if ([[ThemeManager defaultManager].currentThemeName isEqualToString:@"Dark"]) {
        self.view.backgroundColor = [UIColor darkGrayColor];
    } else {
        self.view.backgroundColor = [UIColor whiteColor];
    }

}

3、除了此之外还需要
BaseNavigationController,BaseTableViewController,BaseTableView,BaseTableViewCell,BaseLabel,BaseImageView,BaseButton,等等...

实现原理与BaseViewController相似

4、最后使用switch来控制白天/夜间模式

#import "MJViewController.h"
#import "ThemeManager.h"
#import "MJTableCell.h"
@interface MJViewController ()
@property (weak, nonatomic) IBOutlet UISwitch *nightModeSwitch;
@property (weak, nonatomic) IBOutlet UITableView *tableView;

@end

@implementation MJViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    self.nightModeSwitch.on = [[ThemeManager defaultManager].currentThemeName isEqualToString:@"Dark"];
    [self initNavigationItems];
    [self.tableView registerNib:[UINib nibWithNibName:@"MJTableCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"1"];
    self.tableView.rowHeight = 70;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MJTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"1" forIndexPath:indexPath];
    cell.mj_titleLaebl.text = [NSString stringWithFormat:@"文本%ld",indexPath.row];
    [cell.mj_button setTitle:[NSString stringWithFormat:@"按钮%ld",indexPath.row] forState:UIControlStateNormal];
    return cell;
}
- (void)initNavigationItems {
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"前进" style:UIBarButtonItemStylePlain target:self action:nil];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"后退" style:UIBarButtonItemStylePlain target:self action:nil];
    self.navigationItem.title = @"标题";
}
- (IBAction)nightModeSwitchDidChange:(id)sender {
    // 延时应用主题以避免开关动画卡顿。
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [[ThemeManager defaultManager] setThemeName:self.nightModeSwitch.on ? @"Dark" : @"Default"];
    });

}

总结

实际项目中使用夜间模式时肯定不是那么简单的,但是思路都是一样的(通知+单例或本地数据持久化),只不过是要准备两套主题颜色。

详情参照github.com/ymjeroz/Nig…