- 首先是導(dǎo)航控制器下的視圖結(jié)構(gòu)

導(dǎo)航控制器的三個(gè)區(qū):
導(dǎo)航區(qū):導(dǎo)航控制器的navigationBar,管NSArray<UINavigationItem *> *items;數(shù)組
內(nèi)容區(qū):用于展示導(dǎo)航控制器字控制器的視圖
toolbar區(qū):底部工具條,默認(rèn)隱藏-
導(dǎo)航條的隱藏和展示:
通過(guò)navigationBar.translucent = YES/NO調(diào)節(jié)。
透明情況下:
內(nèi)容區(qū)從屏幕頂部開(kāi)始, 控制器view的frame為 0 0 screenW screenH(控制器的View的frame相對(duì)于UIViewControllerWrapperView計(jì)算)
透明情況下,讓控制器的展示區(qū)從導(dǎo)航條底部開(kāi)始:self.edgesForExtendedLayout = UIRectEdgeNone;設(shè)置后,展示區(qū)的高度同樣-64px。同時(shí)automaticallyAdjustsScrollViewInsets失效,scrollView的bounds不自動(dòng)下移。
測(cè)試:UIViewControllerWrapperView = self.view.superView。更改bounds也可以讓self.view下移64,
導(dǎo)航條不透明情況下:
展示區(qū)從導(dǎo)航條下開(kāi)始 。
導(dǎo)航條不透明情況讓展示區(qū)頂部從屏幕頂部開(kāi)始:self.extendedLayoutIncludesOpaqueBars = YES; 同時(shí)automaticallyAdjustsScrollViewInsets生效。同時(shí)automaticallyAdjustsScrollViewInsets自動(dòng)生效,scrollView的bounds自動(dòng)下移。無(wú)論導(dǎo)航條是否透明,UILayoutContainerView、UINavigationTransitionView、UIViewControllerWrapperView都是和屏幕尺寸一致的,變化的只是展示區(qū)域的frame,即子控制器的view的frame。
測(cè)試:導(dǎo)航控制器下view加載:只要在控制器view不是從頂部0開(kāi)始的情況下,控制器的view的y和height都是不準(zhǔn)確的,當(dāng)子控制器的viewDidAppear的時(shí)候,它的frame是會(huì)被重新定義成展示區(qū)的尺寸。我把展示區(qū)理解成子控制器viewDidAppear后的frame。 導(dǎo)航條透明度的調(diào)節(jié):
方法一:通過(guò)setBackgroundImage調(diào)節(jié)。
viewDidLoad、viewWillAppear設(shè)置setBackgroundImage為一張透明度為1.0的圖片話,相當(dāng)于設(shè)置navigationBar.translucent = NO,展示區(qū)下移64px,高度減少64px。
viewDidAppear設(shè)置setBackgroundImage為一張透明度為1.0的圖片話,相當(dāng)于設(shè)置navigationBar.translucent = NO。但是當(dāng)前控制器不會(huì)顯現(xiàn),展示區(qū)還是0px,高度還是屏幕的尺寸,內(nèi)部的scrollView的bounds還是會(huì)自動(dòng)加64px。pop回上一層控制器后,展示區(qū)下移64px,高度減少64px。如果設(shè)置setBackgroundImage為一張透明度小于1.0的圖片話,就不會(huì)出現(xiàn)navigationBar.translucent狀態(tài)不會(huì)修改。
解決的設(shè)置非透明圖片后,頂欄透明自動(dòng)關(guān)閉的問(wèn)題:
viewDidLoad設(shè)置
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:JKRColor(255, 255, 0, 1.0)] forBarMetrics:UIBarMetricsDefault];
self.extendedLayoutIncludesOpaqueBars = YES;
viewWillDisappear設(shè)置
self.navigationController.navigationBar.translucent = YES;
解決設(shè)置完setBackgroundImage為一張非透明圖片之后,展示區(qū)頂部回到0位置:再設(shè)置self.navigationController.navigationBar.translucent = YES;會(huì)回恢復(fù)展示區(qū)y為0的位置,但是設(shè)置的圖片會(huì)自動(dòng)加一些透明度。

會(huì)出現(xiàn)的問(wèn)題:如果設(shè)置setBackgroundImage同時(shí)設(shè)置barTinkColor,那么圖片透明會(huì)漏出_UIBarBackground的顏色。
如果設(shè)置上一級(jí)的控制器設(shè)置了setBackgroundImage,下一級(jí)的控制器設(shè)置setBackgroundImage圖片為透明色后,底部_UIBarBackground的變?yōu)椴煌该?,漏出黑色,不能穿透顯示底部視圖。

方法二:通過(guò)修改_UIBarBackground的背景色

首先viewDidLoad中定義當(dāng)前控制器的導(dǎo)航條為非透明狀態(tài),展示區(qū)不自動(dòng)下移。
設(shè)置導(dǎo)航條背景色被透明。
遍歷導(dǎo)航條獲取到_UIBarBackground
根據(jù)透明度設(shè)置其顏色
pop時(shí),即viewWillDisappear時(shí)重新定義導(dǎo)航條為透明
遇到的問(wèn)題:當(dāng)側(cè)滑并返回不POP的時(shí)候,當(dāng)前控制器的導(dǎo)航條的_UIBarBackground背景色雖然透明,但是導(dǎo)航條還是白色,觀察發(fā)現(xiàn),因?yàn)镻OP一半的時(shí)候走了viewWillDisappear并執(zhí)行self.navigationController.navigationBar.translucent = YES;返回的時(shí)候,導(dǎo)致導(dǎo)航條內(nèi)部增加了UIVisualEffectView。我嘗試在viewDidAppear中遍歷出這個(gè)視圖移除,但是沒(méi)有效果。發(fā)現(xiàn)控制器的view加載成功后,再次對(duì)導(dǎo)航條修改必須要等viewDidAppear后一段時(shí)間才可以,沒(méi)有找出來(lái)原因。代碼如下:


5.導(dǎo)航條下劃線的隱藏:
方法一:設(shè)置navigationBar的clipsToBounds。問(wèn)題:navigationBar為44高度,有背景色的時(shí)候會(huì)發(fā)現(xiàn)問(wèn)題。
方法二:遍歷出下劃線的UIImageView并隱藏。原理:因?yàn)橄聞澗€的高度為0.333,以高度不大于0.4為條件便利導(dǎo)航條的子視圖。
6.Item間距問(wèn)題。
UIBarButtonItem *itemGap = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
itemGap.width = 80;
把間距的item添加到items對(duì)象數(shù)組中要添加間距的兩個(gè)對(duì)象之間即可