iOS開發(fā)-適配iOS 11及iPhoneX(1)

前言

iOS 11正式版將于9月19號正式推送,作為開發(fā)者當(dāng)然不會等到正式版推出之后才去體驗最新版的iOS 11,于是最近幾天安裝了下XCode9,在模擬器上跑了一下自己的App,發(fā)現(xiàn)了一些問題,本文主要談一下iOS 11下tableView內(nèi)容下移的問題。

一.為什么會發(fā)生內(nèi)容下移

廢話少說先上圖

問題

1.原因分析

在iOS 11中Apple干掉了ViewController中的automaticallyAdjustsScrollViewInsets這個屬性,當(dāng)tableview的frame超出了安全區(qū)域后系統(tǒng)會自動的調(diào)整SafeAreaInsets的值,而iOS 11中真正影響tableview內(nèi)容與邊緣的變成了adjustedContentInset而不是以前的contentInset。由于系統(tǒng)對adjustedContentInset進行了調(diào)整導(dǎo)致了tableView的內(nèi)容到邊緣的距離發(fā)生了變化,下移距離分別是20pt(沒有navigationBar,下移了一個statusBar的高度),64pt(navigationBar的高度以及statusBar的高度)。

2.關(guān)于安全區(qū)域

安全區(qū)域的概念是在iOS 11提出的,如圖

SafeArea

簡單來說下什么是安全區(qū)域,就是把View放在整個屏幕的可視部分,當(dāng)有navigationbar存在時安全區(qū)域也是從navigationbar的bottom開始的,若同時存在tabBar則中間區(qū)域為安全區(qū)域,ViewController中還提供了additionalSafeAreaInsets去擴展安全區(qū)域。

safeAreaInsets屬性反映了一個view距離該view的安全區(qū)域的邊距。對于一個Controller的根視圖而言,SafeAreaInsets值包括了被statusbar和其他可視的bars覆蓋的區(qū)域和其他通過additionalSafeAreaInsets自定義的insets值。對于view層次中得其他view,SafeAreaInsets值反映了view被覆蓋的部分。如果一個view全部在它父視圖的安全區(qū)域內(nèi),則SafeAreaInsets值為(0,0,0,0)。

二、 adjustContentInset

在iOS11中scrollView新增的兩個屬性:adjustContentInset和contentInsetAdjustmentBehavior。

adjustContentInset表示contentView.frame.origin偏移了scrollview.frame.origin多少;是系統(tǒng)計算得來的,計算方式由contentInsetAdjustmentBehavior決定。有以下幾種計算方式:

UIScrollViewContentInsetAdjustmentAutomatic:如果scrollview在一個automaticallyAdjustsScrollViewContentInset = YES的controller上,并且這個Controller包含在一個navigation controller中,這種情況下會設(shè)置在top & bottom上 adjustedContentInset = safeAreaInset + contentInset不管是否滾動。其他情況下與UIScrollViewContentInsetAdjustmentScrollableAxes相同

UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滾動方向上adjustedContentInset = safeAreaInset + contentInset,在不可滾動方向上adjustedContentInset = contentInset;依賴于scrollEnabled和alwaysBounceHorizontal / vertical = YES,scrollEnabled默認為yes,所以大多數(shù)情況下,計算方式還是adjustedContentInset = safeAreaInset + contentInset

UIScrollViewContentInsetAdjustmentNever: adjustedContentInset = contentInset

UIScrollViewContentInsetAdjustmentAlways: adjustedContentInset = safeAreaInset + contentInset

當(dāng)contentInsetAdjustmentBehavior設(shè)置為UIScrollViewContentInsetAdjustmentNever的時候,adjustContentInset值不受SafeAreaInset值的影響。

三、tableView何時會發(fā)生偏移問題

最常見的場景:tableview的frame超出了安全區(qū)域,而且設(shè)置了tableview的contentInset,第一幅圖中的tableview的frame設(shè)置為(0,0,self.view.frame.size.width,self.view.frame.size.height),contentInset設(shè)置為UIEdgeInsetsMake(64,0,0,0);從而導(dǎo)致了adjustedContentInset 偏移了一個safeAreaInset + contentInset,簡單來說:當(dāng)tableview的frame超出安全區(qū)域之后,系統(tǒng)會自動調(diào)整tableview的顯示范圍,但此時又設(shè)置了contentInset屬性導(dǎo)致出現(xiàn)下移現(xiàn)象。

四、解決方案

1.去掉contentInset

因為在iOS 11中系統(tǒng)已經(jīng)默認對scrollview的顯示做了處理只要其超過安全區(qū)域,它的內(nèi)容顯示都會在view上正常顯示,所以就不需要設(shè)置contentInset,避免發(fā)生偏移。

2.設(shè)置contentInsetAdjustmentBehavior

在不改變contentInset的情況下通過設(shè)置tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;讓adjustContentInset值不受SafeAreaInset值的影響。

3. iOS 11 ViewController新增的屬性 addtionalSafeAreaInset;

在不改變contentInset的情況下通過增加安全區(qū)域的范圍來抵消掉SafeAreaInset的值,如果SafeAreaInset值為(20,0,0,0),那么設(shè)置additionalSafeAreaInsets屬性值為(-20,0,0,0),則SafeAreaInsets不會對adjustedContentInset值產(chǎn)生影響

4.把tableview的frame控制在安全區(qū)域內(nèi)且不設(shè)置contentInset

在我的項目中對基類控制器中添加了一個ContentView屬性,該View的區(qū)域范圍也就是安全區(qū)域的范圍,需要做的就是先算出View的高度,把tableview放到安全區(qū)域內(nèi)就可以了,這樣也有個好處就是,iOS 11只對scrollview進行了安全區(qū)域的顯示處理,如果是view的話超出安全區(qū)域外的內(nèi)容是無法顯示的。

這里說一下automaticallyAdjustsScrollViewInsets這個屬性,在iOS 11之前即使把tableview放到了可視范圍之內(nèi)(有NavigationBar且沒有設(shè)置contentInset),當(dāng)該屬性為YES時候tableview還是會發(fā)生偏移。。。(很尷尬,所以這個屬性我一般至為NO,瞬間覺得iOS 11做了一件很美好的事情)

對于安全區(qū)域高度的計算有必要說一下,僅在豎屏有NavigationBar的情況下,傳統(tǒng)的iPhone尺寸安全區(qū)域高度為SCREEN_HEIGHT-64 ;而iPhoneX中為SCREEN_HEIGHT-(44+44+34),(第一個44為iPhoneX狀態(tài)欄的高度,第二個為NavigationBar的高度,第三個為底部非安全區(qū)域的高度,iPhoneX比較特殊,并且WWDC上有明確說明對iPhoneX上view的顯示必須放在安全區(qū)域之內(nèi))。

五、一些體會

最近看了很多WWDC17的視頻,Swift4越來越穩(wěn)定、XCode9以及iOS 11的變化真的很大而且充滿很多新的特性,XCode9支持了無線調(diào)試、斷電增強等功能開發(fā)起來越來越方便,iOS 11的眾多新功能ARKit、Core ML等,讓AR技術(shù)、機器學(xué)習(xí)和人工智能離我們越來越近。作為一名開發(fā)者來說最好的成長就是不斷的填坑,本文借鑒了一些http://www.itdecent.cn/p/efbc8619d56b文中的內(nèi)容對此表示感謝,最后附上WWDC關(guān)于iPhoneX對于SafeArea的介紹:developer.apple.com/videos/play/fall2017/801/

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容