iOS11及iPhoneX适配

苹果公司于9月份如期发布了新的iPhone-iPhone8,iPhone8 Plus,iPhoneX,前两个不用多说,正常形态的iPhone和前代外观上没有太大区别。iPhoneX则带来了不同的样式,不同的体验,18:9的全面屏屏幕,小刘海,去掉Home键后超前的交互方式。当然对于开发者也带来了对于这块屏幕的适配问题。我想苹果爸爸决定在11月初开售iPhoneX也有一部分让开发者对自己的App做iPhoneX适配的一部分原因,毕竟现在Xcode已经有iPhoneX的模拟器了。

过去,我们拿到的手机是方方正正的矩形,所以整个屏幕都可以看做是安全区域Safe Area,而如今由于iPhone X屏幕上的“刘海”以及屏幕四周采用圆角的设计,需要设计师对绘图区域做出调整。苹果给出的安全区域如下

image ![](http://upload-images.jianshu.io/upload_images/1346171-d08f0e41eb1c5c77.gif?imageMogr2/auto-orient/strip)

页面内容不能超出安全区域(Safe Area)

image

下面我们以通讯录和News应用为例看下iPhoneX模拟器中原生应用对于这块全面屏如何适配的

iPhoneX System App.gif

通过例子我们可以发现主要的三点原则:

  1. 带有空间按钮的顶部导航栏(NavigationBar)要处在“刘海”下面
  2. 底部导航栏(Tabbar)不能在虚拟横条Home键(不知道咋叫,暂且这么叫吧)下面,也就是说要和屏幕底部保持距离
  3. 可滚动的列表整块屏幕都是可展示的,但是滚动条要和顶部和底部保持距离不能超出

基本以上三点原则可以概括为一句话,所有不可滚动的控件推荐在安全区域内展示,可滚动的控件整个屏幕都可以用来展示

这么做也算是充分利用了这块屏幕,并且不影响用户正常使用iPhoneX了

Toon的适配

初期Toon对于iPhoneX的适配基本为0,所以出现不少问题,主要集中以下几点:

  1. 顶部导航栏和底部导航栏超出安全区域
  2. 没有导航栏的列表没有全屏展现
  3. 吸底按钮超出安全区域
  4. 顶部导航栏UI错乱
  5. 列表加载控件在安全区域外部展示

下面通过一个Gif图来看下未经过适配的Toon的部分界面在iPhoneX上表现

iPhoneX System App1.gif

可见未经适配的Toon将会以16:9的样子展现在用户手中,这对于产品在iPhoneX中的体验来说将会是极大的灾难,没有充分利用iPhoneX的全面屏,用户体验将是缺失的

经过一段时间的适配,现在开发版的Toon在iPhoneX上已经可以有良好的展示了,虽然还有很多地方没有经过重新设计和优化,不过已经利用了iPhoneX的屏幕展示了

iPhoneX System App2.gif

经过一段时间的适配,解决了16:9展示,导航栏错位等问题,在的问题主要集中在列表底部加载控件的问题等问题上,接下来本文将通过Demo和Toon的部分界面来具体讲一下iPhoneX UI适配上的问题

启动页的适配

如果对于启动页不做任何适配,那么App启动后你会发现应用是16:9的样式展示的

解决方案有两种:

  1. Xib或者Stroyboard来作为应用的启动图
  2. 添加iPhoneX下启动页的图片

Toon工程中采取的方案是第二种

屏幕快照 2017-09-26 下午11.53.29.png

顶部的适配

以前通过加减20来覆盖或者避免状态的代码都会出问题在iPhoneX上

image

状态栏高度不是20了,iOS11安全区的提出,在iPhoneX上状态栏的高变为44
代码中需要通过[UIApplication sharedApplication].statusBarFrame.size.height获取状态栏高度

[self.tableView mas_remakeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(self.view.mas_top).offset([UIApplication sharedApplication].statusBarFrame.size.height);
    make.bottom.equalTo(self.view.mas_bottom);
    make.left.equalTo(self.view.mas_left);
    make.right.equalTo(self.view.mas_right);
}];
image

iOS11automaticallyAdjustsScrollViewInsets属性废弃了会出现ScorllView下沉20的现象

image

