在項(xiàng)目中往往有的時(shí)候需要導(dǎo)航欄的狀態(tài)是變化的,有的時(shí)候需要隱藏,為的是顯示更多的頁面,有的時(shí)候需要顯示出來,給用戶以提示,所以就需要隱藏和顯示導(dǎo)航欄。正如下面的示意圖所示:

分析
本個(gè)項(xiàng)目中,展示的是一個(gè)導(dǎo)航控制器,其中導(dǎo)航控制器中有個(gè)UIViewController或者是UITableviewController為根控制器的這么一個(gè)結(jié)構(gòu)。
實(shí)現(xiàn)
因此在storyboard中我們將之前控制器刪除,然后拖一個(gè)導(dǎo)航控制器出來,然后試著先綁定一個(gè)UITableviewController為根控制器。
導(dǎo)航欄的設(shè)置
為了讓我們的header view所展示的位置是在左上角的圓點(diǎn)位置,我們需要把自動(dòng)偏移設(shè)置關(guān)掉。
self.automaticallyAdjustsScrollViewInsets = NO;
下面就需要隱藏導(dǎo)航欄操作了,我們都知道導(dǎo)航欄有一個(gè)隱藏的屬性,下面試試
self.navigationController.navigationBar.hidden = YES;
這種方法雖然能夠讓導(dǎo)航欄消失隱藏掉,但是如果我們要進(jìn)行滾動(dòng)tableview的時(shí)候,就不能讓導(dǎo)航欄漸變的顯示出來,所以這種方法不能滿足要求。
這種方法行不通那么用透明度的方案來試試:
self.navigationController.navigationBar.alpha = 0;
截圖如下:

因此上面的方案不能實(shí)現(xiàn)功能。
可以使用設(shè)置導(dǎo)航欄背景圖片進(jìn)行設(shè)置,這樣就可以設(shè)置導(dǎo)航欄的背景有個(gè)透明度的變化。
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
當(dāng)傳入的圖片為nil的時(shí)候,會(huì)自動(dòng)的創(chuàng)建一個(gè)半透明的圖片作為導(dǎo)航欄的背景。所以這種方案是可行的,但是導(dǎo)航欄下面的那一根線我們是希望不顯示的:
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
這樣一來,導(dǎo)航欄的那根線就取消掉了。
以上導(dǎo)航欄的基本實(shí)現(xiàn)方案已經(jīng)確定了,但是下面的列表的顯示還有些疑問,到底是用的tableview顯示,利用tableview的headerView;還是用UIViewController進(jìn)行展示頭部的控件,下面的部分就用tableview進(jìn)行展示。
UITableviewController 方案
我們先試著作出示意圖的效果,一個(gè)tableview上放置一個(gè)headerView。
UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];
header.backgroundColor = [UIColor redColor];
self.tableView.tableHeaderView = header;
運(yùn)行下,看效果:

看示意圖,我們可以看到整個(gè)tableview都在移動(dòng),而不是我們效果圖那種的樣式,在往下滾動(dòng)的時(shí)候,頭部的控件是不會(huì)網(wǎng)下移動(dòng)的,但是利用tableview的headerView進(jìn)行布局的方案是不成功的。
UIViewController 方案
我們首先在view上放置一個(gè)tableview和UIView(放置頭部的那些圖片)。

以上都是在storyboard中操作的。

以上的效果圖中可以看到頭部的headerView沒有類似于tableview的headerView那種滾動(dòng)的時(shí)候出現(xiàn)下移的情況。所以這種方式是可行的。
但是我們還需要設(shè)置tableview的偏移量,因?yàn)閳D片的顯示,遮擋住了我們的列表,所以需要設(shè)置一個(gè)偏移量:
self.tableView.contentInset = UIEdgeInsetsMake(244, 0, 0, 0);
導(dǎo)航欄的一些細(xì)節(jié)處理
導(dǎo)航欄的文字,在剛開始出現(xiàn)的時(shí)候是需要隱藏掉的,
//設(shè)置標(biāo)題
UILabel *title = [[UILabel alloc] init];
title.text = @"個(gè)人主頁";
[title sizeToFit];
// 開始的時(shí)候看不見,所以alpha值為0
title.textColor = [UIColor colorWithWhite:0 alpha:0];
self.navigationItem.titleView = title;
雖然我們已經(jīng)把文字隱藏掉了,但是已進(jìn)入到控制器,我們還是能看到導(dǎo)航欄,所以我們需要在進(jìn)入到控制器的時(shí)候隱藏掉,就在storyboard中進(jìn)行設(shè)置就可以了,選中控制器:

