iOS-與導航欄下控件的frame相關的edgesForExtendedLayout、translucent、extendedLayoutIncludesOpaqueBars、automaticallyAdjustsScrollViewInsets等幾個屬性的詳解

在引入了導航控制器UINavigationController和分欄控制器UITabBarController之后,我們在設置控件的frame的時候就需要注意避開導航欄UINavigationBar 44+電源欄UIStatusBar 20的高度,和底部分欄UITabBar 44的高度。底部分欄并沒有太多需要處理的,我們只需要在計算高度的時候避開這44就可以了。而導航欄因為包含透明/半透明、第一個控件是否是UIScrollView或其子類等造成frame.origin.y的起點不同。我們現(xiàn)在來分析一下。

1.edgesForExtendedLayout:UIRectEdge 擴展布局的邊緣
  在iOS7以后 UIViewController 開始使用全屏布局,而且是默認的屬性。通常涉及到布局,就離不開這個屬性 edgesForExtendedLayout,它是一個類型為UIExtendedEdge的屬性,指定UIViewController上的根視圖self.view邊緣要延伸的方向。由于iOS7鼓勵全屏布局,所以它的默認值是UIRectEdgeAll,四周邊緣均延伸,就是說,如果即使視圖中上有UINavigationBar,下有UITabBar,那么視圖仍會延伸覆蓋到四周的區(qū)域。
(1)UIRectEdgeAll(Defalut)


image.png

這里放置了一個frame為(0, 0, 100, 100)的view,backgroundColor設置為redColor,就是這個樣子。也就是說,此時的self.view是從屏幕頂?shù)狡聊坏椎摹4藭r我們計算控件frame的y的時候,如果想把控件在導航欄底部開始,那么y就是64。
(2)UIRectEdgeNone
因此,我們?yōu)榱瞬蛔屛覀兊目丶IView延伸到UINavigationBar下面,我們可以將該屬性設置為UIRectEdgeNone。代碼如下:

[self setEdgesForExtendedLayout:UIRectEdgeNone];

ps:鑒于之前代碼OC與Swift都有,可能帶來的閱讀不習慣,以后貼代碼盡量使用OC,Swift獨有的那就沒辦法了。


image.png

很清晰的可以看出來在設置為UIRectEdgeNone之后,self.view的是從導航欄底部到底部分欄頂部的。此時我們計算控件frame的y的時候,如果想把控件在導航欄底部開始,那么y就是0。

(3)UIRectEdge

typedef NS_OPTIONS(NSUInteger, UIRectEdge) {
 2 
 3     UIRectEdgeNone   = 0,
 4 
 5     UIRectEdgeTop    = 1 << 0,
 6 
 7     UIRectEdgeLeft   = 1 << 1,
 8 
 9     UIRectEdgeBottom = 1 << 2,
10 
11     UIRectEdgeRight  = 1 << 3,
12 
13     UIRectEdgeAll    = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight  
14 
15 } NS_ENUM_AVAILABLE_IOS(7_0);

很明顯,UIRectEdge是個枚舉類型。我們已經分析完了UIRectEdgeNone和UIRectEdgeAll,那么對UIRectEdgeTop和UIRectEdgeBottom也應該有所了解了。UIRectEdgeLeft/UIRectEdgeRight也不難猜測,就是對左右的擴展。目前沒有遇到過左右兩邊系統(tǒng)控件可能覆蓋掉自定義控件的情況,但遇到了我想大家也應該心里有數(shù)了吧。

2.translucent:Bool 半透明的
這個是self.navigationController.navigationBar的屬性,設置導航條UINavigationBar是否半透明。默認是YES,也就是半透明,看起來比較高大上,與圖1效果相同。
當設置為不透明NO的時候,就涉及到下面第三條屬性了,不過在第三條默認的情況下,則被下壓,與圖2效果相同。

[self.navigationController.navigationBar setTranslucent:NO];
image.png

圖中空出的部分,即為導航條UINavigationBar。此時計算frame應從導航欄下部為0開始計算,或者說控件會被下壓64。
不過我們一般不會使用到這一條,因為半透明效果比較好看啊~

3.extendedLayoutIncludesOpaqueBars:Bool 不透明的條下是否可以擴展
  很明顯,這條需要與上一條translucent搭配使用的,默認為NO,也就是不可以擴展。當translucent設置為NO,即導航欄UINavigationBar不透明的時候,默認不能擴展。若我們設置為YES,則會出現(xiàn)這種情況:


image.png

我并沒有改變紅色view的frame,而是被不透明的導航條蓋住看不到了。很明顯此時計算frame又是從屏幕最上方作為0開始計算了。
為了計算究竟是在電源條下方還是屏幕最上方作為y的0點,改變了紅色view的height為64和65重復試驗,結果如下


