iOS 11 安全區(qū)域適配總結(jié)?

| 導(dǎo)語(yǔ) 本文主要是對(duì)iOS 11下企鵝 FM APP中tableView內(nèi)容下移20pt或下移64pt的問(wèn)題適配的一個(gè)總結(jié)。內(nèi)容包括五個(gè)部分:?jiǎn)栴}的原因分析、adjustContentInset屬性的計(jì)算方式缠借、什么情況下的tableView會(huì)發(fā)生內(nèi)容下移、有哪些解決方法信不、解決這個(gè)問(wèn)題時(shí)遇到的另外一個(gè)小問(wèn)題屈溉。

一、iOS 11下APP中tableView內(nèi)容下移20pt或下移64pt的原因分析
問(wèn)題如下圖所示:


  1. 原因分析
    原因是iOS 11中Controller的automaticallyAdjustsScrollViewInsets屬性被廢棄了姐扮,所以當(dāng)tableView超出安全區(qū)域時(shí)系統(tǒng)自動(dòng)調(diào)整了SafeAreaInsets值絮供,進(jìn)而影響adjustedContentInset值,在iOS 11中決定tableView的內(nèi)容與邊緣距離的是adjustedContentInset屬性茶敏,而不是contentInset壤靶。adjustedContentInset的計(jì)算方式見(jiàn)本文第二部分內(nèi)容。因?yàn)橄到y(tǒng)對(duì)adjustedContentInset值進(jìn)行了調(diào)整惊搏,所以導(dǎo)致tableView的內(nèi)容到邊緣的距離發(fā)生了變化贮乳,導(dǎo)致tableView下移了20pt(statusbar高度)或64pt(navigationbar高度)。
    如果你的APP中使用的是自定義的navigationbar恬惯,隱藏掉系統(tǒng)的navigationbar向拆,并且tableView的frame為(0,0,SCREENWIDTH, SCREENHEIGHT)開(kāi)始,那么系統(tǒng)會(huì)自動(dòng)調(diào)整SafeAreaInsets值為(20,0,0,0)酪耳,如果使用了系統(tǒng)的navigationbar浓恳,那么SafeAreaInsets值為(64,0,0,0),如果也使用了系統(tǒng)的tabbar碗暗,那么SafeAreaInsets值為(64,0,49,0)颈将。關(guān)于什么情況下會(huì)發(fā)生內(nèi)容下移的問(wèn)題,本文第三部分有介紹讹堤。
  2. 安全區(qū)域的概念
    系統(tǒng)自動(dòng)調(diào)整tableView內(nèi)容偏移量吆鹤,是根據(jù)安全區(qū)域來(lái)調(diào)整的。安全區(qū)域是iOS 11新提出的洲守,如下圖所示:



    安全區(qū)域幫助我們將view放置在整個(gè)屏幕的可視的部分疑务。即使把navigationbar設(shè)置為透明的沾凄,系統(tǒng)也認(rèn)為安全區(qū)域是從navigationbar的bottom開(kāi)始,保證不被系統(tǒng)的狀態(tài)欄知允、或?qū)Ш綑诟采w撒蟀。可以使用additionalSafeAreaInsets去擴(kuò)展安全區(qū)域使它包括自定義的content在界面上温鸽。每個(gè)view都可以改變安全區(qū)域嵌入的大小保屯,Controller也可以。
    safeAreaInsets屬性反映了一個(gè)view距離該view的安全區(qū)域的邊距涤垫。對(duì)于一個(gè)Controller的根視圖而言姑尺,SafeAreaInsets值包括了被statusbar和其他可視的bars覆蓋的區(qū)域和其他通過(guò)additionalSafeAreaInsets自定義的insets值。view層次中的其它view蝠猬,SafeAreaInsets值反映了該view被覆蓋的部分切蟋。如果一個(gè)view全部在它父視圖的安全區(qū)域內(nèi),則SafeAreaInsets值為(0,0,0,0)榆芦。
    二柄粹、 adjustContentInset屬性的計(jì)算方式
    首先看scrollView在iOS11新增的兩個(gè)屬性:adjustContentInset 和 contentInsetAdjustmentBehavior。
    /* Configure the behavior of adjustedContentInset.Default is UIScrollViewContentInsetAdjustmentAutomatic.*/@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior

