影響TableView布局的問(wèn)題主要是由其父類UIScrollView引起的。
影響UIScrollView布局的因素:
第一類: NavigationBar.translucent,VC.edgesForExtendedLayout,VC.extendLayoutIncludesOpaqueBars
第二類: ScrollView.contentInset,VC.automaticallyAdjustsScrollViewInsets,navigationBar/StatusBar的隱藏,NavigationBar/TabBar的有無(wú),TabBar隱藏的方式,第一個(gè)addSubview的是不是當(dāng)前的ScrollView。
Translucent
self.navigationController.navigationBar.translucent = NO; 時(shí),self.view.frame的值為0.00_64.00_375.00_603.00 (iPhone 6為例)
默認(rèn)屬性下,向上滑動(dòng)TableView,header是可以透過(guò)NavigationBar的,修改translucent屬性為NO后,正是因?yàn)?code>VC的View布局不在NavigationBar底下了,所以這時(shí)看不到header的。
edgesForExtendLayout
枚舉值如下:
typedef NS_OPTIONS(NSUInteger, UIRectEdge) {
UIRectEdgeNone = 0,
UIRectEdgeTop = 1 << 0,
UIRectEdgeLeft = 1 << 1,
UIRectEdgeBottom = 1 << 2,
UIRectEdgeRight = 1 << 3,
UIRectEdgeAll = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight
} NS_ENUM_AVAILABLE_IOS(7_0);
既有TabBar又有NavigationBar的,默認(rèn)值UIRectEdgeAll下,當(dāng)前控制器就做了上面和下面的延展布局。
self.view.frame 的值為0.00_ 0.00_375.00_667.00
當(dāng)將此屬性改變?yōu)?code>UIRectEdgeNone時(shí),上面和下面的延展全部禁止。self.view.frame的值為0.00_64.00_375.00_554.00,說(shuō)明view從導(dǎo)航欄開(kāi)始布局,而且高度為667-49(TabBar高度)-64(NavigationBar高度 )
這里footer顯示不全的原因就是VC的view的高度比TableView的高度小。
extendedLayoutIncludesOpaqueBars
在導(dǎo)航欄不透明時(shí),extendedLayoutIncludesOpaqueBars又為默認(rèn)值NO的情況下。self.view.frame的值為0.00_64.00_375.00_603.00
當(dāng)我們將此屬性改為YES
self.extendedLayoutIncludesOpaqueBars = YES;
此時(shí),self.view.frame的值為0.00_0.00_375.00_667.00
ScrollView.contentInset
關(guān)于ScrollView的這個(gè)屬性,初始值為0,所有對(duì)contentInset值的自動(dòng)調(diào)整都是在viewWillAppear和viewDidAppear之間進(jìn)行調(diào)整。默認(rèn)條件下,viewWillAppear中打印ContentInset--64.00_0.00_49.00_0.00
特別注意:
正常情況下想想要設(shè)置contentInset的值需要在viewDidLoad中進(jìn)行,需要注意的是,設(shè)置contentInset值并不是覆蓋了原值,而是與原值進(jìn)行了各項(xiàng)相加的處理。
比如,我在創(chuàng)建tableView的時(shí)候,添加這樣一行代碼:
tableView.contentInset = UIEdgeInsetsMake(-64,0,0,0);
默認(rèn)值top應(yīng)該是64,設(shè)置新值后并沒(méi)有覆蓋,而應(yīng)該是 -64 + 64 = 0;
這時(shí),打印的結(jié)果為:viewWillAppear中打印ContentInset 為64.00_0.00_49.00_0.00,viewDidAppear中打印ContentInset為0.00_0.00_49.00_0.00
automaticallyAdjustsScrollViewInsets
這個(gè)屬性為當(dāng)前控制器是否要自動(dòng)調(diào)整contentInset,默認(rèn)為YES。
默認(rèn)條件下,viewWillAppear中打印ContentInset為0.00_0.00_0.00_0.00,viewDidAppear中打印ContentInset為64.00_0.00_49.00_0.00
當(dāng)修改其值為NO后,
self.automaticallyAdjustsScrollViewInsets = NO;
修改后控制器不會(huì)根據(jù)系統(tǒng)的默認(rèn)值自動(dòng)調(diào)整ContentInset了,所以在viewWillAppear中打印ContentInset為0.00_0.00_0.00_0.00,viewDidAppear中打印ContentInset為0.00_0.00_0.00_0.00
NavigationBar / TabBar的有無(wú)
就如上面說(shuō)過(guò),NavigationBar和TabBar的存在才是以上那些影響因素的前提。如果沒(méi)有它們這些屬性是無(wú)效果的,只有它們的存在才能通過(guò)這些屬性影響ScrollView的布局。
NavigationBar / StatusBar 的隱藏
NavigationBar隱藏后,在默認(rèn)自動(dòng)調(diào)整ContentInset的情況下,其top的值為20。所以,想要做透明導(dǎo)航欄又不隱藏狀態(tài)欄的需求,需要注意下這里。當(dāng)然是用上面的設(shè)置ScrollView.contentInset的方法可以解決此問(wèn)題。
TabBar的隱藏
一般的App在每個(gè)Tab首頁(yè)的VC才會(huì)展示出TabBar,而在第二層頁(yè)面開(kāi)始就要隱藏TabBar了。但是TabBar不同的隱藏方式,會(huì)產(chǎn)生某些影響,從而影響ScrollView.contentInset.
使用系統(tǒng)的TabBar,通過(guò)hidesBottomBarWhenPushed方法進(jìn)行隱藏TabBar和TabBar.hidden兩種方式來(lái)隱藏,會(huì)產(chǎn)生影響,從而影響ScrollView.contentInset.
使用系統(tǒng)的TabBar,通過(guò)hidesBottomBarWhenPushed方法進(jìn)行隱藏TabBar和tabBar.hidden兩種方式來(lái)對(duì)比。
hidesBottomBarWhenPushed
此方法下,viewWillAppear中打印ContentInset為0.00_0.00_0.00_0.00,viewDidAppear中打印ContentInset為64.00_0.00_0.00_0.00
TabBar.hidden
此方法下,viewWillAppear中打印ContentInset為0.00_0.00_0.00_0.00,viewDidAppear中打印ContentInset為64.00_0.00_49.00_0.00
兩種方法的區(qū)別在于,執(zhí)行TabBar隱藏的時(shí)機(jī)不同,hidesBottomBarWhenPushed方法在viewDidLoad之前執(zhí)行,而TabBar.hidden是在viewWillAppear中執(zhí)行的。正是因?yàn)榇耍斐?code>ScrollView.contentInset的不同,因?yàn)?code>hidesBottomBarWhenPushed方法在布局配置前就隱藏了TabBar了,所以不會(huì)有內(nèi)嵌的影響了。
第一個(gè)addSubview的是不是當(dāng)前的ScrollView
當(dāng)前控制器,self.view上第一個(gè)addSubview的如果是ScrollView,則以上的所有因素才可以影響其布局。如果不是第一個(gè)添加的,則以上所有的屬性影響失效。
而且還有一個(gè)布局方面的問(wèn)題,在默認(rèn)情況下只要是第一個(gè)添加的ScrollView,無(wú)論ScrollView的frame為多少,它的ContentInset是會(huì)一直存在的。