現有許多的app中會要求在UITableView
/UICollectionView
上滑時顯示,下滑動時慢慢的隱藏導航欄和工具欄,先看張效果圖:
此文章是最初實驗的時候寫的;
比較忙,中間有很久一段時間沒有更新,后面換了一種方法實現;
最終請看demo(在文章的末尾),已有多個項目在使用,已適配ios11及iphoneX
一般項目的架構有如下三種:
1. 系統的TabBar和系統navigationBar;
2. 自定義的TabBar和系統navigationBar;
3. 前兩者混合使用(某個可能是自定制的),并且在那個界面中又加了多個子控制器addChildViewController;
針對于第一種情況,如果是對UINavigationController
的結構不熟悉的,可能就比較麻煩了,但網上也有相關的DEMO,今天在這就不多說了,這文章主要是講三種:
首先UI的層次結構大概是這樣子的:
window > UITabBarController > UINavigationController(可能有多個) > parentViewController > 這里有多個ChildViewController 還有一個自定制的UINavigationBar > ChildViewController里面可能又有UIScrollView;
parentViewController的大致結構:UIScrollView > 裝個多個ChildViewController的view,如下圖:
好了,結構介紹完畢,下面我們分析下實現思路:
1, 讓其跟著上下滑動的偏移來決定上或下移多少,直到隱藏或者完全顯示,那肯定是操作parentViewController的UIScrollViewDelegate
代理方法;
2, 到這里你可能會想:這很簡單啊!讓其跟著滑動就可以了;其實不然還得看你的parentViewController里面的子視圖里面的自定制導航欄和scrollView的起始坐標和高度,更多的情況下是:
UINavigationBar
的坐標是:{0, 0, screenWidth, 64};
scrollView和坐標是:{0, 64, screenWidth, screenHeight - 64}
然而在這種情況下:scrollView滑動時候讓其UINavigationBar
跟著滑動,是可以正常隨著偏移滑動,但是你會發現UINavigationBar
與scrollView會中間會出現空白的間隔,且隨著偏移變大面變大;重點問題就在這樣,要怎么解決這個問題?
出現如上的原因是scrollView的Y是64,往上滑動,UINavigationBar
也跟著往上走,但scrollView永遠都是在64的位置,那么你再怎么往上滑動,scrollView里面的內容也是無法顯示的,都超出了父控件.你可能會想讓其scrollView也一起往上移,那這樣的用戶體驗性不好,而且你還得考慮到下邊還有個UITabBar
正好跟著UINavigationBar
反向偏動 ;
正確的方法應該是:
-
把parentViewController的scrollView的坐標設置為:self.view.bounds,即跟屏幕一樣大;
426722A1-8DB7-4036-962A-29C1270EB7CD.png -
parentViewController的ChildViewController的view的frame也跟父控件(scrollView)一樣大,
42C46408-BF93-4684-88F9-8392EFB35476.png - ChildViewController里的tableView的frame設置很關鍵:
Y必須從0開始,高度與ChildViewController.view的高度一致,這里高度保持一致也是為了tabbar下移的時候,不會出現空白區域;再設置tableView的contentInset
內偏移,讓內容往下偏移導航欄的高度,這樣就完美的解決了上下滑動會出現空白區域的問題;
D254E75C-96D4-4D71-A18F-D1ED46DFCFF8.png - 在
UIScrollViewDelegate
的代理方法中實現讓導航欄和工具欄跟著scrollView的contentOffset.y變化;
@implementation NHConcernViewController
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
NHTabBarController *tab = (NHTabBarController *)self.tabBarController;
NHFirstController *parentVC = (NHFirstController *)self.parentViewController;
CGFloat moveOffset = scrollView.contentOffset.y - _lastPoint.y;
NSLog(@"%f",moveOffset);
//偏移量小于 -kNavgationHeight時,不需要改變
if (scrollView.contentOffset.y <= -kNavgationHeight) return;
if (scrollView.contentOffset.y > _lastPoint.y) {
[tab tabBarControllerShouldMoveTabbarOffset:moveOffset];
[parentVC didScrollTableViewShouldChangeNavigationBarWithOffset:moveOffset];
}else {
[tab tabBarControllerShouldMoveTabbarOffset:moveOffset];
[parentVC didScrollTableViewShouldChangeNavigationBarWithOffset:moveOffset];
}
_lastPoint = scrollView.contentOffset;
}
@end
//這里的`NHFirstController`就是文中所說的`parentViewController`
@interface NHFirstController
- (void)didScrollTableViewShouldChangeNavigationBarWithOffset:(CGFloat)newSize;
@end
@implementation NHFirstController
/**
* tableView滾動的時候改變導航欄的frame
* @param newFrame new frame
*/
- (void)didScrollTableViewShouldChangeNavigationBarWithOffset:(CGFloat)newPoint{
CGRect newRect = _navgationView.frame;
newRect.origin.y += -newPoint ;
_navgationView.frame = newRect;
if (newRect.origin.y > 0) {
newRect.origin.y = 0;
_navgationView.frame = newRect;
}
if (newRect.origin.y < -kNavgationHeight) {
newRect.origin.y = -kNavgationHeight;
_navgationView.frame = newRect;
}
}
@end
特別注意:自定制的導航條在要add完scrollView后再add
- (void)viewDidLoad {
[super viewDidLoad];
[self addChildViewControllers];
[self setNavgationBar];
}
你滑一滑試下,是不是OK了.