adjustContentInset表示contentView.frame.origin偏移了scrollview.frame.origin多少匆绣;是系統(tǒng)計(jì)算得來(lái)的驻右,計(jì)算方式由contentInsetAdjustmentBehavior決定。有以下幾種計(jì)算方式:
1.UIScrollViewContentInsetAdjustmentAutomatic:如果scrollview在一個(gè)automaticallyAdjustsScrollViewContentInset = YES的controller上崎淳,并且這個(gè)Controller包含在一個(gè)navigation controller中堪夭,這種情況下會(huì)設(shè)置在top & bottom上 adjustedContentInset = safeAreaInset + contentInset不管是否滾動(dòng)。其他情況下與UIScrollViewContentInsetAdjustmentScrollableAxes相同
2.UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滾動(dòng)方向上adjustedContentInset = safeAreaInset + contentInset凯力,在不可滾動(dòng)方向上adjustedContentInset = contentInset茵瘾;依賴于scrollEnabled和alwaysBounceHorizontal / vertical = YES礼华,scrollEnabled默認(rèn)為yes咐鹤,所以大多數(shù)情況下,計(jì)算方式還是adjustedContentInset = safeAreaInset + contentInset
**3.UIScrollViewContentInsetAdjustmentNever: **adjustedContentInset = contentInset
4.UIScrollViewContentInsetAdjustmentAlways: adjustedContentInset = safeAreaInset + contentInset
當(dāng)contentInsetAdjustmentBehavior設(shè)置為UIScrollViewContentInsetAdjustmentNever的時(shí)候圣絮,adjustContentInset值不受SafeAreaInset值的影響祈惶。
三、什么情況下的tableView會(huì)發(fā)生上述問(wèn)題
如果設(shè)置了automaticallyAdjustsScrollViewInsets = YES扮匠,那么不會(huì)發(fā)生問(wèn)題捧请,一直都是由系統(tǒng)來(lái)調(diào)整內(nèi)容的偏移量。
接下來(lái)排查下自己的項(xiàng)目中哪些頁(yè)面會(huì)發(fā)生以上問(wèn)題棒搜。
當(dāng)tableView的frame超出安全區(qū)域范圍時(shí)疹蛉,系統(tǒng)會(huì)自動(dòng)調(diào)整內(nèi)容的位置,SafeAreaInsets值會(huì)不為0力麸,于是影響tableView的adjustContentInset值可款,于是影響tableView的內(nèi)容展示育韩,導(dǎo)致tableView的content下移了SafeAreaInsets的距離。SafeAreaInsets值為0時(shí)闺鲸,是正常的情況筋讨。
需要了解每個(gè)頁(yè)面的結(jié)構(gòu),看tableView是否被系統(tǒng)的statusbar或navigationbar覆蓋摸恍,如果被覆蓋的話悉罕,則會(huì)發(fā)生下移。也可以通過(guò)tableview.safeAreaInsets的值來(lái)確認(rèn)是因?yàn)榘踩珔^(qū)域的問(wèn)題導(dǎo)致的內(nèi)容下移立镶。
如下代碼片段壁袄,可以看出系統(tǒng)對(duì)tableView向下調(diào)整了20pt的距離,因?yàn)閠ableView超出了安全區(qū)域范圍媚媒,被statusbar覆蓋然想。
tableview.contentInset: {64, 0, 60, 0}tableview.safeAreaInsets: {20, 0, 0, 0}tableview.adjustedContentInset: {84, 0, 60, 0}

四、這個(gè)問(wèn)題的解決方法有哪些欣范?

  1. 重新設(shè)置tableView的contentInset值变泄,來(lái)抵消掉SafeAreaInset值,因?yàn)閮?nèi)容偏移量 = contentInset + SafeAreaInset恼琼;
    如果之前自己設(shè)置了contentInset值為(64,0,0,0),現(xiàn)在系統(tǒng)又設(shè)置了SafeAreaInsets值為(64,0,0,0)妨蛹,那么tableView內(nèi)容下移了64pt,這種情況下晴竞,可以設(shè)置contentInset值為(0,0,0,0)蛙卤,也就是遵從系統(tǒng)的設(shè)置了。
  2. 設(shè)置tableView的contentInsetAdjustmentBehavior屬性
    如果不需要系統(tǒng)為你設(shè)置邊緣距離噩死,可以做以下設(shè)置:
    //如果iOS的系統(tǒng)是11.0颤难,會(huì)有這樣一個(gè)宏定義“#define __IPHONE_11_0 110000”;如果系統(tǒng)版本低于11.0則沒(méi)有這個(gè)宏定義#ifdef __IPHONE_11_0 if ([tableView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) { tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;}#endif

