业务需求
在实现阅读器项目中我们发现大多数阅读软件都拥有调节应用亮度的slider控件。并且可以区分应用内亮度与系统亮度。即实现应用内“亮度”改变而不影响系统亮度。其实最终实现的代码非常简单,在此我只想分享解决这个问题所用的观察方式和思路。
错误方案
我通过修改系统亮度实现了这一需求。但是!!!这样实现其实有很大的问题。
实现方式
@property (weak, nonatomic) IBOutlet UISlider *SliderBar;
- (void)awakeFromNib
{
[super awakeFromNib];
//给slider控件赋初值
self.SliderBar.value = [UIScreen mainScreen].brightness;
}
- (IBAction)lightSliderChanged:(UISlider *)sender {
//根据slider改变调节系统亮度
[[UIScreen mainScreen] setBrightness:sender.value];
}
问题1
如上代码,我们修改的只是系统亮度,当用户在外面或其他应用调节系统亮度将直接影响我们应用内的亮度。
错误方案——优化
由于“问题1”的发生,我开始思考如何让应用内的亮度独立开来,很容易就想到使用NSUserDefaults记录一个亮度,当应用打开时使用这个亮度来重新设置系统亮度。
相关代码
+ (CGFloat)fetchAppLight{
CGFloat light = [[NSUserDefaults standardUserDefaults] floatForKey:kAppLightKey];
return light;
}
+ (void)modifyAppLight:(CGFloat)light{
[[NSUserDefaults standardUserDefaults] setFloat:light forKey:kAppLightKey];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[UIScreen mainScreen] setBrightness:[LZUtils fetchAppLight]];
// 当应用从后台进入或直接打开时,将亮度修改为上次记录的亮度
}
问题2
当我们这样实现以后会出现这样一个情况,当用户在应用外设置亮度变大,再点击进入应用,亮度会很突兀的变化。导致体验非常差。
观察与思考
由于上述方案无法解决需求,我开始观察其他QQ阅读,追书神器等应用。
发现1:他们都具有和系统亮度分离的功能
思考1:解决方案一定不是通过改变系统亮度来实现
发现2:当不追随系统亮度时只有阅读界面会分离亮度
思考2:仅仅对单个界面处理
发现3:不追随系统亮度时,应用内最大亮度为当前系统亮度。
思考3:应该是使用蒙版遮罩来实现模拟亮度变化!!!
说到这里,我们已经分析出来正确的解决方案了,就是在阅读界面使用遮罩类的方式来模拟亮度变化。
正确方法
使用CALayer对象进行遮罩,注意不要使用view,因为view是具有事件响应的。代码非常简单,如下:
//设置最小透明度50%,否则太暗
#define kMaxTransparent 0.5f
@property (nonatomic, strong) CALayer *brightnessLayer;
初始化一个黑色背景并具有一定透明度的layer
- (CALayer *)brightnessLayer{
if(!_brightnessLayer){
_brightnessLayer = [CALayer layer];
_brightnessLayer.frame = CGRectMake(0, 0, kScreenWidth, kScrrenHeight);
_brightnessLayer.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:kMaxTransparent - [LZUtils fetchAppLight]].CGColor;
}
return _brightnessLayer;
}
在需要遮罩的界面注册一个观察者,当修改亮度时改变遮罩透明度
- (void)viewDidLoad {
[LZNotificationCenter addObserver:self selector:@selector(readViewLightNeedChange:) name:kReadViewLightNeedChangeNofication object:nil];
}
- (void)dealloc {
[LZNotificationCenter removeObserver:self];
}
- (void)readViewLightNeedChange:(NSNotification*)notification{
self.brightnessLayer.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:kMaxTransparent - [LZUtils fetchAppLight]].CGColor;
}
感受
当我们在实现某些需求而又不知道如何下手时,我们不仅要从各个渠道收集资料来帮忙解决问题。更应该通过自己的观察和思考得到解决方案,
希望我的这次经历可以在你未来迷茫的时候帮到你,也希望这个亮度的实现方案可以帮到像我一样之前没找到具体方案的程序猴们。