简介

  导航视图控制器是一个特殊的容器视图控制器,它可以维护有明确层次关系的视图之间的切换。我们可以打开模拟器或者你的iPhone看看设置功能,这里就是一个典型的对导航视图控制器的应用,如下图所示。很明显,导航视图控制器维护了一个栈结构,这是一种先进后出(FILO)的结构,我们将一个一个的视图压入栈中,当我们想返回的时候就可以依次出栈。

iOS开发系列课程(05) --- 导航视图控制器_视图控制器

创建导航控制器

  • -initWithRootViewController::在创建导航控制器时指定根视图控制器
  • -initWithNavigationBarClass:toobarClass::用指定的导航条创建导航视图控制器

控制器的入栈和出栈

  • -pushViewController:animated:方法:将一个视图控制器压入栈中
  • -popViewControllerAnimated:方法:从栈中弹出一个视图控制器
  • -popToRootViewControllerAnimated:方法:从栈中直接弹出根视图控制器
  • -popToViewController:animated:方法:从栈中弹出指定的视图控制器

iOS开发系列课程(05) --- 导航视图控制器_视图控制器_02

  可以通过UINavigationController的viewControllers属性获得其栈中保存的所有视图控制器;topViewController可以获得栈顶的视图控制器。

UINavigationBar

  一个导航视图控制器通常是由以下几个部分构成的:

iOS开发系列课程(05) --- 导航视图控制器_ios开发_03

导航条半透明以及相关坐标计算

  导航视图控制器会维持一个导航条(UINavigationBar),这个导航条被所有的视图控制器共享,可以通过UINavigationController对象navigationBar属性获得导航条,再通过下面的属性设置其半透明效果,注意对导航条的设置将对所有的视图控制器生效。

  • translucent属性:设置导航条是否半透明,默认值是YES。对此属性的设置会影响到坐标的计算,因为导航条有44点的高度。例如在视图控制控制器中放置一个按钮,其frame属性的第二个参数设置为100,那么在设置半透明为YES和NO的情况下按钮的呈现效果如下图所示。可以看出设置半透明后的按钮坐标计算是以窗口顶端为参考系的,而不透明的时候按钮坐标是相对于导航条的,相差了44个点。

iOS开发系列课程(05) --- 导航视图控制器_ios开发_04

  

iOS开发系列课程(05) --- 导航视图控制器_导航条_05

设置背景图片

  • -setBackgroundImage:forBarMetrics:
  • -setBackgroundImage:forBarPosition:barMetrics:

说明:UIBarPostion和UIBarMetrics都是枚举类型,前者表示导航栏的位置;后者表示导航栏的外观。前者可能的取值包括:UIBarPositionAny(不指定位置)、UIBarPositionBottom(位于视图底部)、UIBarPositionTop(位于视图顶部)和UIBarPositionTopAttached(位于屏幕顶部同时也在其视图的顶部);后者可能的取值包括:UIBarMetricsDefault(设备默认的外观)、UIBarMetricsCompact(手机尺寸的外观)等。

隐藏和显示导航条

  • navigationBarHidden属性:是否隐藏导航控制栏

UINavigationItem

  通过视图控制器的navigationItem属性可以获得和视图控制器对应的导航栏项,该属性是只读的,但是通过它的子属性可以对UINavigationItem进行定制。可以定制的内容包括:

  • leftBarButtonItem/leftBarButtonItems属性:定制左侧导航项
  • rightBarButtonItem/rightBarButtonItems属性:定制右侧导航项
  • backBarButtonItem属性:定制返回项
  • title属性:导航项的标题
  • prompt属性:导航项的提示
  • titleView属性:导航项标题视图,该属性可以是任意UIView及其子类型,因此可以在此随意定制自己想要的东西

说明:由于navigationItem是每个视图持有自己的navigationItem,因此可以为每个视图定制不同的导航项。

  如果当前视图控制器通过navigationItem设置了leftBarButtonItem,则显示当前视图控制器设置好的leftBarButtonItem;如果当前视图控制器没有设置leftBarButtonItem,且当前视图控制器不是根视图控制器,显示上一层的backBarButtonItem;如果上一层没有指定backBarButtonItem,系统将根据上一层视图控制器的标题自动生成一个返回按钮;如果当前视图控制器没有设置leftBarButtonItem且当前视图控制器是根视图控制器,则左边不显示任何东西。

  如果当前视图控制器通过navigationItem属性定制了titleView,那么将会显示自定义的titleView,titleView的高度不应该超过导航条的高度;如果当前视图控制器没有定制titleView,系统会根据当前视图控制器的标题或者navigationItem的标题创建一个UILabel来显示此标题;navigationItem的标题优于视图控制器的标题。

