- 首先是导航控制器下的视图结构
导航控制器的三个区:
导航区:导航控制器的navigationBar,管NSArray<UINavigationItem *> *items;数组
内容区:用于展示导航控制器字控制器的视图
toolbar区:底部工具条,默认隐藏-
导航条的隐藏和展示:
通过navigationBar.translucent = YES/NO调节。
透明情况下:
内容区从屏幕顶部开始, 控制器view的frame为 0 0 screenW screenH(控制器的View的frame相对于UIViewControllerWrapperView计算)
透明情况下,让控制器的展示区从导航条底部开始:self.edgesForExtendedLayout = UIRectEdgeNone;设置后,展示区的高度同样-64px。同时automaticallyAdjustsScrollViewInsets失效,scrollView的bounds不自动下移。
测试:UIViewControllerWrapperView = self.view.superView。更改bounds也可以让self.view下移64,
导航条不透明情况下:
展示区从导航条下开始 。
导航条不透明情况让展示区顶部从屏幕顶部开始:self.extendedLayoutIncludesOpaqueBars = YES; 同时automaticallyAdjustsScrollViewInsets生效。同时automaticallyAdjustsScrollViewInsets自动生效,scrollView的bounds自动下移。无论导航条是否透明,UILayoutContainerView、UINavigationTransitionView、UIViewControllerWrapperView都是和屏幕尺寸一致的,变化的只是展示区域的frame,即子控制器的view的frame。
测试:导航控制器下view加载:只要在控制器view不是从顶部0开始的情况下,控制器的view的y和height都是不准确的,当子控制器的viewDidAppear的时候,它的frame是会被重新定义成展示区的尺寸。我把展示区理解成子控制器viewDidAppear后的frame。 导航条透明度的调节:
方法一:通过setBackgroundImage调节。
viewDidLoad、viewWillAppear设置setBackgroundImage为一张透明度为1.0的图片话,相当于设置navigationBar.translucent = NO,展示区下移64px,高度减少64px。
viewDidAppear设置setBackgroundImage为一张透明度为1.0的图片话,相当于设置navigationBar.translucent = NO。但是当前控制器不会显现,展示区还是0px,高度还是屏幕的尺寸,内部的scrollView的bounds还是会自动加64px。pop回上一层控制器后,展示区下移64px,高度减少64px。如果设置setBackgroundImage为一张透明度小于1.0的图片话,就不会出现navigationBar.translucent状态不会修改。
解决的设置非透明图片后,顶栏透明自动关闭的问题:
viewDidLoad设置
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:JKRColor(255, 255, 0, 1.0)] forBarMetrics:UIBarMetricsDefault];
self.extendedLayoutIncludesOpaqueBars = YES;
viewWillDisappear设置
self.navigationController.navigationBar.translucent = YES;
解决设置完setBackgroundImage为一张非透明图片之后,展示区顶部回到0位置:再设置self.navigationController.navigationBar.translucent = YES;会回恢复展示区y为0的位置,但是设置的图片会自动加一些透明度。
会出现的问题:如果设置setBackgroundImage同时设置barTinkColor,那么图片透明会漏出_UIBarBackground的颜色。
如果设置上一级的控制器设置了setBackgroundImage,下一级的控制器设置setBackgroundImage图片为透明色后,底部_UIBarBackground的变为不透明,漏出黑色,不能穿透显示底部视图。
方法二:通过修改_UIBarBackground的背景色
首先viewDidLoad中定义当前控制器的导航条为非透明状态,展示区不自动下移。
设置导航条背景色被透明。
遍历导航条获取到_UIBarBackground
根据透明度设置其颜色
pop时,即viewWillDisappear时重新定义导航条为透明
遇到的问题:当侧滑并返回不POP的时候,当前控制器的导航条的_UIBarBackground背景色虽然透明,但是导航条还是白色,观察发现,因为POP一半的时候走了viewWillDisappear并执行self.navigationController.navigationBar.translucent = YES;返回的时候,导致导航条内部增加了UIVisualEffectView。我尝试在viewDidAppear中遍历出这个视图移除,但是没有效果。发现控制器的view加载成功后,再次对导航条修改必须要等viewDidAppear后一段时间才可以,没有找出来原因。代码如下:
5.导航条下划线的隐藏:
方法一:设置navigationBar的clipsToBounds。问题:navigationBar为44高度,有背景色的时候会发现问题。
方法二:遍历出下划线的UIImageView并隐藏。原理:因为下划线的高度为0.333,以高度不大于0.4为条件便利导航条的子视图。
6.Item间距问题。
UIBarButtonItem *itemGap = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
itemGap.width = 80;
把间距的item添加到items对象数组中要添加间距的两个对象之间即可