可以调用scrollview新的apicontentInsetAdjustmentBehavior

self.automaticallyAdjustsScrollViewInsets = NO;
if (@available(iOS 11.0, *)) {
    self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
image

但是这么写会导致在iPhoneX下出现,由于在X下安全区域的出现,顶部异形区域不建议覆盖,会造成视觉的差异

image

在代码中我们需要来根据设备高度来判断iPhoneX,从而来避免这种情况

[self.tableView mas_remakeConstraints:^(MASConstraintMaker *make) {
    if (CGRectGetHeight([UIScreen mainScreen].bounds) == 812.0) {
        if (@available(iOS 11.0, *)) {
            make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
        }
    } else {
        make.top.equalTo(self.view.mas_top);
    }
    make.bottom.equalTo(self.view.mas_bottom);
    make.left.equalTo(self.view.mas_left);
    make.right.equalTo(self.view.mas_right);
}];
image

如果用了MJRefresh在iPhoneX下列表顶部会出现这样的情况,顶部刷新控件会有露出,UI不美观

image

如果设置contentInsetAdjustmentBehaviorUIScrollViewContentInsetAdjustmentNever,并且设置顶部距离为导航栏距离,又会造成全面屏展示不充分也不是很好

- (void)viewDidLoad {
    [super viewDidLoad];
    <!--省略部分代码-->
    if (@available(iOS 11.0, *)) {
        self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }
    <!--省略部分代码-->
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    [self.tableView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top).offset(self.view.layoutMargins.top);
        <!--省略部分代码-->
    }];
}
image

我建议的适配方式,根据具体情况来设置contentInset的值

- (void)viewDidLoad {
    [super viewDidLoad];
    <!--省略部分代码-->
    if (@available(iOS 11.0, *)) {
        self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }
    <!--省略部分代码-->
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];
    if (CGRectGetHeight([UIScreen mainScreen].bounds) == 812.0) {
        // 只在iPhoneX下适配
        if (@available(iOS 11.0, *)) {
            self.tableView.contentInset = UIEdgeInsetsMake(self.view.safeAreaInsets.top, 0, 0, 0);
        }
    }
    [self.tableView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top).offset(0);
        <!--省略部分代码-->
    }];
}

使用以上代码,或者UI设计顶部刷新控件都样式都可以解决该问题,但是我觉得最终极的解决方案还是UI设计根据iPhoneX的异性全面屏给以良好的适配方案,如果有更好的设计方案,比如当列表为初始滚动状态时不显示顶部刷新控件,可以跟我交流

image

顶部的适配问题主要集中体现在以前通过写死状态高度20造成的,对于这个问题,只要调用系统提供获取状态栏高度的方法,就可以避免,至于顶部刷新控件的问题,这个本文建议采取和本文建议的处理底部加载控件的方案来实施,具体可以继续看下文

底部的适配

底部导航栏

如果是采用系统默认的底部导航栏,没有采用自定义的方式,底部导航栏iOS系统级就做了处理,会保证在Tabbar是在安全区域之内

如果是采取自定义的方式那么则要对做出响应的处理

+ (CGFloat)computeTabbarHeight {
    NSInteger style = [[TNAppStackManager shareInstance] rootStyle];
    if (style == RootControllerStyle_TabCircleDrawer || style == RootControllerStyle_TabCircleNoDrawer) {
        return 70.;
    } else if (style == RootControllerStyle_TabNormal) {
        return [[UIDevice currentDevice] systemVersion].doubleValue >= 11.0 ? (fabs(CGRectGetHeight([UIScreen mainScreen].bounds) - 812.) >= 1.0 ? 49. : 83.) : 53.;
    }
    
    return 0;
}

以上是Toon工程在处理底部导航栏高度的示例代码,通过系统版本和设备来判断具体导航栏的高度

列表底部加载控件的的处理

列表的底部加载控件和在全屏下的顶部刷新控件的问题是我认为不不好给出解决方案的问题

iOS11废弃了原有的automaticallyAdjustsScrollViewInsets属性,为scrollview添加了新的属性
contentInsetAdjustmentBehavior

现在对于我列表的适配,我看大都是这个样子的

