iOS 导航栏 知识总结

2016-05-30  本文已影响2605人  WeiHing

一点说明:本文中“导航控制器”区别于“视图控制器”存在


UINavigationController

UINavigationController
UINavigationController是一个导航控制器,它用来组织有层次关系的视图。导航控制器维护着一个视图控制器栈。在设计导航控制器时,UINavigationController默认也不会显示任何视图(这个控制器自身的UIView不会显示),需要指定用户看到的第一个视图,该视图控制器即是根控制器rootViewController,而且这个根控制器不会像其他子控制器一样被销毁,它是导航控制器栈中所有视图控制器的栈底。在UINavigationController中子控制器以栈的形式存储,只有在栈顶的控制器能够显示在界面中,一旦一个子控制器出栈则会被销毁。

子控制器入栈出栈相关方法
官方文档:You add and remove view controllers from the stack using segues or using the methods of this class. The user can also remove the topmost view controller using the back button in the navigation bar or using a left-edge swipe gesture.出栈:segue、method,移除栈顶:back button、left-edge swipe gesture


子控制器通过pop方法移除栈顶,先销毁的是子控制器自己本身,然后子控制器里面的View才被销毁,因为子控制器是持有View的。 导航控制下面的子控制器什么时候会被销毁

UINavigationBar与UINavigationItem的关系

UINavigationBar
UINavigationItem

UINavigationBar导航栏:继承自UIView


*它最典型的用法就是放在屏幕顶端,包含着各级视图的导航按钮。它最首要的属性是左按钮(返回按钮)、中心标题,还有可选的右按钮(不过实际上UINavigationBar好像并没有这些属性,应该是存在于UINavigationItem类中的)。你可以单独用导航栏,或者和导航控制器一起使用(后者最普遍)。
如果你使用导航控制器去管理不同屏幕内容之间的导航,导航控制器会自动创建NavigationBar,以及在合适的时候push\pop navigation items

UINavigationItem导航项:继承自NSObject


一个UINavigationItem对象管理展示在导航栏上的按钮和视图。当创建一个导航界面的时候,每个压入导航栈中的视图控制器都需要一个navigation item,它包含了展示在导航栏上的按钮和视图。导航控制器利用最顶层的两个视图控制器的navigation item来提供导航栏的内容。(可以通过子视图控制器(包括根视图控制器)的navigationItem属性访问这个导航项,修改其左右两边的按钮和标题的内容。)

记录一些需要注意的地方:

单独用导航栏UINavigationBar,(不是采用UINavigationController)
代码方式:

- (void)viewDidLoad{
    UINavigationBar *navBar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 44)];
    //添加NavigationBar到视图上
    [self.view addSubview:navBar];
    UINavigationItem *navItem = [[UINavigationItem alloc]initWithTitle:@"welcome page"];
    
    UIBarButtonItem *btnlogin = [[UIBarButtonItem alloc]initWithTitle:@"login" style:UIBarButtonItemStyleDone target:self action:@selector(login)];
    navItem.leftBarButtonItem = btnlogin;
    //把NavigationItem添加到导航栏上(进栈)
    [navBar pushNavigationItem:navItem animated:NO];
}

UIBarButtonItem

UIBarButtonItem继承自UIBarItem,再往上的继承NSObject


是专门放在UIToolbar or UINavigationBar上的控件,具有按钮的行为。它分左、右、返回UIBarButtonItem,可以把她们添加到UINavigationItem上去
UINavigationItem *navItem = [[UINavigationItem alloc]initWithTitle:@"welcome page"];
UIBarButtonItem *btnlogin = [[UIBarButtonItem alloc]initWithTitle:@"login" style:UIBarButtonItemStyleDone target:self action:@selector(login)];
navItem.leftBarButtonItem = btnlogin;

UIBarButtonItem有如下初始化方法:



第一种可以设置系统自带风格按钮UIBarButtonSystemItem。

比如:

1.使用代码方式创建导航

步骤:

1.friend视图控制器,设置左右导航栏按钮

#import <UIKit/UIKit.h>
@interface FriendViewController : UIViewController
@end

#import "FriendViewController.h"
#import "ContactViewController.h"
@interface FriendViewController ()

@end

@implementation FriendViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //根据实际运行结果看来(视图不断切换,但下面这句话只会打印一次):
    //因为是根视图控制器,永远不会被销毁,所以viewdidload只会执行一次。
    NSLog(@"childviewcontroller:%@",self.navigationController.childViewControllers);
    
    NSLog(@"%i",self.navigationController == self.parentViewController);//true
    
    self.navigationItem.title = @"friend";
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"edit" style:UIBarButtonItemStyleDone target:nil action:nil];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithImage:[UIImage imageNamed:@"User_normal"] style:UIBarButtonItemStyleDone target:self action:@selector(addPeople)];
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)addPeople{
    ContactViewController *contactVC = [[ContactViewController alloc]init];
    [self.navigationController pushViewController:contactVC animated:YES];
}
@end

2.contact视图控制器,添加右导航按钮,左导航按钮不设置默认显示上级视图控制器名称作为返回按钮

#import <UIKit/UIKit.h>
@interface ContactViewController : UIViewController
@end

