1. 程式人生 > >Xcode9 iOS11適配 iPhoneX適配 heightForHeaderInSection、contentInset失效解決 contentInsetAdjustmentBehavior詳解

Xcode9 iOS11適配 iPhoneX適配 heightForHeaderInSection、contentInset失效解決 contentInsetAdjustmentBehavior詳解

1.iPhoneX基本屬性

啟動圖尺寸:1125px × 2436px(即 375pt × 812pt @3x))

iphoneX 螢幕高:812.0個點

導航欄高度+狀態列高度:88.0個點(導航欄高度仍是44個點,狀態列高度增高為44個點,所以劉海的高度並不是狀態列的高度。狀態列和導航欄平分了頭部總的高度)

tabbar高度:83.0個點(原是固定49個點,增高了34個點。所以)


2.MJRefresh錯位等 使用UIScrollview的控制元件的頁面造成的頁面錯位

iOS11廢棄了automaticallyAdjustsScrollViewInsets屬性,需要使用scrollview的contentInsetAdjustmentBehavior屬性。

[objc] view plain copy  print?
  1. if (@available(iOS 11.0, *)) {  
  2.         self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;  
  3.     } else {  
  4.         // Fallback on earlier versions
  5.     }  

3.替換寫死的狀態列高度20 導航欄44  和64。安全起見替換寫死的tabbar高度49

[objc] view plain
 copy  print?
  1. - (CGFloat)tabbarHeight{  
  2.     returnself.tabBarController.tabBar.frame.size.height;  
  3. }  
  4. - (CGFloat)navigationBarHeight{  
  5.     returnself.navigationController.navigationBar.frame.size.height;  
  6. }  
  7. - (CGFloat)naviBarAndStatusBarHeight{  
  8.     CGFloat height = self.navigationController
    .navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height;  
  9.     return height;  
  10. }  


4.UITableView中的UITableViewStyleGrouped型別設定heightForHeaderInSection失效

在iOS11上,原來使用UITableViewStyleGrouped設定的sectionheader高度可能失效。本人發現兩種解決辦法

方法一:.在iOS11上tableview的style使用UITableViewStylePlain。

[objc] view plain copy  print?
  1. UITableViewStyle style = UITableViewStyleGrouped;  
  2.   if (@available(iOS 11.0,*)) {  
  3.       style = UITableViewStylePlain;  
  4.   }  
  5.   self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(00, SCREEN_WIDTH, SCREEN_HEIGHT) style:style];  
然後在代理中照常設定就好了 [objc] view plain copy  print?
  1. - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{  
  2.     return yourHeight;  
  3. }  
  4. //注意,設定heightForHeaderInSection的同時也要實現這個代理。 如果不實現這個代理,仍然會出現間隙不均的情況。
  5. - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{  
  6.     UIView *header = [[UIView alloc] init];  
  7.     header.frame = CGRectMake(00, SCREEN_WIDTH, yourHeight);  
  8.     return header;  
  9. }  

方法二。所有系統下都使用UITableViewStyleGrouped,然後同時實現以下四個代理方法(在iOS11下,對應的sectionHeaderHeight和sectionHeaderView要成對存在,之前只設置sectionHeaderHeight也可以,所以規範起見:統一成雙入對)

[objc] view plain copy  print?
  1. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{  
  2.     return1;  
  3. }  
  4. - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{  
  5.     return CountHeight(30);  
  6. }  
  7. - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{  
  8.     UIView *header = [[UIView alloc] init];  
  9.     header.frame = CGRectMake(00, SCREEN_WIDTH, CountHeight(30));  
  10.     header.backgroundColor = SHBackgroundColor;  
  11.     return header;  
  12. }  
  13. - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{  
  14.     return0.01;//注意這裡!如果你不需要footerView,這裡不能返回0,否則間距還是有問題
  15. }  
  16. - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{  
  17.     return [[UIView alloc] initWithFrame:CGRectZero];  
  18. }  


5.contentInset失效。iOS11下引入了safeArea的概念。需要注意這幾個屬性:

[objc] view plain copy  print?
  1. 1.UIScrollView的屬性contentInsetAdjustmentBehavior  
  2. 2.UIScrollView的只讀屬性adjustedContentInset  
  3. 3.UIView的只讀屬性safeAreaInsets  

iOS11下當你沒有設定contentInsetAdjustmentBehavior時,系統會自動為你將試圖新增到安全區域。

如下圖所示區域


所以,此時你如果仍然設定了contentInset,比如下面的程式碼

[objc] view plain copy  print?
  1. self.tableView.contentInset = UIEdgeInsetsMake(00490);  
就會出現下方多了49個點。

解決辦法仍然是兩個:

方法一:

[objc] view plain copy  print?
  1. if (@available(iOS 11.0, *)) {  
  2.     self.tableView.contentInset = UIEdgeInsetsMake(headerH, 000);  
  3. }else{//11系統以下,如果需要還是要加的
  4.     self.tableView.contentInset = UIEdgeInsetsMake(headerH, 0490);  
  5. }  

方法二:

[objc] view plain copy  print?
  1. if (@available(iOS 11.0, *)) {  
  2.      self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;  
  3.  }else{  
  4.  }  
  5.  self.contentInset = UIEdgeInsetsMake(headerH, 0490);  

6.程式碼塊呼叫失效

Xcode9中原來設定的程式碼塊可能會失效。這個問題比較蛋疼。你去多開啟幾個 多點一下edit,多換一下completion scopes可能就恢復了。


7.contentInsetAdjustmentBehavior詳解

以下引自騰訊bugly博文。(簡單地說就是UIScrollViewContentInsetAdjustmentNever相當於以前的automaticallyAdjustsScrollViewInsets=NO,此時你可遮蔽系統自動調整,佈局由你自己支配。其他三個屬性基本是系統幫你將檢視新增到safeArea裡面)

    /* Configure the behavior of adjustedContentInset.
Default is UIScrollViewContentInsetAdjustmentAutomatic.
*/@property(nonatomic) UIScrollViewContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior

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

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

2.UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滾動方向上adjustedContentInset = safeAreaInset + contentInset,在不可滾動方向上adjustedContentInset = contentInset;依賴於scrollEnabled和alwaysBounceHorizontal / vertical = YES,scrollEnabled預設為yes,所以大多數情況下,計算方式還是adjustedContentInset = safeAreaInset + contentInset

3.UIScrollViewContentInsetAdjustmentNever: adjustedContentInset = contentInset

4.UIScrollViewContentInsetAdjustmentAlways: adjustedContentInset = safeAreaInset + contentInset

當contentInsetAdjustmentBehavior設定為UIScrollViewContentInsetAdjustmentNever的時候,adjustContentInset值不受SafeAreaInset值的影響。