self.automaticallyAdjustsScrollViewInsets = NO;
if (@available(iOS 11.0, *)) {
    self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;

这两个属性都是为了让列表对于全屏和异形屏幕下有良好的展示设计的,对于非全屏状态下的列表,这两个属性不处理没有关系,因为只有在全屏或者半全屏(只有顶部导航或者)

对于Toon来说,刚开我们对于所有的列表都将上面的属性置为了UIScrollViewContentInsetAdjustmentNever,这样在iPhoneX部分界面就变成这样了

iPhoneX示例
iPhoneX示例

会发现在iPhoneX下,tableView展示区域是到底的,这样会影响用户使用home虚拟横条,所以这个值是需要根据具体情况分析的,例如如果tableView是全屏展示的就需要设置为UIScrollViewContentInsetAdjustmentNever

在此基础上需要适配就是tableView的刷新控件和加载控件了,假设大家使用的都是MjRefresh,那么对于刷新控件出现的问题上文已经讲过了,不在赘述。我们来讨论下加载控件会出现的问题。

刷新控件还好,大部分刷新控件都是在有顶部导航栏的情况下,可是底部加载控件不同,又很多处理方式,本文只做一个抛砖引玉的示例,具体处理方式还是要结合产品、UI、技术来以前讨论针对具体情况具体分析,接下来我将会以Toon中小组模块我的评论界面为例,给出我的解决方案

如果contentInsetAdjustmentBehavior设置为UIScrollViewContentInsetAdjustmentNever,那么出现的问题是,底部加载控件会在安全区域意外露出。

Simulator Screen Shot - iPhone X - 2017-09-29 at 00.06.07.png

为了明显我讲底部加载控件的背景色置成了橙色,可以看到正常情况,加载控件是暴露在安全区域外部,上面的文字也能看到,这样一来既不没关也显得不够专业,并且文字也被home虚拟横条挡住了

那么怎么处理这种情况才会更好些呢,本文给的解决方案是给底部加载控件加一个遮罩,而这个遮罩是根据,tableView的偏移量来展示的,最后的效果如下。

iPhoneX System App4.gif

核心代码如下:

- (void)setLoadFooter {
    self.tableView.mj_footer = [MJRefreshBackStateFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadCommentData)];
    self.tableView.mj_footer.backgroundColor = [UIColor orangeColor];
    self.tableView.mj_footer.maskView = [[UIView alloc] init];
    self.tableView.mj_footer.maskView.backgroundColor = [UIColor whiteColor];
    [self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if (object == self.tableView && [keyPath isEqualToString:@"contentOffset"]) {
        if (@available(iOS 11.0, *)) {
            /*
             判断设备为iPhoneX时,
             并且contentInsetAdjustmentBehavior不为UIApplicationBackgroundFetchIntervalNever
             */
            if (CGRectGetHeight([UIScreen mainScreen].bounds) == 812.0 && self.tableView.contentInsetAdjustmentBehavior == UIScrollViewContentInsetAdjustmentAutomatic) {
                CGFloat distanceToSafeBottom = (self.tableView.contentOffset.y + CGRectGetHeight(self.tableView.frame) - self.view.safeAreaInsets.bottom) - self.tableView.contentSize.height;
                if (distanceToSafeBottom < 0) {
                    self.tableView.mj_footer.maskView.frame = CGRectZero;
                } else {
                    CGFloat showFooterHeight = distanceToSafeBottom;
                    if (showFooterHeight > CGRectGetHeight(self.tableView.mj_footer.bounds)) {
                        showFooterHeight = CGRectGetHeight(self.tableView.mj_footer.bounds);
                    }
                    if (self.tableView.mj_footer.state != MJRefreshStateRefreshing) {
                        self.tableView.mj_footer.maskView.frame = CGRectMake(0, 0, CGRectGetWidth(self.tableView.mj_footer.bounds), showFooterHeight);
                    }
                }
            }
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,515评论 25 707
  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,708评论 22 664
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,029评论 4 62
  • 走过多少路口,去过多少城市,瞧过多少人流,看过多少风景。 一起度过无数节日,今却应一道风景而停驻,不忘过去的年年...
    GTR1042阅读 295评论 0 1
  • 早上涂口红把口红弄断了,刚刚开锁把锁芯拔出来了,这样的大力士女孩还有谁
    沧澜鱼阅读 319评论 0 0