最終效果圖:Dock跟隨HomeVC一起切換
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PGJyPgo8YnI+CjwvcD4KPHA+PHN0cm9uZz7SqsfzOjwvc3Ryb25nPjwvcD4KPHA+PHN0cm9uZz61sbXju/dIb21lVkPA78PmtcTOorKpwdCx7bXExLPSu9DQyrG68iw8L3N0cm9uZz48L3A+CjxwPjxzdHJvbmc+cHVzaLW9U3RhdHVzRGV0YWlszqKyqc/qx+m/2NbGxvcssqLH0kRvY2vSstK7xvDP+8qnPC9zdHJvbmc+PC9wPgo8cD48c3Ryb25nPrWxteO791N0YXR1c0RldGFpbM6isqnP6sfpv9jWxsb3yc/D5rXE1/Ox37e1u9iwtMWlLERvY2vSsrj618VIb21lVkPSu8bwu9jAtDwvc3Ryb25nPjwvcD4KPHA+PC9wPgo8cD48c3Ryb25nPjxicj4KSG9tZVZDLm08L3N0cm9uZz48L3A+CjxwPjwvcD4KPHByZSBjbGFzcz0="brush:java;">// 點擊列表中的一條微博,創建一個StatusDetailViewController,並為其成員status賦值(數據來源),並通過導航push入棧
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 創建一個微博正文詳情控制器,
StatusDetailViewController *detailVC = [[StatusDetailViewController alloc] init];
// 為即將跳轉的微博正文控制器,傳遞weibo數據(以供其顯示用)
StatusListCellFrame *statusListCellFrame = _statusCellFrames[indexPath.row];
detailVC.status = statusListCellFrame.status;
// 通過導航控制器跳轉過去
[self.navigationController pushViewController:detailVC animated:YES];
}
如上圖所示,
主控制器(BeyondVC)的view包含兩個部分:
1,上部的導航控制器 2,下面的Dock
上部的導航控制器的view又包括兩個部分:
1,上部的導航條(push的時候,它始終不動)
2,下部的根控制器(HomeVC)(push的時候會動畫切換)
為了讓Dock和導航控制器的根控制(HomeVC)能一起滑過去,又能夠一起滑回來,
必須讓主控制器(BeyondVC)成為導航控制器的代理,
使之能夠監聽push動作之willShowViewController和didShowViewController方法
在下面的willShowViewController方法中,
先將Dock從主控制器(BeyondVC)上移除,然後添加到導航控制器的根控制(HomeVC)裡面
導航控制器的代理方法 willShowViewController
#pragma mark - 導航控制器的代理方法 // 屏幕寬 320 #define kWinWidth self.view.bounds.width // 屏幕高 480 #define kWinHeight self.view.bounds.height // 頂部狀態條 20 #define kStatusBarHeight 20 // 目的是,監聽push動作,在新控制器將進入棧頂時,設置左邊按鈕為返回箭頭,設置右邊按鈕為回到首頁 - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { //重要~~~~ // 先取得根控制器 UIViewController *rootVC = navigationController.viewControllers[0]; // 如果將要顯示的控制器(將被push入棧的), 不是棧底控制器(根控制器),才需要設置左邊為返回按鈕,右邊為首頁按鈕 if (viewController != rootVC) { // 左邊的返回到上一個控制器 viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem barButtonItemWithBgIcon:@"navigationbar_back.png" target:self action:@selector(popToPreviousVC)]; // 右邊的回到首頁按鈕,即回到棧底控制器(即從詳情頁回到列表頁) viewController.navigationItem.rightBarButtonItem = [UIBarButtonItem barButtonItemWithBgIcon:@"navigationbar_home.png" target:self action:@selector(backToRootVC)]; // 1,先拉長導航控制器的view的高度 為整個窗口的高度-20 (因為dock消失後,底部會多空出黑色的空間) navigationController.view.frame = CGRectMake(0, 20,320,480 - 20); // 2,先讓Dock從主控制器(BeyondViewController)的view上移除 [_dock removeFromSuperview]; // 3,為了在Push下一個控制器,讓dock和根控制器一起平移,所以,添加dock到導航控制器的根控制器的view上 ,並重新調整Dock在HomeVC的view中的Y值即可,注意導航不會移動,移的是導航的根控制器,而根控制器的原點(0 0)是 :20+導航欄高度44 // 如果根控制器是可以滾動的,則要注意y的原點是在tableView的頂部(當向下滾了一定的距離之後) if ([rootVC.view isKindOfClass:[UIScrollView class]]) { UIScrollView * scrollV = (UIScrollView *)rootVC.view; // dock的導航控制器的根控制器裡面的y值 // 因為滾動之後,rootView的左上角到頂上很遠的地方了 _dock.frame =CGRectMake(0, scrollV.contentOffset.y + 460 - kDockHeight, 320, kDockHeight ); } else { // dock的導航控制器的根控制器裡面的y值 _dock.frame =CGRectMake(0, 480 - 20 - 2*kDockHeight, 320, kDockHeight ); } // 4,最後再添加dock到導航控制器的根控制器裡面(rootVC界面上(即導航控制器的根控制器),目的是push新的VC的時候,讓dock和導航控制器的根控制器一起平移到界面的左邊去,當點擊返回鍵的時候,dock又能和rootVC一起回來 [rootVC.view addSubview:_dock]; } }
在下面的didShowViewController方法中,
先將Dock從導航控制器的根控制(HomeVC)上移除,然後添加到主控制器(BeyondVC)裡面
導航控制器的代理方法 didShowViewController
// 導航控制器的Y = 20,導航控制器的高度 = 總高度 - DOCK高度 - 20 #define kContentFrame CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height - kDockHeight - 20) // BeyondVC主控制器中,DOCK的Y = 總高度 - DOCK高度 #define KDockFrame CGRectMake(0, self.view.frame.size.height - kDockHeight, self.view.frame.size.width, kDockHeight) // 目的是,監聽push動作,在新控制器已經顯示的時候,將dock從導航控制器中移除,再又重新顯示到主控制器 - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { // 先取得導航 的棧底的根控制器 UIViewController *rootVC = navigationController.viewControllers[0]; // 如果要顯示的控制器是根控制器,重新把Dock if (viewController == rootVC) { // 更改導航控制器view的frame // 導航控制器的Y = 20,導航控制器的高度 = 總高度 - DOCK高度 - 20 navigationController.view.frame = kContentFrame; // 將Dock先從棧底的根控制器rootVC上移除 [_dock removeFromSuperview]; // 再添加dock到BeyondViewController,DOCK的Y = 總高度 - DOCK高度 _dock.frame = KDockFrame; [self.view addSubview:_dock]; } }