navigation's skills




navigation技巧

[A].获取 导航栏所有的视图控制器

获取 导航栏所有的视图控制器,选择想要跳转的那个视图控制器直接传值!无需考虑“反向传值”!!

展示例子🌰:

跳转关系:
MyInfosViewController(我的信息) → VerifyIdentityViewController(验证 手机号) → WriteNewPhoneNumberViewController(更改手机号)

各界面的层次关系:



修改旧的手机号成功!
跳转到“我的信息”界面,并把手机号传到“我的信息”界面!

NSArray *pushVCAry = [self.navigationController viewControllers];
//pushVCAry.count-3  回到MyInfosVC中去
MyInfosViewController *popVC = [pushVCAry objectAtIndex:pushVCAry.count-3]; //(-1:当前层)

//可直接“进行传值”
popVC.transmitPhoneNumberStr = _phoneNumTF.text; 
[self.navigationController popToViewController:popVC animated:YES];


也可以直接判断
要跳转回去的ViewController 是否为 “ MyInfosViewController”类型?

NSArray *pushVCAry = [weakSelf.navigationController viewControllers];
UIViewController *popVC;

for (int i = 0; i < pushVCAry.count; i ++) {
  if ([pushVCAry[i] isKindOfClass:[MyInfosViewController class] ]) {
     popVC = pushVCAry[i];
  }
}

//可直接“进行传值”
popVC.transmitPhoneNumberStr = _phoneNumTF.text; 
[self.navigationController popToViewController:popVC animated:YES];




[B].判断在当前UIViewController中,viewWillDisappear的时候是push还是pop
- (void)viewWillDisappear:(BOOL)animated {
        NSArray *viewControllers = self.navigationController.viewControllers;
        if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
            // View is disappearing because a new view controller was pushed onto the stack
            NSLog(@"New viewcontroller was pushed");
        } else if ([viewControllers indexOfObject:self] == NSNotFound) {
            // View is disappearing because it was popped from the stack
            NSLog(@"Viewcontroller was popped");
        }
    }














导航栏 navigationBar

  • 系统自带图标文字颜色:(setTintColor

    [self.navigationController.navigationBar setTintColor:[UIColor whiteColor] ];
    


  • 标题文字的设置:(富文本 --- setTitleTextAttributes

    [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor redColor]}];
    


  • 半透明属性设置

    self.navigationController.navigationBar.translucent = NO;
    
    在iOS 6之前(包括iOS 6) translucent默认就是NO,在iOS 7之后就默认是YES了。





[A].隐藏 导航栏边框下面的黑线

一般:在“viewWillAppear”里(当前界面),隐藏 导航栏边下的黑线
在“viewWillDisappear”里(下个界面),再显示 导航栏边下的黑线

  • 方法一
    //隐藏 导航栏边下的黑线
    [self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
    

  • 方法二
    //隐藏 导航栏边下的黑线  
    self.navigationController.navigationBar.clipsToBounds = YES; 
    

  • 方法三

    获取导航栏边下黑线,再隐藏!!

    //获取 某个视图边下的黑线  
    - (UIImageView *)getNavBlackWithBar:(UIView *)bar {    
      if ([bar isKindOfClass:[UIImageView class]] && bar.frame.size.height < 1) {
          return (UIImageView *)bar;
      }
      for (UIView *views in bar.subviews) {
          UIImageView *imageView = [self getNavBlackWithBar:views];
          if (imageView) {
              return imageView;
          }
      }
      return nil;
    
    }
    


    使用:

    //获取 导航栏边下的黑线  
    UIImageView* blackLineImageView = [self getNavBlackWithBar:self.navigationController.navigationBar];
    //去掉导航栏边下的黑线  
    blackLineImageView.hidden = YES;
    




[B].返回按钮
  • 自己这一 ,设置 (Push到的)子层返回按钮

    //自己的返回按钮
    self.navigationController.navigationBar.backIndicatorImage = [UIImage imageNamed:@"navbar_icon_back"];//图片
    UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:nil action:nil ];
    self.navigationItem.backBarButtonItem = item;
    

    自带返回手势!!!
    有时候返回(设置背景图片)时,会产生卡顿!!!!!


  • 解决:在(Push到的)子层 ,设置 返回按钮

    //左侧 返回按钮
    UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
    //点击按钮  (pop操作)
    [backButton addTarget:self.navigationController action:@selector(popViewControllerAnimated:) forControlEvents:UIControlEventTouchUpInside];
    
    /** 设置 背景颜色:方便观察Button的大小 */
    //button.backgroundColor = [UIColor grayColor];
    
    /** 设置 图片 */
    UIImage *imgForButton = [UIImage imageNamed:@"navbar_icon_back"];
    [backButton setImage: imgForButton forState:UIControlStateNormal];
    
    /** 设置 文字 */
    NSString *titleStr = @"返回";
    [backButton setTitle:titleStr forState:UIControlStateNormal];
    //字体大小
    backButton.titleLabel.font = [UIFont systemFontOfSize:17.f];
    //字体颜色
    [backButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    
    
    /** 尺寸调整 */
    backButton.frame = CGRectMake(0, 0 , 100, 100); //硬编码:设置UIButton位置、大小
    //文本尺寸
    CGSize titleLabelSize = [titleStr sizeWithAttributes:@{NSFontAttributeName:backButton.titleLabel.font}];
    //图片尺寸
    CGSize buttonImageSize = imgForButton.size; 
    //最终的宽度:文本尺寸的宽度+图片尺寸的宽度
    backButton.frame = CGRectMake(0,0,buttonImageSize.width + titleLabelSize.width, buttonImageSize.height);
    
    
    //左侧的leftBarButtonItem,使用返回按钮
    UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    self.navigationItem.leftBarButtonItem = barButtonItem;
    



隐藏返回按钮
  • 上一层 视图控制器 (无字,且 无点击事件响应

    // 隐藏“返回”按钮    可点击(无字,且 无点击事件响应)
    self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:self action:nil];
      
    //⭐️将“返回”按钮的文字设置不在界面显示
    [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(NSIntegerMin, NSIntegerMin) forBarMetrics:UIBarMetricsDefault];
    


  • 下一层 视图控制器 (直接隐藏)

    // 隐藏“返回”按钮
    [self.navigationItem setHidesBackButton:YES];
    




[C].设置 图片背景 setBackgroundImage

使用的图片:

lucencyNavgationBar_ios7”:透明图片;
navgationBar_ios7”:蓝色渐变色图片。


基本设置格式
导航栏状态栏(作为整体)显示的都是图片!!

/** 设置为图片(状态栏+导航栏) */
UIImage * Nav_BG_img = [[UIImage imageNamed:@"navgationBar_ios7"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0) resizingMode:UIImageResizingModeStretch];//图片 自适应大小
[self.navigationController.navigationBar setBackgroundImage:Nav_BG_img forBarMetrics:UIBarMetricsDefault];
效果:


错误展示

导航栏背景图片(backgroundImage) 设置为 无图片image 或 “nil”。

//设置导航栏背景图片 为 无图片的image
[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault];

或者:

//设置导航栏背景图片 为 nil
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];