把top Bar的設(shè)置改為None就可以了。
實(shí)現(xiàn)滾動(dòng)隱藏或顯示導(dǎo)航欄
我們知道tableview是繼承自scrollView的,所以有個(gè)-scrollViewDidScroll:方法中可以拿到tableview的滾動(dòng)。而且當(dāng)調(diào)用contentInset會(huì)自動(dòng)調(diào)用-scrollViewDidScroll:。
我們可以這個(gè)方法中監(jiān)聽到scrollView的偏移量:
#pragma mark - scrollview
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(@"%f", scrollView.contentOffset.y); // 原始偏移的位置是-244
}
所以導(dǎo)航欄的一些控制操作就在這個(gè)方法中進(jìn)行實(shí)現(xiàn)。
我們需要注意到的是,當(dāng)整個(gè)頁面上移到一定的位置的時(shí)候,就不在上移了,因?yàn)樾枰魤?4的位置給導(dǎo)航欄進(jìn)行顯示。也就是說這個(gè)顯示圖片這部分上移到一定的位置就不在移動(dòng)了。
我們需要改變這個(gè)控件的高度,那么就需要修改這個(gè)控件高度的約束,所以就需要拖個(gè)約束到控制器中。
// 頭部展示高度約束
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *imageHeight;
計(jì)算頭部的高度:
CGFloat offset = scrollView.contentOffset.y - oriOfftY;
CGFloat imgH = oriHeight - offset;
if (imgH < 64) {
// 當(dāng)上移到距離頂部小于64的時(shí)候,就不在移動(dòng)了。
imgH = 64;
}
self.imageHeight.constant = imgH;

到此我們就需要處理透明度漸變的問題了。
由效果圖可以知道,整個(gè)頁面上移到一定的距離,就會(huì)完全顯示出導(dǎo)航欄,下移一定的距離,導(dǎo)航欄就會(huì)消失掉。
//透明度
//找最大值/
CGFloat alpha = offset * 1 / 136.0; // (200 - 64) / 136.0f
if (alpha >= 1) {
// 透明度最大值
alpha = 0.99;
}
設(shè)置文字:
//拿到標(biāo)題 標(biāo)題文字的隨著移動(dòng)高度的變化而變化
UILabel *titleL = (UILabel *)self.navigationItem.titleView;
titleL.textColor = [UIColor colorWithWhite:0 alpha:alpha];
最后一步就是修改導(dǎo)航欄的背景的漸變效果:
//把顏色生成圖片
UIColor *alphaColor = [UIColor colorWithWhite:1 alpha:alpha];
//把顏色生成圖片
UIImage *alphaImage = [UIImage imageWithColor:alphaColor];
//修改導(dǎo)航條背景圖片
[self.navigationController.navigationBar setBackgroundImage:alphaImage forBarMetrics:UIBarMetricsDefault];
-imageWithColor :這個(gè)方法是UIImage的一個(gè)分類中的方法,專門就是把顏色轉(zhuǎn)換成圖片的方法:
// 顏色轉(zhuǎn)為圖片
+ (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0, 0, 1.0f, 1.0f);
// 開啟位圖上下文
UIGraphicsBeginImageContext(rect.size);
// 開啟上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
// 使用color演示填充上下文
CGContextSetFillColorWithColor(ref, color.CGColor);
// 渲染上下文
CGContextFillRect(ref, rect);
// 從上下文中獲取圖片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 結(jié)束上下文
UIGraphicsEndImageContext();
return image;
}
以上基本完成了想要的效果圖的功能了。
代碼傳送門,如果有幫助你的話,GitHub上給個(gè)贊唄!