iOS 11.0 iPhone X SafeArea向下兼容

随着iPhone X的发布,界面上变化最大的当属NavigationBar和TabBar,如果我们通过Frame定义视图的位置,则需判断设备类型是否为iPhone X,我们是否可以通过一种更优雅的方式,视图展示时不需要关心设备类型。

  • 首先我们介绍几个iOS知识点

    1. iOS 11 的 Safe Area

      XIB勾选Use Safe Area Layout Guide最低支持的版本iOS9.0

      屏幕快照 2017-11-07 下午3.24.35.png

      代码方式实现SafeArea

      @property (nonatomic,readonly) UIEdgeInsets safeAreaInsets API_AVAILABLE(ios(11.0),tvos(11.0));

    image.png
    1. Top Layout Guide 和 Bottom Layout Guide

      topLayoutGuide.length:表示当前页面的上方被status bar、navigation bar遮挡的部分,对应safeAreaInsets.top

      bottomLayoutGuide.length:表示当前页面的下方被TabBar、ToolBar遮挡的部分,对应safeAreaInsets.bottom

      这两个属性属于ViewController

  • 实现

    1. 思路

      是否我们可以给UIViewController增加一个视图(ContentView),ContentView根据SafeArea自动适应,其它的视图添加到ContentView,这样就不需要关心导航栏和TabBar的高度

      • 创建基类ViewController,ViewController添加一个视图,该视图针对SafeArea做好约束条件,项目中所有的Controller都继承这个类,这种方式侵入性太强

      • 通过Category的方式,UIViewController增加一个视图属性,当Controller中添加视图时,都增加到Category类中的这个视图上,这种方式,如果用户不调用Category增加的视图,不对Controller有任何影响

    2. 代码

UIViewController+SafeArea.h

@interface UIViewController (SafeArea)

@property (nonatomic, strong) UIView    *contentView;

@end
#import "UIViewController+SafeArea.h"
#import 
#import "Masonry.h"

static const void *ContentView = &ContentView;

@implementation UIViewController (SafeArea)

- (void)setContentView:(UIView *)contentView {
    objc_setAssociatedObject(self, ContentView, contentView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIView *)contentView {
    UIView *view = objc_getAssociatedObject(self, ContentView);
    if (!view) {
        view = [UIView new];
        view.backgroundColor = [UIColor clearColor];
        self.contentView = view;
        [self.view addSubview:view];
        
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.and.right.equalTo(self.view);
            if (@available(iOS 11.0, *)) {
                make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
                make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
            } else {
                self.automaticallyAdjustsScrollViewInsets = NO;
                make.top.equalTo(self.mas_topLayoutGuide);
                make.bottom.equalTo(self.mas_bottomLayoutGuide);
            }
        }];
    }
    return view;
}

@end
  1. 使用

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.title = @"SafeArea";
    
    [self.contentView addSubview:self.tableView];
    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.top.bottom.and.right.equalTo(self.contentView);
    }];
}

注意如果项目首页展示UICollectionView,启动页状态栏默认隐藏,这时候再进入到首页UICollectionView中的cell展示出现问题,我们需要特殊处理

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    
    [self.collectionView.collectionViewLayout invalidateLayout];
}

完整的使用例子可以参考:

https://github.com/cheyongzi/SafeArea

觉得还不错的可以给个Star

你可能感兴趣的:(iOS 11.0 iPhone X SafeArea向下兼容)