contentInsetAdjustmentBehavior屬性也是用來(lái)取代automaticallyAdjustsScrollViewInsets屬性的已维,推薦使用這種方式行嗤。

  1. 通過(guò)設(shè)置iOS 11新增的屬性addtionalSafeAreaInset;
    iOS 11之前垛耳,大家是通過(guò)將Controller的automaticallyAdjustsScrollViewInsets屬性設(shè)置為NO栅屏,來(lái)禁止系統(tǒng)對(duì)tableView調(diào)整contentInsets的。如果還是想從Controller級(jí)別解決問(wèn)題堂鲜,那么可以通過(guò)設(shè)置Controller的additionalSafeAreaInsets屬性栈雳,如果SafeAreaInset值為(20,0,0,0),那么設(shè)置additionalSafeAreaInsets屬性值為(-20,0,0,0)缔莲,則SafeAreaInsets不會(huì)對(duì)adjustedContentInset值產(chǎn)生影響哥纫,tableView內(nèi)容不會(huì)顯示異常。這里需要注意的是addtionalSafeAreaInset是Controller的屬性痴奏,要知道SafeAreaInset的值是由哪個(gè)Controller引起的蛀骇,可能是由自己的Controller調(diào)整的奖慌,可能是navigationController調(diào)整的。是由哪個(gè)Controller調(diào)整的松靡,則設(shè)置哪個(gè)Controller的addtionalSafeAreaInset值來(lái)抵消掉SafeAreaInset值简僧。
    五、遇到的另外一個(gè)與安全區(qū)域無(wú)關(guān)的tableView內(nèi)容下移的問(wèn)題
    我的作品頁(yè)面的tableView下移了約40pt雕欺,這里是否跟安全區(qū)域有關(guān)呢岛马?



    查了下頁(yè)面結(jié)構(gòu),tableView的父視圖的frame在navigationbar的bottom之下屠列,tableView在父視圖的安全區(qū)域內(nèi)啦逆,打印出來(lái)tableView的SafeAreaInset值也是(0,0笛洛,0夏志,0);所以不是安全區(qū)域?qū)е碌膬?nèi)容下移。
    經(jīng)過(guò)查看代碼苛让,發(fā)現(xiàn)tableView的style:UITableViewStyleGrouped類型沟蔑,默認(rèn)tableView開(kāi)頭和結(jié)尾是有間距的,不需要這個(gè)間距的話狱杰,可以通過(guò)實(shí)現(xiàn)heightForHeaderInSection方法(返回一個(gè)較小值:0.1)和viewForHeaderInSection(返回一個(gè)view)來(lái)去除頭部的留白瘦材,底部同理。
    iOS 11上發(fā)生tableView頂部有留白仿畸,原因是代碼中只實(shí)現(xiàn)了heightForHeaderInSection方法食棕,而沒(méi)有實(shí)現(xiàn)viewForHeaderInSection方法。那樣寫是不規(guī)范的错沽,只實(shí)現(xiàn)高度簿晓,而沒(méi)有實(shí)現(xiàn)view,但代碼這樣寫在iOS 11之前是沒(méi)有問(wèn)題的千埃,iOS 11之后應(yīng)該是由于開(kāi)啟了估算行高機(jī)制引起了bug憔儿。添加上viewForHeaderInSection方法后,問(wèn)題就解決了镰禾∶笄或者添加以下代碼關(guān)閉估算行高,問(wèn)題也得到解決吴侦。
    self.tableView.estimatedRowHeight = 0;self.tableView.estimatedSectionHeaderHeight = 0;self.tableView.estimatedSectionFooterHeight = 0;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市坞古,隨后出現(xiàn)的幾起案子备韧,更是在濱河造成了極大的恐慌,老刑警劉巖痪枫,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件织堂,死亡現(xiàn)場(chǎng)離奇詭異叠艳,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)易阳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門附较,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人潦俺,你說(shuō)我怎么就攤上這事拒课。” “怎么了事示?”我有些...
    開(kāi)封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵早像,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我肖爵,道長(zhǎng)卢鹦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任劝堪,我火速辦了婚禮冀自,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘秒啦。我一直安慰自己凡纳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布帝蒿。 她就那樣靜靜地躺著荐糜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪葛超。 梳的紋絲不亂的頭發(fā)上暴氏,一...
    開(kāi)封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音绣张,去河邊找鬼答渔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛侥涵,可吹牛的內(nèi)容都是我干的沼撕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼芜飘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼务豺!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起嗦明,我...
    開(kāi)封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤笼沥,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體奔浅,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡馆纳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了汹桦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鲁驶。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖舞骆,靈堂內(nèi)的尸體忽然破棺而出钥弯,到底是詐尸還是另有隱情,我是刑警寧澤葛作,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布寿羞,位于F島的核電站,受9級(jí)特大地震影響赂蠢,放射性物質(zhì)發(fā)生泄漏绪穆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一虱岂、第九天 我趴在偏房一處隱蔽的房頂上張望玖院。 院中可真熱鬧,春花似錦第岖、人聲如沸难菌。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)郊酒。三九已至,卻和暖如春键袱,著一層夾襖步出監(jiān)牢的瞬間燎窘,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工蹄咖, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留褐健,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓澜汤,卻偏偏與公主長(zhǎng)得像蚜迅,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子俊抵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容