1、效果展示

2、實(shí)現(xiàn)原理
實(shí)現(xiàn)原理其實(shí)就是觀察UIScrollView的contentOffset的y值,根據(jù)y值的變化來不斷的設(shè)置導(dǎo)航欄背景色的alpha值,從而使其達(dá)到導(dǎo)航欄透明度漸變的效果。
3、細(xì)節(jié)說明
擴(kuò)展UINavigationBar
首先,我們發(fā)現(xiàn)直接修改UINavigationBar的背景顏色是不行的。因?yàn)樵赨INavigationBar的高度是44,其上面的20px是狀態(tài)欄,如果單純的setBackgroundColor只是漸變狀態(tài)欄下邊的44px的顏色,看起來效果像截?cái)嗔艘粯?。所以,我們需要擴(kuò)展UINavigationBar這個(gè)類,在該類添加一個(gè)view,使得該view高度為64px并且是在最上層顯示,目的是把狀態(tài)欄給遮擋住。部分代碼如下:
- (void)cnSetBackgroundColor:(UIColor *)backgroundColor
{
if (!self.overlay) {
[self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.overlay = [[UIView alloc] initWithFrame:CGRectMake(0, -20, [UIScreen mainScreen].bounds.size.width, CGRectGetHeight(self.bounds) + 20)];
self.overlay.userInteractionEnabled = NO;
self.overlay.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
[self insertSubview:self.overlay atIndex:0];
}
self.overlay.backgroundColor = backgroundColor;
}
其中,overlay是通過runtime運(yùn)行時(shí)添加的一個(gè)關(guān)聯(lián)對(duì)象。
設(shè)置UIScrollView的contentInset
因?yàn)樾枰鶕?jù)滾動(dòng)距離變化來設(shè)置導(dǎo)航欄的透明度,所以初始情況下,需要設(shè)置好UIScrollView里的contentInset值
監(jiān)聽UIScrollView的contentOffset.y值
根據(jù)UIScrollView 的delegate方法scrollViewDidScroll,我們能實(shí)時(shí)獲得contentOffset.y值,根據(jù)該值的變化對(duì)剛才擴(kuò)展的UINavigationBar的背景色的alpha值,做相應(yīng)的變化,具體實(shí)現(xiàn):
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
UIColor *color = [UIColor colorWithRed:45/255.0 green:45/255.0 blue:45/255.0 alpha:1];
CGFloat offsetY = scrollView.contentOffset.y;
if (offsetY >= - _halfHeight - 64) {
CGFloat alpha = MIN(1, (_halfHeight + 64 + offsetY)/_halfHeight);
[self.navigationController.navigationBar cnSetBackgroundColor:[color colorWithAlphaComponent:alpha]];
_descriptionView.alpha = 1 - alpha;
} else {
[self.navigationController.navigationBar cnSetBackgroundColor:[color colorWithAlphaComponent:0]];
}
}
4、補(bǔ)充說明
需要在viewWillAppear方法中去掉導(dǎo)航欄的底邊線,也就是那一條區(qū)分的橫線。
[self.navigationController.navigationBar setShadowImage:[UIImage new]];
為避免返回到其他頁面后,還是沿用該導(dǎo)航欄樣式,所以需要在viewWillDisappear的時(shí)候,還原之前的樣式,也就是把overlay給去掉,具體看代碼實(shí)現(xiàn)。
5、Github代碼
2017/02/27 更新
看到讀者評(píng)論說,用了后會(huì)使得導(dǎo)航欄的Item消失不見的,我自己測(cè)試了一下,發(fā)現(xiàn)在iOS10上面會(huì)出現(xiàn)這個(gè)問題,估計(jì)UINavigationBar在iOS10上面的布局可能有了變化,我后來想了另外一個(gè)更投機(jī)的方法去實(shí)現(xiàn)這個(gè)功能,不需要通過Category多添加UINavigationBar里面的背景View去實(shí)現(xiàn),而是通過
self.navigationController.navigationBar.barTintColor
去設(shè)置顏色,而通過使用
[[[self.navigationController.navigationBar subviews] objectAtIndex:0] setAlpha:0];
找到navigationBar的背景view,然后設(shè)置alpha值。已經(jīng)更新到GitHub上了,各位看官可以去下載看看。