带有下划线和动画效果的视图切换(addChildViewController)


在iOS 5之前苹果是不允许出现自定义的Container的 ,也就是说你创建的一个View Controller的view不能包含另一个View Controller的view,这对于逻辑复杂的界面来说,不易于功能拆分。也许曾经你为了某个公用的显示逻辑,直接将某个View Controller的view添加到另一个View Controller的view上,然后发现可以正常显示和使用,但实际上这种行为是非常危险的。

 

iOS 5.0 开始支持Custom Container View Controller,开放了用于构建自定义Container的接口。如果你想创建一个自己的Container,那么有一些概念还得弄清楚。Container的主要职责就是管理一个或多个Child View Controller的展示的生命周期,需要传递显示以及旋转相关的回调。

 

其实显示或者旋转的回调的触发的源头来自于window,一个app首先有一个主window,初始化的时候需要给这个主window指定一个rootViewController,window会将显示相关的回调(viewWillAppear:, viewWillDisappear:, viewDidAppear:, or viewDidDisappear: )以及旋转相关的回调(willRotateToInterfaceOrientation:duration: ,willAnimateRotationToInterfaceOrientation:duration:, didRotateFromInterfaceOrientation:)传递给rootViewController。rootViewController需要再将这些callbacks的调用传递给它的Child View Controllers。

 

一. 父子关系范式

实现一个Custom Container View Controller并不是一个简单的事情,主要分为两个阶段:父子关系的建立以及父子关系的解除。如果pVC将cVC的view添加为自己的subview,那么cVC必须为pVC的Child View Controller,而反过来则不一定成立,比如UINavigationController,一个View Controller被push进来后便和navigationController建立父子关系了,但是只有最上面的View Controller 是显示着的,底下的View Controller的view则被移出了容器的view的显示层级,当一个View Controller被pop之后,便和navigationController解除了父子关系了。

 

展示一个名为content的child view controller:

 
 
  1. [self addChildViewController:content];  //1 
  2. content.view.frame = [self frameForContentController];  
  3. [self.view addSubview:self.currentClientView]; //2 
  4. [content didMoveToParentViewController:self]; //3 

1.将content添加为child view controller,addChildViewController:接口建立了逻辑上的父子关系,子可以通过parentViewController,访问其父VC,addChildViewController:接口的逻辑中会自动调用 [content willMoveToParentViewController:self];

2.建立父子关系后,便是将content的view加入到父VC的view hierarchy上,同时要决定的是 content的view显示的区域范围。 

3.调用child的 didMoveToParentViewController: ,以通知child,完成了父子关系的建立

 

移除一个child view controller:

 
 
  1. [content willMoveToParentViewController:nil]; //1 
  2. [content.view removeFromSuperview]; //2 
  3. [content removeFromParentViewController]; //3 

1.通知child,即将解除父子关系,从语义上也可以看出 child的parent即将为nil

2.将child的view从父VC的view的hierarchy中移除 

3.通过removeFromParentViewController的调用真正的解除关系,removeFromParentViewController会自动调用 [content didMoveToParentViewController:nil]



代码实现部分,封装的一个简单视图控制类管理切换视图功能

@interface ContaintControllerHealp ()<TopSortChooseDelegate>
@property (nonatomic, strong)UIViewController *currentVC;//保存当前选择的VC

@property (nonatomic, strong)NSArray *controllers;

@property (nonatomic, strong)UIViewController *fatherVC;

@end
@implementation ContaintControllerHealp

-(instancetype)initByCeateContainWithControllers:(NSArray *)controllers titles:(NSArray *)titles fatherController:(UIViewController *) fahterVC{
    self = [super init];
    if (self) {
        fahterVC.automaticallyAdjustsScrollViewInsets = NO;
        self.fatherVC = fahterVC;
        self.controllers = controllers;
        [self creatTopSegmentWithTitles:titles fatherC:fahterVC];

        [self createControllerResolutionWith:controllers fatherVC:fahterVC];

    }
    return self;
}
//
-(void)creatTopSegmentWithTitles:(NSArray *)titles fatherC:(UIViewController *)fahterVC{
    CunstomTopScrollView *customScro = [[CunstomTopScrollView alloc] initWithFrame:CGRectMake(0, 64, fahterVC.view.frame.size.width, 40) titileArr:titles];
    customScro.delegate = self;
    
    [fahterVC.view addSubview:customScro];
}
-(void)createControllerResolutionWith:(NSArray *)controllers fatherVC:(UIViewController *)fatherVC{
    //拿第一个VC而已。。写麻烦了
    [controllers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        UIViewController *VC = obj;
        if (idx == 0) {//默认第一个
            [fatherVC addChildViewController:VC];
            [fatherVC.view addSubview:VC.view];
            //  默认,第一个视图(你会发现,全程就这一个用了addSubview)

            [VC didMoveToParentViewController:fatherVC];//确定关系建立
            self.currentVC = VC;
        }
        
    }];
}
#pragma mark 选择按钮代理
-(void)getSelectButton:(NSInteger)chooseIndex{
    UIViewController *VC = [self.controllers objectAtIndex:chooseIndex];
    if (VC == self.currentVC) {
        return;
    }
    else{
        [self replaceController:self.currentVC newController:VC];
    }
    
    
}

//  切换各个标签内容
- (void)replaceController:(UIViewController *)oldController newController:(UIViewController *)newController
{
    /**
     *            着重介绍一下它
     *  transitionFromViewController:toViewController:duration:options:animations:completion:
     *  fromViewController      当前显示在父视图控制器中的子视图控制器
     *  toViewController        将要显示的姿势图控制器
     *  duration                动画时间(这个属性,old friend 了 O(∩_∩)O)
     *  options                 动画效果(渐变,从下往上等等,具体查看API)
     *  animations              转换过程中得动画
     *  completion              转换完成
     */
    [self.fatherVC addChildViewController:newController];
    [self.fatherVC transitionFromViewController:oldController toViewController:newController duration:0.2 options:UIViewAnimationOptionLayoutSubviews animations:nil completion:^(BOOL finished) {
        if (finished) {
            [newController didMoveToParentViewController:self.fatherVC];//确认关系
            //移除上一个
            [oldController willMoveToParentViewController:nil];
            [oldController removeFromParentViewController];
            self.currentVC = newController;
        }
        else{
            self.currentVC = oldController;
        }
    }];
    
    
    
}


demo下载链接http://download.csdn.net/download/shenyingqiang/9080771


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值