image.png

結論是從屏幕上方作為y的0開始計算。
不過第2條都很少用,第3條使用的幾率...

4.automaticallyAdjustsScrollViewInsets:Bool 自動校準滾動視圖的嵌入視圖
這個其實就很簡單了,也是我們最常使用的一個吧。automaticallyAdjustsScrollViewInsets是一個bool類型,默認為YES,也就是會自動校準滾動視圖的嵌入視圖。不過這個只針對于UIScrollView及其子視圖,所以我們是用UITextView做一下測試。

創(chuàng)建了一個frame為(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)占據整個屏幕的UITextView,并放置了足夠多的文字。在默認automaticallyAdjustsScrollViewInsets為YES的前提下,我們測試下可能出現(xiàn)的結果。


image.png

似乎什么毛病都沒有啊很正常啊。但是不要忘記我設置的frame的y是0啊。那大家可能就好奇了,難道UIScrollView的滾動視圖的frame是從導航欄下邊界算起的?不忙,我們設置automaticallyAdjustsScrollViewInsets為NO再試試。

[self setAutomaticallyAdjustsScrollViewInsets:NO];
image.png

這個是一啟動就出現(xiàn)的界面,我并沒有向上滑動它的內容區(qū)域,也就是說,似乎此時的frame又是從屏幕下方開始的了。
不要慌,我們改一下設置試試看。
我將UITextView的frame設置為(0, 64, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height),也就是y改成了64;然后改變了它的背景顏色為紅色redColor;最后將[self setAutomaticallyAdjustsScrollViewInsets:NO];這行代碼注掉,讓它默認為YES。
看一下效果。


image.png

注意:導航欄是半透明的,所以不存在被壓到紅色看不到的問題,也就是說,UITextView的frame的y的64的位置,是導航欄下方;那么0自然就是在屏幕下方開始計算了。
很明顯,automaticallyAdjustsScrollViewInsets改變的并不是UIScrollView的frame,而是它的內容區(qū)域contentView的可滾動區(qū)域,也就是scrollIndicatorInsets。這是我們能滾到的最大范圍。相當于scrollIndicatorInsets這個屬性UIEdgeInsetsMake(<#CGFloat top#>, <#CGFloat left#>, <#CGFloat bottom#>, <#CGFloat right#>)的值從UIEdgeInsetsMake(0, 0, 0, 0)變?yōu)榱薝IEdgeInsetsMake(64, 0, 0, 0)。這就是automaticallyAdjustsScrollViewInsets這個屬性的作用。
另外再說一點,這個automaticallyAdjustsScrollViewInsets的屬性,只對加在self.view上的第一個子視圖起作用,所以我們可以在將UIScrollView加載到self.view上之前先加載一個其他控件,這樣也能達到同樣的效果。
ps:

當升級到iOS 11的時候,發(fā)現(xiàn)UIScrollView 有莫名其妙的偏移了 可是明明設置了

automaticallyAdjustsScrollViewInsets

這是因為iOS 11為UIScrollView 添加了新的屬性contentInsetAdjustmentBehavior 這是一個枚舉

找到UIScrollViewContentInsetAdjustmentNever 從來不自動調整和automaticallyAdjustsScrollViewInsets = NO 是一個功效 這樣就解決了iOS 11這個bug

        if (@available(iOS 11.0, *)) {

            Scrollview.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;

        } else {

            // Fallback on earlier versions

        }
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • *7月8日上午 N:Block :跟一個函數(shù)塊差不多,會對里面所有的內容的引用計數(shù)+1,想要解決就用__block...
    炙冰閱讀 2,731評論 1 14
  • 之前參加過王老師在橙子學院開的溝通課,很受益。今天又聽到王老師這次的微課,還是覺得老師講得真好。對于今年過年回家應...
    寒江雪霏閱讀 434評論 0 0
  • 昨天同事約見面,愉快的談話里情不自禁的代入前女友,“我想,她留在那里會比較難過吧,我先出來了”,“她是一個...
    茜子_10dc閱讀 341評論 0 0
  • 此刻的我被感動著,感動與你們無微不至的關心:有專程從上海趕來的大姐、有從山西專門寄來的小米與核桃…… ...
    唯美兒閱讀 265評論 0 1
  • 親愛的小溪: 你好嗎? 你一定要好好的,這是我最大的心愿。 近幾日,秋雨綿綿,正如我的思念。一場秋雨一場涼,你要注...
    葭溪閱讀 282評論 6 4

友情鏈接更多精彩內容