
當(dāng)我們使用UINavigationController時(shí),插入一個(gè)控制器,然后往這個(gè)控制器的view上加subview(比如一個(gè)tableView)時(shí),經(jīng)常會(huì)碰到tableView的實(shí)際展示跟自己設(shè)置的frame不一致的情況。這里就總結(jié)記錄一下平時(shí)自己遇到過(guò)的相關(guān)問(wèn)題。
iOS7之前控制器有一個(gè)屬性wantsFullScreenLayout。當(dāng)把它設(shè)置為YES時(shí),你添加的subview的y就是從屏幕的最頂部開(kāi)始算,包含navigationbar,設(shè)置為NO時(shí),則從navigationbar的bottom開(kāi)始算。因?yàn)閕OS7之前,navigationbar默認(rèn)一般是不透明的,所以wantsFullScreenLayout一般默認(rèn)為NO。從iOS7開(kāi)始,這個(gè)屬性被廢棄了,代替它的是三個(gè)新的屬性:edgesForExtendedLayout、extendedLayoutIncludesOpaqueBars、automaticallyAdjustsScrollViewInsets,今天重點(diǎn)說(shuō)的就是這三個(gè)經(jīng)常用的屬性。
edgesForExtendedLayout
The extended edges to use for the layout.
This property is applied only to view controllers that are embedded in a container such as UINavigationController. The window’s root view controller does not react to this property. The default value of this property is UIRectEdgeAll
這個(gè)屬性是通過(guò)擴(kuò)展子視圖的邊緣來(lái)適配屏幕,因?yàn)閕OS7之后鼓勵(lì)全屏,navigationbar變得半透明,所以這個(gè)屬性默認(rèn)為UIRectEdgeAll,及x和y是從屏幕的左上角開(kāi)始算的。比如設(shè)置tableView的frame如下:
self.tableView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 350);
這里為了防止automaticallyAdjustsScrollViewInsets的干擾,我們?cè)?code>viewDidAppear:方法里加上一句代碼,下文會(huì)細(xì)說(shuō)。
// 相當(dāng)于把a(bǔ)utomaticallyAdjustsScrollViewInsets設(shè)置為NO了
self.tableView.contentInset = UIEdgeInsetsZero;
效果如下圖:

當(dāng)如下更改edgesForExtendedLayout的設(shè)置時(shí)
self.edgesForExtendedLayout = UIRectEdgeNone;
效果如下:

顯然這是我們要的tableView效果,但是我們發(fā)現(xiàn)navigationbar的顏色變灰了,這是因?yàn)閚avigationbar是半透明的,但是navigationbar下面沒(méi)有視圖。

這時(shí)我們可以通過(guò)改變navigationbar的透明度來(lái)實(shí)現(xiàn)。
self.navigationController.navigationBar.translucent = NO;
// self.edgesForExtendedLayout = UIRectEdgeNone;
設(shè)置不透明之后,subview的邊緣就擴(kuò)展不到頂部上了,只能到navigationbar的底部。效果

extendedLayoutIncludesOpaqueBars
A Boolean value indicating whether or not the extended layout includes opaque bars.
The default value of this property is NO
這個(gè)屬性是指當(dāng)navigationbar不透明時(shí),layout是否包含navigationbar。當(dāng)navigationbar透明時(shí),此屬性不起作用。比如在上面設(shè)置不透明的基礎(chǔ)上,把這個(gè)屬性設(shè)置為YES(該屬性默認(rèn)NO),
self.navigationController.navigationBar.translucent = NO;
// self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = YES;
發(fā)現(xiàn)tableView的y從屏幕最頂部開(kāi)始算了。

automaticallyAdjustsScrollViewInsets
A Boolean value that indicates whether the view controller should automatically adjust its scroll view insets.
The default value of this property is YES, which lets container view controllers know that they should adjust the scroll view insets of this view controller’s view to account for screen areas consumed by a status bar, search bar, navigation bar, toolbar, or tab bar. Set this property to NO if your view controller implementation manages its own scroll view inset adjustments.
這個(gè)屬性太強(qiáng)大了,它會(huì)根據(jù)navigationbar和tabbar的存在,自動(dòng)調(diào)整scrollView的contentInset。如下圖

透過(guò)半透明的navigationbar可以看到tableView的y其實(shí)還是在屏幕的最頂部,但是第一個(gè)cell已經(jīng)變成從navigationbar的底部開(kāi)始了,這是因?yàn)?code>automaticallyAdjustsScrollViewInsets屬性默認(rèn)為YES,tableView的contentInset已經(jīng)由UIEdgeInsetsZero自動(dòng)調(diào)整為UIEdgeInsetsMake(64, 0, 0, 0)了。當(dāng)我們?cè)O(shè)置self.automaticallyAdjustsScrollViewInsets = NO;時(shí),就變成上文第一張效果圖的效果了。但是它也有不足,就是scrollview必須是根視圖添加的第一個(gè)子視圖,否則此屬性無(wú)效。
最后
這都是作者在實(shí)際工作中的一些總結(jié),如有不對(duì)之處,歡迎指正。