當(dāng)我們使用UINavigationController時,插入一個控制器,然后往這個控制器的view上加subview(比如一個tableView)時,經(jīng)常會碰到tableView的實際展示跟自己設(shè)置的frame不一致的情況。這里就總結(jié)記錄一下平時自己遇到過的相關(guān)問題。
iOS7之前控制器有一個屬性wantsFullScreenLayout
。當(dāng)把它設(shè)置為YES時,你添加的subview的y就是從屏幕的最頂部開始算,包含navigationbar,設(shè)置為NO時,則從navigationbar的bottom開始算。因為iOS7之前,navigationbar默認一般是不透明的,所以wantsFullScreenLayout
一般默認為NO。從iOS7開始,這個屬性被廢棄了,代替它的是三個新的屬性:edgesForExtendedLayout
、extendedLayoutIncludesOpaqueBars
、automaticallyAdjustsScrollViewInsets
,今天重點說的就是這三個經(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
這個屬性是通過擴展子視圖的邊緣來適配屏幕,因為iOS7之后鼓勵全屏,navigationbar變得半透明,所以這個屬性默認為UIRectEdgeAll
,及x和y是從屏幕的左上角開始算的。比如設(shè)置tableView的frame如下:
self.tableView.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 350);
這里為了防止automaticallyAdjustsScrollViewInsets的干擾,我們在viewDidAppear:
方法里加上一句代碼,下文會細說。
// 相當(dāng)于把automaticallyAdjustsScrollViewInsets設(shè)置為NO了
self.tableView.contentInset = UIEdgeInsetsZero;
效果如下圖:
當(dāng)如下更改edgesForExtendedLayout
的設(shè)置時
self.edgesForExtendedLayout = UIRectEdgeNone;
效果如下:
顯然這是我們要的tableView效果,但是我們發(fā)現(xiàn)navigationbar的顏色變灰了,這是因為navigationbar是半透明的,但是navigationbar下面沒有視圖。
這時我們可以通過改變navigationbar的透明度來實現(xiàn)。
self.navigationController.navigationBar.translucent = NO;
// self.edgesForExtendedLayout = UIRectEdgeNone;
設(shè)置不透明之后,subview的邊緣就擴展不到頂部上了,只能到navigationbar的底部。效果
extendedLayoutIncludesOpaqueBars
A Boolean value indicating whether or not the extended layout includes opaque bars.
The default value of this property is NO
這個屬性是指當(dāng)navigationbar不透明時,layout是否包含navigationbar。當(dāng)navigationbar透明時,此屬性不起作用。比如在上面設(shè)置不透明的基礎(chǔ)上,把這個屬性設(shè)置為YES(該屬性默認NO),
self.navigationController.navigationBar.translucent = NO;
// self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = YES;
發(fā)現(xiàn)tableView的y從屏幕最頂部開始算了。
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.
這個屬性太強大了,它會根據(jù)navigationbar和tabbar的存在,自動調(diào)整scrollView的contentInset。如下圖
透過半透明的navigationbar可以看到tableView的y其實還是在屏幕的最頂部,但是第一個cell已經(jīng)變成從navigationbar的底部開始了,這是因為automaticallyAdjustsScrollViewInsets
屬性默認為YES,tableView的contentInset已經(jīng)由UIEdgeInsetsZero
自動調(diào)整為UIEdgeInsetsMake(64, 0, 0, 0)
了。當(dāng)我們設(shè)置self.automaticallyAdjustsScrollViewInsets = NO;
時,就變成上文第一張效果圖的效果了。但是它也有不足,就是scrollview必須是根視圖添加的第一個子視圖,否則此屬性無效。
最后
這都是作者在實際工作中的一些總結(jié),如有不對之處,歡迎指正。