在項目中往往有的時候需要導航欄的狀態是變化的,有的時候需要隱藏,為的是顯示更多的頁面,有的時候需要顯示出來,給用戶以提示,所以就需要隱藏和顯示導航欄。正如下面的示意圖所示:
分析
本個項目中,展示的是一個導航控制器,其中導航控制器中有個UIViewController或者是UITableviewController為根控制器的這么一個結構。
實現
因此在storyboard中我們將之前控制器刪除,然后拖一個導航控制器出來,然后試著先綁定一個UITableviewController為根控制器。
導航欄的設置
為了讓我們的header view所展示的位置是在左上角的圓點位置,我們需要把自動偏移設置關掉。
self.automaticallyAdjustsScrollViewInsets = NO;
下面就需要隱藏導航欄操作了,我們都知道導航欄有一個隱藏的屬性,下面試試
self.navigationController.navigationBar.hidden = YES;
這種方法雖然能夠讓導航欄消失隱藏掉,但是如果我們要進行滾動tableview的時候,就不能讓導航欄漸變的顯示出來,所以這種方法不能滿足要求。
這種方法行不通那么用透明度的方案來試試:
self.navigationController.navigationBar.alpha = 0;
截圖如下:
因此上面的方案不能實現功能。
可以使用設置導航欄背景圖片進行設置,這樣就可以設置導航欄的背景有個透明度的變化。
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
當傳入的圖片為nil的時候,會自動的創建一個半透明的圖片作為導航欄的背景。所以這種方案是可行的,但是導航欄下面的那一根線我們是希望不顯示的:
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
這樣一來,導航欄的那根線就取消掉了。
以上導航欄的基本實現方案已經確定了,但是下面的列表的顯示還有些疑問,到底是用的tableview顯示,利用tableview的headerView;還是用UIViewController進行展示頭部的控件,下面的部分就用tableview進行展示。
UITableviewController 方案
我們先試著作出示意圖的效果,一個tableview上放置一個headerView。
UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];
header.backgroundColor = [UIColor redColor];
self.tableView.tableHeaderView = header;
運行下,看效果:
看示意圖,我們可以看到整個tableview都在移動,而不是我們效果圖那種的樣式,在往下滾動的時候,頭部的控件是不會網下移動的,但是利用tableview的headerView進行布局的方案是不成功的。
UIViewController 方案
我們首先在view上放置一個tableview和UIView(放置頭部的那些圖片)。
以上都是在storyboard中操作的。
以上的效果圖中可以看到頭部的headerView沒有類似于tableview的headerView那種滾動的時候出現下移的情況。所以這種方式是可行的。
但是我們還需要設置tableview的偏移量,因為圖片的顯示,遮擋住了我們的列表,所以需要設置一個偏移量:
self.tableView.contentInset = UIEdgeInsetsMake(244, 0, 0, 0);
導航欄的一些細節處理
導航欄的文字,在剛開始出現的時候是需要隱藏掉的,
//設置標題
UILabel *title = [[UILabel alloc] init];
title.text = @"個人主頁";
[title sizeToFit];
// 開始的時候看不見,所以alpha值為0
title.textColor = [UIColor colorWithWhite:0 alpha:0];
self.navigationItem.titleView = title;
雖然我們已經把文字隱藏掉了,但是已進入到控制器,我們還是能看到導航欄,所以我們需要在進入到控制器的時候隱藏掉,就在storyboard中進行設置就可以了,選中控制器:
把top Bar的設置改為None就可以了。
實現滾動隱藏或顯示導航欄
我們知道tableview是繼承自scrollView的,所以有個-scrollViewDidScroll:
方法中可以拿到tableview的滾動。而且當調用contentInset
會自動調用-scrollViewDidScroll:
。
我們可以這個方法中監聽到scrollView的偏移量:
#pragma mark - scrollview
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(@"%f", scrollView.contentOffset.y); // 原始偏移的位置是-244
}
所以導航欄的一些控制操作就在這個方法中進行實現。
我們需要注意到的是,當整個頁面上移到一定的位置的時候,就不在上移了,因為需要留夠64的位置給導航欄進行顯示。也就是說這個顯示圖片這部分上移到一定的位置就不在移動了。
我們需要改變這個控件的高度,那么就需要修改這個控件高度的約束,所以就需要拖個約束到控制器中。
// 頭部展示高度約束
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *imageHeight;
計算頭部的高度:
CGFloat offset = scrollView.contentOffset.y - oriOfftY;
CGFloat imgH = oriHeight - offset;
if (imgH < 64) {
// 當上移到距離頂部小于64的時候,就不在移動了。
imgH = 64;
}
self.imageHeight.constant = imgH;
到此我們就需要處理透明度漸變的問題了。
由效果圖可以知道,整個頁面上移到一定的距離,就會完全顯示出導航欄,下移一定的距離,導航欄就會消失掉。
//透明度
//找最大值/
CGFloat alpha = offset * 1 / 136.0; // (200 - 64) / 136.0f
if (alpha >= 1) {
// 透明度最大值
alpha = 0.99;
}
設置文字:
//拿到標題 標題文字的隨著移動高度的變化而變化
UILabel *titleL = (UILabel *)self.navigationItem.titleView;
titleL.textColor = [UIColor colorWithWhite:0 alpha:alpha];
最后一步就是修改導航欄的背景的漸變效果:
//把顏色生成圖片
UIColor *alphaColor = [UIColor colorWithWhite:1 alpha:alpha];
//把顏色生成圖片
UIImage *alphaImage = [UIImage imageWithColor:alphaColor];
//修改導航條背景圖片
[self.navigationController.navigationBar setBackgroundImage:alphaImage forBarMetrics:UIBarMetricsDefault];
-imageWithColor :
這個方法是UIImage的一個分類中的方法,專門就是把顏色轉換成圖片的方法:
// 顏色轉為圖片
+ (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();
// 結束上下文
UIGraphicsEndImageContext();
return image;
}
以上基本完成了想要的效果圖的功能了。
代碼傳送門,如果有幫助你的話,GitHub上給個贊唄!