效果:


总结
  • 1.因为导航栏是同一个!而每个界面里导航栏造型 不同
    设置背景图片,改变导航栏的外观!需要对每个界面出现前(在“-(void)viewWillAppear:(BOOL)animated { }”里)进行设置!

    需要“-(void)viewWillAppear:(BOOL)animated { }”、“-(void)viewWillDisappear:(BOOL)animated { }”配合使用!

  • 2.使用图片背景来设置界面里导航栏造型时,能使 系统自带的“返回按钮,不然会出现“跳转卡顿”的现象!

    需在每个界面里,设置各界面的“返回按钮!(在当前层里,设置返回按钮)




让页面导航栏透明:(背景图片 设置为透明图片)

//透明的图片
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"lucencyNavgationBar_ios7"] forBarMetrics:UIBarMetricsDefault];

//去掉 透明导航栏边的黑边
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];

效果:



查看视图的层次关系:






一般操作:
在“-(void)viewWillAppear:(BOOL)animated { }”里面:
//透明的图片
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"lucencyNavgationBar_ios7"] forBarMetrics:UIBarMetricsDefault];
//去掉 透明导航栏边的黑边
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
在“-(void)viewWillDisappear:(BOOL)animated { }”里面,重置:
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
//显示 透明导航栏边的黑边
[self.navigationController.navigationBar setShadowImage:nil];


对于push到的界面:

根据下个界面的导航栏造型是否改变!
在下个界面的“-(void)viewWillAppear:(BOOL)animated { }”里,重新设置navigationBar背景图片!!




[D]. 隐藏导航栏
  • 显示 导航栏:
    最佳:
    [self.navigationController setNavigationBarHidden:NO animated:YES];

    不建议:
    self.navigationController.navigationBarHidden = NO;

    self.navigationController.navigationBar.hidden = NO;

    显示导航栏 效果:
    本层:当前界面
    下一层:push到的界面



  • 隐藏 导航栏:
    最佳:
    [self.navigationController setNavigationBarHidden:YES animated:YES];

    不建议:
    self.navigationController.navigationBarHidden = YES;

    self.navigationController.navigationBar.hidden = YES;

    隐藏导航栏 效果:
    本层:当前界面
    下一层:push到的界面



使用实例

仅仅在某个视图控制器中,隐藏navigationBar!

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    //隐藏 navigationBar
    [self.navigationController setNavigationBarHidden:YES animated:YES];
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    //显示 navigationBar
    [self.navigationController setNavigationBarHidden:NO animated:YES];
}

效果:




[E]. 适配 导航栏

当前视图控制器里的UIScrollView,自动适配导航栏
self.automaticallyAdjustsScrollViewInsets = NO; //自动适配 导航栏


修改当前视图控制器的“edgesForExtendedLayout”属性:
self.edgesForExtendedLayout = UIRectEdgeNone; //布局 从导航栏下面开始
将“edgesForExtendedLayout”属性 设置为UIRectEdgeNone,那么布局就是从导航栏下面开始!!!




[F]. 背景色设置

基本格式:“setBackgroundColor:

展示例子🌰:
[self.navigationController.navigationBar setBackgroundColor:[UIColor blueColor]];

UIImage * Nav_BG_img = [[UIImage imageNamed:@"navgationBar_ios7"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0) resizingMode:UIImageResizingModeStretch];//图片 自适应大小
[self.navigationController.navigationBar setBackgroundImage:Nav_BG_img forBarMetrics:UIBarMetricsDefault]; //跳转迟钝


背景图片” 和 “背景色” 的区别

但是使用 设置“背景色”,需要配合设置 状态栏颜色




barTintColor

涉及到UIVisualEffectView


在界面跳转时,导航栏颜色变化会有UIVisualEffectView的效果!一般不设置“setBarTintColor”。


展示例子🌰:
[self.navigationController.navigationBar setBarTintColor:[UIColor redColor] ];


背景图片(backgroundImage)”、“barTintColor” 和 “背景色(backgroundColor)” 的区别:

barTintColor:红色
















goyohol's essay

推荐阅读更多精彩内容