强调:UINavigationController本身并不显示无需定制,UINavigationBar属于导航控制器(子对象),它使被多个视图共享的,当你切换视图控制器时,导航栏并没有切换,如果需要定制导航视图控制器就需要定制导航栏以及导航栏上的项目UINavigationItem。我们可以让每个视图控制器都有自己的UINavigationItem,并按照自己的意愿来创建它。

  下面通过代码对上述内容加以展示。

创建文字和图片UIBarButtonItem

// 重设rightBarButtonItem
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStyleDone target:self action:@selector(onClick:)];

    //重设leftBarButtonItem
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"itemImage1"] landscapeImagePhone:[UIImage imageNamed:@"itemImage2"] style:UIBarButtonItemStyleBordered target:nil action:nil];

创建系统自带的UIBarButtonSystemItem

UIBarButtonItem * item1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:nil action:nil];
    UIBarButtonItem * item2 = [[UIBarButtonItem alloc] initWithTitle:@"OK" style:UIBarButtonItemStylePlain target:nil action:nil];

    // 使用自定义视图,创建barButtonItem
    UISwitch * sw = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
    [sw addTarget:self action:@selector(pushNextViewController) forControlEvents:UIControlEventValueChanged];

    // barButton官方推荐大小是20*20
    UIBarButtonItem * item3 = [[UIBarButtonItem alloc] initWithCustomView:sw];

    // 将多个item添加到右侧
    self.navigationItem.rightBarButtonItems = @[item1, item2, item3];

定制backBarButtonItem

UIButton *goBackButton = [UIButton buttonWithType:UIButtonTypeSystem];
    goBackButton.frame = CGRectMake(10, 10, 60, 40);
    [goBackButton addTarget:self action:@selector(goBackButtonClicked) forControlEvents:UIControlEventTouchUpInside];
    [goBackButton setTitle:@"滚蛋" forState:UIControlStateNormal];
    UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:goBackButton];
    self.navigationItem.leftBarButtonItem = barItem;

UIToolbar

  每个导航控制器,还配备了工具条(44坐标高),默认隐藏,可以通过将导航视图控制器的toolBarHidden属性设置为NO使其显示。工具条属于UINavigationController,一个导航控制器,只有一个工具条。工具条上的toolBarItem属于每个视图控制器,每个视图控制器可以单独定制工具条上的每个项。

显示UINavigationController自带的UIToolbar

  • toolBarHidden属性:设置为NO可以显示自带的工具条

设置UIToolbar的背景图

self.navigationController.toolbarHidden = NO;
    UIImage *bgImage = [UIImage imageNamed:@"toolBar"];
    [navigationController.toolbar setBackgroundImage:bgImage forToolbarPosition:UIBarPositionBottom barMetrics:UIBarMetricsDefault];
    [self.navigationController.toolbar setTintColor:[UIColor whiteColor]];

向UIToolbar中增加UIBarButtonItem

UIBarButtonItem * item1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:nil action:nil];
    UIBarButtonItem * item2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemBookmarks target:nil action:nil];
    UIBarButtonItem * item3 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:nil action:nil];
    UIBarButtonItem * spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    self.toolbarItems = @[item1, spaceItem, item2, spaceItem, item3];

UIAppearance

UIAppearrance的作用

  从iOS 5开始,UIKit中提供了一个叫做UIAppearance的协议,通过该协议可以轻松的统一你的界面,它提供如下两个方法:

  • (id)appearance:通过它可以修改所有的指定类型的视图的UI
  • (id)appearanceWhenContainedIn:(Class <>)ContainerClass,…:可以指定要修改的类型包括哪些

修改导航样式

[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil] setBackgroundImage:myNavBarButtonBackgroundImage forState:state barMetrics:metrics];
    [[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], [UIPopoverController class], nil] setBackgroundImage:myPopoverNavBarButtonBackgroundImage forState:state barMetrics:metrics];
    [[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], nil]
        setBackgroundImage:myToolbarButtonBackgroundImage forState:state barMetrics:metrics];
    [[UIBarButtonItem appearanceWhenContainedIn:[UIToolbar class], [UIPopoverController class], nil] setBackgroundImage:myPopoverToolbarButtonBackgroundImage forState:state barMetrics:metrics];