一直看到好多的app都有狀態欄隨視圖的滑動,透明度動態改變,跳轉入其它視圖則正常顯示導航欄,今天有點時間,就自己動手實現一下,本以為沒什么難度,殊不知還是有些點需要注意的。
先看一下效果:
2017-09-21 17_01_55.gif
下面我們一步一步剖析:
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重新添加代理