? 0.4?2017.10.20 10:13*?字數(shù) 1206?閱讀 4834評論 0喜歡 5
隨著蘋果?iOS11系統(tǒng)的發(fā)布,我也在第一時間將手機系統(tǒng)更新,sb Xcode也更新到了最新版本崭庸。在運行公司項目的時候發(fā)現(xiàn)一些界面內(nèi)tableview出現(xiàn)了向下偏移,上啦刷新有問題的情況网严。之前都在忙項目贩绕,搜索找到解決方法之后也沒有仔細的探究為什么會出現(xiàn)這個問題。現(xiàn)在讓我好好的總結一下赠法,如何在iOS 11系統(tǒng)里適配UITableView麦轰。
認識一下SafeArea
SafeArea幫助你在置放內(nèi)容和控件時,避免與系統(tǒng)UI元素重疊。
safeArea.png
safeAreaInset是UIView在iOS11系統(tǒng)之后新增加的一個屬性款侵,它根據(jù)inset在視圖的界內(nèi)矩形中指示出一塊不受navigation bars末荐,tab bars,toolbars等遮擋的視圖。并且新锈,如果這塊視圖還沒有被一個父視圖包含或者沒有出現(xiàn)在屏幕上時甲脏,這個屬性值為空。你可以通過addtionalSafeAreaInsets這個屬性來改變safeAreaInsets的值妹笆,以此來創(chuàng)建你自己想要的控件剃幌,并且可以通過viewSafeAreaInsetsDidChange方法進行回調(diào)。
為什么會出現(xiàn)向下偏移的問題
在ios11系統(tǒng)之前晾浴,視圖控制器通過automaticallyAdjustsScrollViewInsets這個屬性來控制是否自動調(diào)節(jié)滑動視圖UIScrollView的contentInset,來調(diào)節(jié)滑動視圖的位置负乡。
在ios11之后系統(tǒng)之后,這個屬性被棄用了〖够耍現(xiàn)在視圖控制通過安全距離safeAreaInsets和滑動視圖的contentInsetAdjustmentBehavior來共同控制UIScrollView的adjustedContentInset抖棘,進而調(diào)節(jié)滑動視圖的位置。
下面是adjustContentInset屬性的計算方式
UIScrollViewContentInsetAdjustmentAutomatic
UIScrollView會自動計算和適應頂部和底部的內(nèi)邊距并且在UIScrollView?不可滾動時狸涌,也會設置內(nèi)邊距切省。
UIScrollViewContentInsetAdjustmentScrollableAxes
自動適應邊距,即在可滾動方向上adjustedContentInset = safeAreaInset + contentInset,在不可滾動方向上adjustedContentInset = contentInset帕胆。
UIScrollViewContentInsetAdjustmentNever:
和automaticallyAdjustsScrollViewInsets=NO有著同樣的效果朝捆,不計算內(nèi)邊距,即adjustedContentInset = contentInset懒豹。
UIScrollViewContentInsetAdjustmentAlways:
根據(jù)safeAreaInsets計算內(nèi)邊距芙盘,即adjustedContentInset = safeAreaInset + contentInset。
當tableView的frame超出安全區(qū)域范圍時脸秽,系統(tǒng)會自動調(diào)整內(nèi)容的位置儒老,SafeAreaInsets值會不為0,于是影響tableView的adjustContentInset值记餐,于是影響tableView的內(nèi)容展示驮樊,導致tableView的content下移了safeAreaInsets.top的距離。SafeAreaInsets值為0時片酝,顯示正常囚衔。
你需要了解每個頁面的結構,看tableView是否被系統(tǒng)的statusbar或navigationbar覆蓋雕沿,如果被覆蓋的話练湿,則會發(fā)生下移。也可以通過tableview.safeAreaInsets的值來確認是因為安全區(qū)域的問題導致的內(nèi)容下移晦炊。
如果解決UITableView向下偏移的問題
(1)重新設置tableView的contentInset值
重新設置tableView的contentInset值鞠鲜,來抵消掉SafeAreaInset值宁脊,因為內(nèi)容下移偏移量 = contentInset + SafeAreaInset,這也是我項目中解決這個問題使用的方法贤姆。
(2)設置tableView的contentInsetAdjustmentBehavior屬性
如果不需要系統(tǒng)為你設置邊緣距離榆苞,可以做以下設置:
if(@available(iOS11.0, *)) {? ? ? ? ss.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;? ? }
(3)通過設置addtionalSafeAreaInset屬性
iOS 11之前,大家是通過將Controller的automaticallyAdjustsScrollViewInsets屬性設置為NO霞捡,來禁止系統(tǒng)對tableView自動調(diào)整contentInsets的坐漏。如果還是想從Controller上解決問題,那么可以通過設置Controller的additionalSafeAreaInsets屬性碧信,如果SafeAreaInset值為(20,0,0,0)赊琳,那么設置additionalSafeAreaInsets屬性值為(-20,0,0,0),則SafeAreaInsets不會對adjustedContentInset值產(chǎn)生影響砰碴,tableView內(nèi)容不會向下偏移20px躏筏。
這里需要注意的是addtionalSafeAreaInset是Controller的屬性,要知道SafeAreaInset的值是由哪個Controller引起的呈枉,可能是由自己的Controller調(diào)整的趁尼,可能是navigationController調(diào)整的。是由哪個Controller調(diào)整的猖辫,則設置哪個Controller的addtionalSafeAreaInset值來抵消掉SafeAreaInset值酥泞。
(4)實現(xiàn)UITableView的數(shù)據(jù)源方法
當UITableView的style為UITableViewStyleGrouped類型,默認UITableView每個section的開頭和結尾是有間距的啃憎,不需要這個間距的話芝囤,可以通過實現(xiàn)heightForHeaderInSection方法(返回一個較小值:0.01)和viewForHeaderInSection(返回一個view)來去除頭部的留白,底部同理辛萍。
iOS 11上發(fā)生tableView頂部有留白悯姊,原因是代碼中只實現(xiàn)了heightForHeaderInSection方法,而沒有實現(xiàn)viewForHeaderInSection方法叹阔。那樣寫是不規(guī)范的挠轴,只實現(xiàn)高度,而沒有實現(xiàn)view.雖然這樣寫在iOS11之前是沒有問題的耳幢,iOS11之后應該是由于開啟了估算行高機制引起了bug。添加上viewForHeaderInSection方法后欧啤,問題就解決了睛藻。或者添加以下代碼關閉估算行高邢隧,問題也得到解決店印。
BUT 你的controller中使用了tableviewHeader的話。這樣設置是不行的倒慧。而且這樣設置在高版本系統(tǒng)中頭部會超出controller的view的按摘。
其實我們只需要在約束中加入包券。
? ? [self.tableViewHeaderView mas_makeConstraints:^(MASConstraintMaker *make) { ? ? ? ?if(@available(iOS11.0, *)) {
? ? ? ? ? ? make.top.equalTo(self.tableView);
? ? ? ? }
? ? }];
就可以解決問題,而且在高版本系統(tǒng)中不會出現(xiàn)問題炫贤。