適配iOS11--contentInsetAdjustmentBehavior

weixin_34146805發表於2018-06-29

一.bug展示

Xcode 升級到 9.0beta版本後,公司中的專案執行到iOS11的裝置上出現了一個UI Bug,就像下面這種情況.

1745083-f3ea0650663693a7.png
image.png

很顯然,tableView有了額外的內邊距.程式碼執行到之前的環境上是沒問題的,可用Xcode9一編譯,再跑到iOS11上就會出現這麼嚴重的問題...

二.問題產生原因

先貼一段設定tableView的程式碼

private func setupTableView() {
        tableView = UITableView()
        tableView.frame = view.bounds
        tableView.dataSource = self
        tableView.delegate = self
        tableView.backgroundColor = UIColor.red
        // 公司的專案中導航欄是不透明的,所以需要加上這兩行程式碼,我們自己來計算scrollView的內邊距
        extendedLayoutIncludesOpaqueBars = true;
        automaticallyAdjustsScrollViewInsets = false;
        // 設定tableView的內邊距(能夠顯示出導航欄和tabBar下覆蓋的內容)
        tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0)
        // 設定內容指示器(滾動條)的內邊距
        tableView.scrollIndicatorInsets = tableView.contentInset
}

關於extendedLayoutIncludesOpaqueBarsautomaticallyAdjustsScrollViewInsets

  • 這兩個屬性屬於UIViewController
  • 預設情況下extendedLayoutIncludesOpaqueBars = false 擴充套件布局不包含導航欄
  • 預設情況下automaticallyAdjustsScrollViewInsets = true 自動計算滾動檢視的內容邊距
  • 但是,當 導航欄不透明時,而tabBar為透明的時候,為了正確顯示tableView的全部內容,需要重新設定這兩個屬性的值,然後設定contentInset(參考程式碼).

上面的程式碼邏輯沒有問題,但是放到iOS11 上為啥錯了呢?
找了半天,點開了automaticallyAdjustsScrollViewInsets 這個屬性,發現這個屬性在iOS11過期了,如圖:

1745083-3ea166abc2eecf69.png
image.png

在OC的宣告中,這個屬性是這樣的:
@property(nonatomic,assign) BOOL automaticallyAdjustsScrollViewInsets API_DEPRECATED_WITH_REPLACEMENT("Use UIScrollView's contentInsetAdjustmentBehavior instead", ios(7.0,11.0),tvos(7.0,11.0)); // Defaults to YES
這說明在iOS11 中, UIViewControllerautomaticallyAdjustsScrollViewInsets屬性已經不再使用,我們需要使用UIScrollViewcontentInsetAdjustmentBehavior 屬性來替代它.

關於contentInsetAdjustmentBehavior

@available(iOS 11.0, *)
public enum UIScrollViewContentInsetAdjustmentBehavior : Int {

    case automatic // Similar to .scrollableAxes, but will also adjust the top & bottom contentInset when the scroll view is owned by a view controller with automaticallyAdjustsScrollViewContentInset = YES inside a navigation controller, regardless of whether the scroll view is scrollable

    case scrollableAxes // Edges for scrollable axes are adjusted (i.e., contentSize.width/height > frame.size.width/height or alwaysBounceHorizontal/Vertical = YES)

    case never // contentInset is not adjusted

    case always // contentInset is always adjusted by the scroll view's safeAreaInsets
}

UIScrollViewContentInsetAdjustmentBehavior 是一個列舉型別,值有以下幾種:

  • automaticscrollableAxes一樣,scrollView會自動計算和適應頂部和底部的內邊距並且在scrollView 不可滾動時,也會設定內邊距.
  • scrollableAxes 自動計算內邊距.
  • never不計算內邊距
  • always 根據safeAreaInsets 計算內邊距
    很顯然,我們這裡要設定為 never

三.開始適配

swift 中

private func setupTableView() {
        tableView = UITableView()
        tableView.frame = view.bounds
        tableView.dataSource = self
        tableView.delegate = self
        tableView.backgroundColor = UIColor.red

        extendedLayoutIncludesOpaqueBars = true;
        if #available(iOS 11.0, *) {
            tableView.contentInsetAdjustmentBehavior = .never
        } else {
            automaticallyAdjustsScrollViewInsets = false;
        };
        tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0)
        tableView.scrollIndicatorInsets = tableView.contentInset
}

OC 中


self.extendedLayoutIncludesOpaqueBars = YES;
if (@available(iOS 11.0, *)) {
        self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
        self.automaticallyAdjustsScrollViewInsets = NO;
}
_tableView.contentInset = UIEdgeInsetsMake(64, 0, 49, 0);
_tableView.scrollIndicatorInsets = _tableView.contentInset;

就是這麼簡單,如果幫你解決了問題或者提供一些思路的話麻煩給個小心鼓勵一下,回見~

相關文章