zoukankan      html  css  js  c++  java
  • 自定义导航视图控制器切换

    在iOS开发过程中,通常我们会使用UINavigationController,UITabbarController等苹果提供的视图控制器来切换我们的视图。在iOS5之前,如果要自定义容器视图控制器很麻烦,比如你要考虑到子视图的生命周期,当设备旋转时的情况等,好在iOS5中苹果提供了添加视图控制器(addChildViewController)等管理视图控制器的API,这样我们就能使用此API来自定义自己的视图控制器了,这篇文章只要介绍如何使用此API实现UITabbarController的基本功能。

    开始

    使用过UITabbarController的都知道,UITabbarController可以在多个UIViewController中切换,来显示多个界面,先来看一下层级关系:

    TabbarController作为根视图,然后添加了一个ChildViewController,最后用户看到内容是ChildViewController的视图内容和底部的TabBar

    首先我们新建一个新的工程,选择Single View Application,启用StoryBoard,将其默认的ViewController作为ContainerViewController,然后创建两个新的ViewController,分别作为两个childViewController,这样目录中就有这些文件:

    我们先进入StoryBoard拖入两个UIButton,给两个button设置tag:

    然后创建两个ViewController,这里我启用了xib,设置一下ViewController的背景色:

    这里我一个设置了绿色,还有个设置了棕色,还分别在每个ViewController上添加了UILabel,用于区分

    然后进入ContainerViewController.m,声明以下私有变量和方法:

    1.@interface ContainerViewController () {
    2.FirstViewController *_firstViewController;
    3.SecondViewController *_secondViewController;
    4. 
    5.NSMutableArray *_viewControllers;
    6.}

    - (IBAction)buttonTouched:(id)sender;

    FirstViewController和SecondViewController是两个ChildViewController,_viewControllers则是保存ChildViewController的数组,再去StoryBoard关联下点击事件

    在viewDidLoad中初始化:

    01.- (void)viewDidLoad
    02.{
    03.[super viewDidLoad];
    04. 
    05._viewControllers = [@[] mutableCopy];
    06._firstViewController = [[FirstViewController alloc] initWithNibName:@'FirstViewController' bundle:nil];
    07._secondViewController = [[SecondViewController alloc] initWithNibName:@'SecondViewController' bundle:nil];
    08. 
    09.[_viewControllers addObject:_firstViewController];
    10.[_viewControllers addObject:_secondViewController];
    11. 
    12.[self loadViewControllerAtIndex:0];
    13.}

    实例化了两个ViewController,然后将两个ViewController添加至数组中

    关键部分来了,loadViewControllerAtIndex用于切换视图控制器,以下是实现:

    01.- (void)loadViewControllerAtIndex:(NSInteger)index {
    02.NSInteger nextIndex = 0;
    03.if (index == 0) {
    04.nextIndex = 1;
    05.else if (index == 1) {
    06.nextIndex = 0;
    07.}
    08. 
    09.UIViewController *fromViewController = _viewControllers[nextIndex];// 获取当前viewController
    10.UIViewController *toViewController = _viewControllers[index];// 获取将要切换的viewController
    11. 
    12.  //
    13.if (self.childViewControllers.firstObject == toViewController) {
    14.return;
    15.}
    16. 
    17.if (self.childViewControllers.count > 0) {
    18.self.view.userInteractionEnabled = NO;// 切换过程中禁用操作,等切换动画结束后恢复
    19.[fromViewController willMoveToParentViewController:nil];// fromViewController将要移除
    20.[self addChildViewController:toViewController];// 将toViewController添加至ContainerViewController
    21. 
    22.     // 设置view的frame
    23.if (index == 1) {
    24.toViewController.view.frame = [self nextViewStartFrame];
    25.else {
    26.toViewController.view.frame = [self preViewStartFrame];
    27.}
    28. 
    29.     // 官方提供的切换动画API,在这里执行切换动画
    30.[self transitionFromViewController:fromViewController toViewController:toViewController duration:0.25options:UIViewAnimationOptionCurveEaseInOut animations:^{
    31.         // 执行动画
    32.if (index == 1) {
    33.fromViewController.view.frame = [self preViewStartFrame];
    34.toViewController.view.frame = [self newViewStartFrame];
    35.else {
    36.fromViewController.view.frame = [self nextViewStartFrame];
    37.toViewController.view.frame = [self newViewStartFrame];
    38.}
    39.} completion:^(BOOL finished) {
    40.       // 动画执行完毕,从父视图添加或移除层级关系
    41.if (finished) {
    42.[toViewController didMoveToParentViewController:self];
    43.[fromViewController removeFromParentViewController];
    44.self.view.userInteractionEnabled = YES;
    45.}
    46.}];
    47.else {
    48.[self addChildViewController:toViewController];
    49.[self.view addSubview:toViewController.view];
    50.[toViewController didMoveToParentViewController:self];
    51.}
    52.}

    - (CGRect)newViewStartFrame {

        returnCGRectMake(0.0, 0.0, 320.0, 500.0);

    }

    - (CGRect)nextViewStartFrame {

        returnCGRectMake(320.0, 0.0, 320.0, 500.0);

    }

     - (CGRect)preViewStartFrame {

        returnCGRectMake(-320.0, 0.0, 320.0, 500.0);

    }

    这个函数用于切换视图,使用addChildViewController把要添加的ViewController添加至ContainerViewController,移除不需要显示的。添加一个ViewController有几个步骤:

    1. [self addChildViewController:toViewController];  添加至当前viewController

    2. [self.view addSubView:toViewController.view];   添加view至self.view中

    3. [toViewController didMoveToParentViewController:self];  当添加完成后要调用此方法来告知已经移动到父视图控制器中

    移除一个ViewController也有几个步骤:

    1. [fromViewController willMoveToParentViewController:nil];  参数传入nil说明将要移除视图

    2. [fromViewController.view removeFromSuperView];  从父视图中移除fromViewController.view

    3. [fromViewController removeFromParentViewController];  将fromViewController从父视图层级中移除

    想要添加和移除ViewController这几个步骤是必要的,但是这里由于使用了transitionFromViewController:toViewController:duration:options:animations:completion:这个方法,它会先将toViewController.view添加至superView,然后执行动画,所以省略了[self.view addSubView:toViewController.view]

    这样切换函数就算完成了,然后我们实现按钮事件函数:

    1.- (IBAction)buttonTouched:(id)sender {
    2.if (((UIButton *)sender).tag == 1) {        
    3.[self loadViewControllerAtIndex:0];
    4.else {
    5.[self loadViewControllerAtIndex:1];
    6.}
    7.}

    点击不同的按钮切换不同的界面,最后运行效果如下:

    这里只是大致实现了下切换效果,在iOS7中新增的UIViewControllerContextTransitioning和UIViewControllerAnimatedTransitioning增强了对自定义的切换,这篇文章做了详细说明http://objccn.io/issue-12-3/

  • 相关阅读:
    POJ 3267 The Cow Lexicon(动态规划)
    POJ 1125 Stockbroker Grapevine(最短路径Floyd算法)
    HDU 2374 || SDUT2386 A Game with Marbles(简单题)
    JavaScript之scrollTop、scrollHeight、offsetTop、offsetHeight等属性学习笔记
    基于SNMP的MIB库访问实现的研究
    一个兼容大多数浏览器 的 图片滚动的js
    C#获取本地计算机名,IP,MAC地址,硬盘ID
    中文首字母搜素的实现 sql函数
    xml文档的加密与解密
    修改Windows 2003 server远程桌面端口3389
  • 原文地址:https://www.cnblogs.com/W-Kr/p/5095268.html
Copyright © 2011-2022 走看看