#import "ContactViewController.h"
#import "AccountViewController.h"
@interface ContactViewController ()

@end

@implementation ContactViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 是子控制器,在视图不断切换的过程中,反复被创建和销毁;下面这句话多次打印出来。
    NSLog(@"childviewcontroller:%@",self.navigationController.childViewControllers);
    
    NSLog(@"%i",self.navigationController == self.parentViewController);
    
    self.view.backgroundColor = [UIColor whiteColor];//***注意***不设置切换会有卡顿
    [self setTitle:@"contact"];
    
    //设置下一级视图控制器导航返回按钮
    UIBarButtonItem *back = [[UIBarButtonItem alloc]initWithTitle:@"my contact" style:UIBarButtonItemStyleDone target:nil action:nil];
    self.navigationItem.backBarButtonItem = back;
    
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"account" style:UIBarButtonItemStyleDone target:self action:@selector(goToAccount)];
}

- (void)goToAccount{
    AccountViewController *accountVC = [[AccountViewController alloc]init];
    [self.navigationController pushViewController:accountVC animated:YES];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
@end
#import <UIKit/UIKit.h>
@interface AccountViewController : UIViewController
@end

#import "AccountViewController.h"
#import "FriendViewController.h"
@interface AccountViewController ()

@end

@implementation AccountViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"account";
    
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"toFriend" style:UIBarButtonItemStyleDone target:self action:@selector(goToFriend)];
}

- (void)goToFriend{
    //直接跳转到根控制器
    [self.navigationController popToRootViewControllerAnimated:YES];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
@end

4.初始化导航控制器并设置根视图控制器

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor whiteColor];
    [[UINavigationBar appearance]setBarTintColor:[UIColor yellowColor]];
    [[UINavigationBar appearance]setBarStyle:UIBarStyleBlack];    
    FriendViewController *friendVC = [[FriendViewController alloc]init];
    UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:friendVC];
    self.window.rootViewController = navController;
    [self.window makeKeyAndVisible];
    return YES;
}


*需要注意的地方:在使用UINavigationController的pushViewController:animated:执行入栈一个子控制器操作时,会出现"卡顿"现象。
原因:这是因为从iOS7开始, UIViewController的根view的背景颜色默认为透明色(即clearColor),所谓"卡顿"其实就是由于透明色重叠后,造成视觉上的错觉,所以这并不是真正的"卡顿"。
解决方法:只要在该UINavigationController所push的那个子控制器中设置背景颜色,即取缔默认的透明色 (即clearColor)
如:在viewDidLoad中写上 self.view.backgroundColor = [UIColor whiteColor];

// 注意:跳转到指定控制器的时候,要跳转到的目标控制器必须是在当前导航控制器的栈内的,不能是新创建的控制器
    NSArray *vcs = self.navigationController.childViewControllers;
    OneViewController *oneVc = (OneViewController *)vcs[1];
    [self.navigationController popToViewController:oneVc animated:YES];
}

** 注意:返回到指定控制器的时候,要跳转到的目标控制器必须是在当前导航控制器的栈内的,不能是新创建的控制器**

2.使用storyboard创建导航

1.在storyboard中拖拽一个UINavigationController。UINavigationController默认会带一个UITableViewController作为其根控制器。设置UITableViewController的标题为“Testing”,同时设置为静态表格并且包含两行,分别在单元格中放置一个UILabel命名为“A”和“B”
2.新建两个UITableViewController,标题分别设置为“A”、“B”
按住Ctrl拖拽“ Testing”的第一个表单元格到视图控制器“A”,同时选择segue为“show”,拖拽第二个表单元格到视图控制器“B”,同时选择segue为“show”。



到这里为止,可以通过点击两个单元格导航到A、B视图。

这里通过storyboard创建导航的关键是"segue"
Segue的工作方式分为以下几个步骤:
1.创建目标视图控制器(即A、B视图控制器)
2.创建Segue对象
3.调用源视图对象的prepareForSegue:sender:方法
4.调用Segue对象的perform方法将目标视图控制器推送到屏幕
5.释放Segue对象

先给Testing控制器绑定一个控制器文件(继承于UITableViewController)。然后选中连接A控制器的segue,设置它的identifier为"Segue",B同理



在Testing控制器对应文件中添加:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
  //  获得源视图控制器
    UITableViewController *testingVC = segue.sourceViewController;
  //获得目标视图控制器
    UITableViewController *desVC = segue.destinationViewController;
    NSLog(@"sourceController:%@,destinationController:%@",testingVC.navigationItem.title,desVC.navigationItem.title);
}

点击两个单元格,出现打印结果如下:对应上述第3步


在Testing视图控制器中放上左右导航按钮,并添加对应点击事件

- (IBAction)toA:(id)sender {
    [self performSegueWithIdentifier:@"ASegue" sender:self];
}
- (IBAction)toB:(id)sender {
    [self performSegueWithIdentifier:@"BSegue" sender:self];

}

运行程序,点击左右两个导航按钮,同样可以跳转到对应的A、B视图控制器,对应上述第4步。

什么是Segue(延伸)
Storyboard上每一根用来界面跳转的线,都是一个UIStoryboardSegue对象(简称Segue)

上一篇 下一篇

猜你喜欢

热点阅读