先来看看效果图
夜间模式.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"];
});
}
总结
实际项目中使用夜间模式时肯定不是那么简单的,但是思路都是一样的(通知+单例或本地数据持久化),只不过是要准备两套主题颜色。