一直看到好多的app都有状态栏随视图的滑动,透明度动态改变,跳转入其它视图则正常显示导航栏,今天有点时间,就自己动手实现一下,本以为没什么难度,殊不知还是有些点需要注意的。
先看一下效果:
下面我们一步一步剖析:
1、设置导航颜色,下边两种设置导航方法,都可以动态改变透明度
[[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:45/255.0 green:45/255.0 blue:45/255.0 alpha:1]];
[[UINavigationBar appearance] setBackgroundImage:[[UIImage imageNamed:@"顶部栏_7.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:10] forBarMetrics:UIBarMetricsDefault];
2、设置视图偏移量
_halfHeight = [UIScreen mainScreen].bounds.size.height * 0.5 - 64;
[_mytableView setContentInset:UIEdgeInsetsMake(_halfHeight, 0, 0, 0)];
3、视图出现时处理
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;//导航栏的背景色是黑色, 字体为白色
[self scrollViewDidScroll:self.mytableView];//开始就处理
[self.navigationController.navigationBar setShadowImage:[UIImage new]];//用于去除导航栏的底线,也就是周围的边线
}
4、主要处理方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat offsetY = scrollView.contentOffset.y;
NSLog(@"oooooo%f",offsetY);
if (offsetY >= - _halfHeight-64) {
CGFloat alpha = MIN(1, (_halfHeight + offsetY + 64)/(_halfHeight+64));
//这里需要区分,在translicent 切换值时,偏移量相差64
if (self.navigationController.navigationBar.translucent && offsetY >= -64) {
alpha = 1;
}
[[[self.navigationController.navigationBar subviews] objectAtIndex:0] setAlpha:alpha];//设置显示层视图透明度
if (alpha == 1) {
[self.navigationController.navigationBar setTranslucent:NO];
}else{
[self.navigationController.navigationBar setTranslucent:YES];
}
} else {
[self.navigationController.navigationBar setTranslucent:YES];
[[[self.navigationController.navigationBar subviews] objectAtIndex:0] setAlpha:0];
}
}
这里为了使导航在恰当的时机显示正确的颜色,添加了Translucent属性的设置,这个值默认是YES,此时导航栏有透明效果,若是设置为NO则无法动态改变透明度,此处需要注意
Translucent为YES时tableView的起始是从屏幕顶端开始的,若是设置为NO则是从64高度开始的,这个在透明度为1的临界点时会出现问题,需要修正修正代码:
//这里需要区分,在translicent 切换值时,偏移量相差64
if (self.navigationController.navigationBar.translucent && offsetY >= -64) {
alpha = 1;
}
本以为到这里就结束了,多想了一下,若是跳转其它视图,要正常显示,此时就要设置Translucent 为NO,为了对所有视图起作用,需添加UIViewController的分类,直接上代码:
+ (void)load{
Method viewWillAppear = class_getInstanceMethod(self, @selector(viewWillAppear:));
Method logViewWillAppear = class_getInstanceMethod(self, @selector(logViewWillAppear:));
method_exchangeImplementations(viewWillAppear, logViewWillAppear);
}
- (void)logViewWillAppear:(BOOL)animated{
[self logViewWillAppear:animated];
if ([self isKindOfClass:[ViewController class]]) {
[self.navigationController.navigationBar setTranslucent:YES];
}else{
[self.navigationController.navigationBar setTranslucent:NO];
}
}
至此达到了我们想要的效果,即当期视图可动态导航透明度,其它视图不受影响正常显示
添加修正:
由于设置Translucent时tableciew的偏移量改变,则还会调用活动的代理方法,会重新的设置导航的透明度,所以必须
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
self.mytableView.delegate = nil;//必须加上
[[[self.navigationController.navigationBar subviews] objectAtIndex:0] setAlpha:1];
}
然后在ciewwillAppear重新添加代理