iOS导航栏使用总结

zhangdianbing 8个月前
   <p>目录:</p>    <p>一、设置导航栏样式</p>    <p>二、自定义导航栏返回按钮后侧滑不可用问题</p>    <p>三、隐藏导航栏底部的分割线</p>    <p>四、导航栏引起的布局问题</p>    <p>一、设置导航栏样式</p>    <p>设置导航栏的样式可分为全局设置与局部设置;</p>    <p>1.全局设置</p>    <p>全局设置一般的都是在AppDelegate中设置,这样整个app都会生效,相关的代码与效果图如下:</p>    <pre>  <code class="language-objectivec">//1.设置导航栏背景颜色  [[UINavigationBar appearance] setBarTintColor:[UIColor orangeColor]];        //2.设置导航栏背景图片  [[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"navigationBarImg"] forBarMetrics:UIBarMetricsDefault];        //3.设置导航栏标题样式  [[UINavigationBar appearance] setTitleTextAttributes: [NSDictionary dictionaryWithObjectsAndKeys:                                                             [UIColor purpleColor], NSForegroundColorAttributeName,                                                             [UIFont boldSystemFontOfSize:25], NSFontAttributeName, nil]];        //4.设置导航栏返回按钮的颜色  [[UINavigationBar appearance] setTintColor:[UIColor greenColor]];  //5.设置导航栏隐藏  [[UINavigationBar appearance] setHidden:YES];</code></pre>    <p style="text-align:center"><img src="https://simg.open-open.com/show/3317b4c5739a9b4e3c357b946514abf3.png"></p>    <p>设置导航栏样式效果图</p>    <p>2.局部设置</p>    <p>全局设置后,如果只有其中几个页面导航栏样式不同,那么我们可以使用局部设置。</p>    <p>注意1:局部设置与全局设置方法相同,但调用方法的对象变成了"self.navigationController.navigationBar"</p>    <p>注意2:局部设置必须遵循一个原则:"进入页面时修改,离开页面时还原”。</p>    <p>比如我们进入一个页面,需要设置当前导航栏的背景色为灰色,使用如下方法:</p>    <pre>  <code class="language-objectivec">//进入页面时设置颜色:灰色  - (void)viewWillAppear:(BOOL)animated{      [super viewWillAppear:animated];      [self.navigationController.navigationBar setBarTintColor:[UIColor grayColor]];  }  //离开页面时还原为全局设置:橙色  - (void)viewWillDisappear:(BOOL)animated{      [super viewWillDisappear:animated];      [self.navigationController.navigationBar setBarTintColor:[UIColor orangeColor]];  }</code></pre>    <p>二、解决自定义导航栏返回按钮后侧滑不可用问题</p>    <p>iOS导航栏自带的返回按钮形式单一,所以大多情况下,我们都需要自定义导航栏返回按钮。但是此时我们却发现页面的侧滑返回功能不可用了。为了解决这个问题,我们需要在App中使用我们自定义的导航控制控制器,示例代码如下:</p>    <pre>  <code class="language-objectivec">#import “BaseNavigationController.h"  //第一步:设置自定义导航控制器使用UIGestureRecognizerDelegate  @interface BaseNavigationController ()  <uigesturerecognizerdelegate>     @end  @implementation BaseNavigationController  - (void)viewDidLoad {      [super viewDidLoad];      //第二步:设置自定义导航控制器的侧滑手势的代理      self.interactivePopGestureRecognizer.delegate = self;  }     //第三步:实现代理方法  - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{      if (self.childViewControllers.count == 1) {          // 表示用户在根控制器界面,就不需要触发滑动手势,          return NO;      }      return YES;  }  @end  </uigesturerecognizerdelegate></code></pre>    <p>三、隐藏导航栏底部的分割线</p>    <p>隐藏导航底部分割线也是我们偶尔会遇到的开发需求,首先我们可以通过Xcode的Debug View Hierarchy功能查看导航栏的视图结构,效果如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/e9530e32bdd2c16dbd126f76e8f1887d.png"></p>    <p>导航栏视图层级图</p>    <p>从图中可以看出,导航栏的底部分割线是一个UIImageView对象,而且高度只有0.5,所以我们可以据此获取到导航栏的底部分割线对象,在一个视图控制器中实现此需求,代码如下:</p>    <pre>  <code class="language-objectivec">#import "TestViewController.h"  @interface TestViewController ()  //第一步:设置一个属性,存放导航栏底部分割线对象  @property (nonatomic, strong) UIImageView *navBarBottomImage;  @end  @implementation TestViewController  - (void)viewDidLoad {      [super viewDidLoad];      ////第三步:获取导航栏底部分割线对象      UIImageView *navBarBottomImage = [self findNavBarBottomImage:self.navigationController.navigationBar];      self.navBarBottomImage = navBarBottomImage;   }  //第四步:设置分割线的显示或隐藏  //进入页面隐藏分割线  - (void)viewWillAppear:(BOOL)animated{      [super viewWillAppear:animated];          self.navBarBottomImage.hidden = YES;  }  //离开页面时显示分割线  -(void)viewWillDisappear:(BOOL)animated{      [super viewWillDisappear:animated];      self.navBarBottomImage.hidden = NO;  }  //第二步:添加用于获取导航栏分割线的方法  //导航栏底部分割线是一个UIImageView,且高度不超过1.0个高度,可据此查找此对象  -(UIImageView *)findNavBarBottomImage:(UIView *)view {      if ([view isKindOfClass:UIImageView.class] && view.bounds.size.height <= 1.0) {          return (UIImageView *)view;      }      for (UIView *subview in view.subviews) {          UIImageView *imageView = [self findNavBarBottomImage:subview];          if (imageView) {              return imageView;          }      }      return nil;  }</code></pre>    <p>四、导航栏引起的布局问题</p>    <p>1.内容偏移属性:automaticallyAdjustsScrollViewInsets</p>    <p>automaticallyAdjustsScrollViewInsets是视图控制器的一个属性,默认为YES,用于优化滑动类视图(继承于UIScrollView的视图)在视图控制里的显示:</p>    <p>iOS系统的导航栏UINavigationBar与标签栏UITabBar默认都是半透明模糊效果,在这种情况下系统会对视图控制器的UI布局进行优化: 视图控制器里面第一个被添加进去的视图是滑动类视图,并且其Frame是整个屏幕大小时,系统会自动调整其contenInset,以保证滑动视图里的内容不被UINavigationBar与UITabBar遮挡。</p>    <p>但是对于普通的视图,此时我们仍然需要注意:非滑动视图的布局仍然要考虑导航栏和标签栏高度,注意不被遮挡,比如布局的时候加上导航栏高度,以免内容被导航栏遮挡。</p>    <p>我们可以通过一段代码来测试一下效果,在默认导航栏(半透明)的视图控制器里添加如下代码:</p>    <pre>  <code class="language-objectivec">//UITextView是滑动视图,内容自动向下偏移,不会被导航栏覆盖  UITextView *leftTextView = [[UITextView alloc] init];  leftTextView.frame = CGRectMake(0, 0,100, kDeviceHeight); //  leftTextView.backgroundColor = [UIColor lightGrayColor];  leftTextView.text = @"君不见,黄河之水天上来,奔流到海不复回。君不见,高堂明镜悲白发,朝如青丝暮成雪。人生得意须尽欢,莫使金樽空对月。天生我材必有用,千金散尽还复来。";  leftTextView.font = [UIFont systemFontOfSize:18];  leftTextView.editable = NO;  [self.view addSubview:leftTextView];        //UIView是非滑动视图,内容被导航栏部分覆盖  UIView *rightView= [[UIView alloc] initWithFrame:CGRectMake(150, 0, 100, 100)];  rightView.backgroundColor = [UIColor redColor];  [self.view addSubview:rightView];</code></pre>    <p style="text-align:center"><img src="https://simg.open-open.com/show/3f01f38756ebde4db6083d03d23c8b31.png"></p>    <p>导航栏透明情况下,滑动视图自动偏移,普通视图被遮挡</p>    <p>其实,这种系统的优化也是可以控制关闭的,关闭优化之后,滑动视图就会和普通视图一样,如果还设置其布局的原点是(0,0),其内容就会被导航栏所覆盖,关键代码如下:</p>    <pre>  <code class="language-objectivec">//automaticallyAdjustsScrollViewInsets在11.0后失效,所以需要判断  if (@available(iOS 11.0,*)) {         scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;  }else{         //automaticallyAdjustsScrollViewIn,关闭自动偏移的系统优化         self.automaticallyAdjustsScrollViewInsets = NO;  }</code></pre>    <p>2.边缘延伸属性:edgesForExtendedLayout</p>    <p>edgesForExtendedLayout也是视图控制器的布局属性,默认值是UIRectEdgeAll,即:当前视图控制器里各种UI控件会忽略导航栏和标签的存在,布局时若设置其原点设置为(0,0),视图会延伸显示到导航栏的下面被覆盖。</p>    <p>所以我们可以设置 <strong>self.edgesForExtendedLayout=UIRectEdgeNone</strong> ,此时视图控制器里内容就会避开导航栏和标签栏了,依然是上面的leftTextView和rightView,设置了UIRectEdgeNone之后的效果图如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/10c150613b9066392cb79fe742cfae08.png"></p>    <p>self.edgesForExtendedLayout=UIRectEdgeNone</p>    <p>3.导航栏透明属性translucent</p>    <p>上述两种属性都是在解决导航栏半透明情况下的布局问题,但是如果我们的需求就是导航栏不透明,那么视图控制器里的控件就会默认从(0,64)开始布局了,设置导航栏不透明的方法如下:</p>    <pre>  <code class="language-objectivec">self.navigationController.navigationBar.translucent= NO;</code></pre>    <p>来自:https://www.jianshu.com/p/50cd38f2772c</p>    <p> </p>