首页 > 代码库 > iOS_20_微博Dock的跟随切换

iOS_20_微博Dock的跟随切换

最终效果图:Dock跟随HomeVC一起切换




要求:

当点击HomeVC里面的微博列表的某一行时候,

push到StatusDetail微博详情控制器,并且Dock也一起消失

当点击StatusDetail微博详情控制器上面的左边返回按钮,Dock也跟着HomeVC一起回来


HomeVC.m

// 点击列表中的一条微博,创建一个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];
    }
}





这样就实现了,让主控制器里面的Dock跟随导航控制器的根控制器,一起消失,又一起回来~