背景

iPhone X 刘海机于9月13日发布,给科技小春晚带来一波高潮。作为开发人员却多出来一份忧虑,iPhone X 怎么适配?我们 App 的脑袋会不会也长一刘海出来?Tabbar 会不会被圆角?先来看一下美团 App 的表现:

图 1.1 启动时的 App 表现           图 1.2 下拉刷新之后的表现

图 1.3 搜索的表现          图 1.4 “我的Tab”表现

在图1.1中乍一看表现还不错,可是在图1.2中,下拉刷新之后,我们的导航栏还是被刘海挡住了。搜索也中枪,搜索首页没有办法取消,“热门搜索区域”也多出来一块儿空白。另外,“我的Tab”页部分如图1.3、图1.4所示,导航栏回不去了,右上角的三个UIBarButtonItem也不见了。其他还有很多UI上的Bug,等着我们去一一发现并修改。

针对可能出现的问题,苹果在 developer.apple.com 上给出了一些建议。其中一个是 HIG (Human Interface Guideline)。另外 WWDC 会议官方 App 的作者,也给出了适配时的一些经验

我们来看看他们是怎么说的。

HIG部分

首先看一下各个机型尺寸的变化。

图 2.1 各版本 iPhone 的尺寸

下图是 iPhone X 对比其他机型的变化部分。iPhone X 和 iPhone 8 的宽度一致,在垂直方向上多了145pt,这就意味着首页可以展示更多的内容,多出来的这20%的垂直空间,也许可以挂上更高价值的运营位。

图2.2 iPhone X 和其他设备的尺寸对比

布局

注意图2.2蓝色部分,你会发现这些都算在了展示内容的区域。所以我们在设计的时候,要避免内容被圆角、刘海给挡住。Like this:

图 2.3 CGRectMake(0,0,100,100)

iPhone X 的坐标系统以及能显示内容的区域如下图所示:

图 2.4 iPhone X 的显示区域

Status Bar

iPhone X 上的 StatusBar 高度比之前的 iPhone 高一些,也就是说,我们如果写死20pt高度的 frame 布局,都要大面积修(tu)改(xue)。在 iPhone X 上,通过打印 [[UIApplication sharedApplication] statusBarFrame] 可以看到,高度是44pt。

图 2.5 iPhone X 的状态栏高度

"如果你的 App 是隐藏 StatusBar 的,建议重新考虑。iPhone X 为用户在垂直空间上提供了更多展示余地,且状态栏中也包含了用户需要知道的信息,除非能通过隐藏状态栏带给用户额外的价值,否则苹果建议大家将状态栏还给用户。"

另外还有一点,用户在使用 iPhone X 打电话的时候,StatusBar 的高度也不会发生变化了。

屏幕底部

因为没有了 Home 键,iPhone X 的底部是预留给系统功能的一个区域 - Home Indicator,这部分的高度是34pt。

图 2.6 iPhone X 的 Home Indicator 区域

“如果你的底部是 TabBar,那么 Home Indicator 背景会来自于 TabBar 背景的延伸,如果我们是一个 feed 流的页面,那么底部会展示 feed 流的局部。”

意思是如果有 TabBar,那么那个区域会延展你的 barTintColor;没有的话,就显示透明的(参照 Setting)。之所以这么设计,是为了让 indicator 清晰可见,告诉用户你可以滑动这部分区域。所以苹果不建议我们的 UI 元素过于靠近这部分区域。

图 2.7 有 TabBar 的 Home Indicator 区

SafeArea

iOS 11 废弃了 iOS 7 之后出现的 topLayoutGuide/bottomLayoutGuide,取而代之的是safeLayoutGuide 概念。我们的UI元素都应该布局在这些区域之内,避免被各种 bar(NavgationBar、ToolBar、TabBar、StatusBar)遮挡。

图2.8 iPhone 的 SafeArea

如果我们用了 AutoLayout,并且开启了 safeAreaLayoutGuide,布局会自动加上这些 safeLayoutGuide,你的视图不会超出这部分 SafeArea。如2.9所示,如果你需要增加 Guide 的区域,那么可以设置 self.additionalSafeAreaInsets 来增加区域。

图 2.9 默认的 SafeArea 和 self.additionalSafeAreaInsets = UIEdgeInsetsMake(64, 0, 0, 0);

其他

还有其他的一些改变,比如图片的 Aspect Ratio 在 iPhone X 上的表现也会有所不同了;

刘海两边的区域都能响应不同的手势,最好不要和自己的 App 发生冲突。

来自Session 201的建议

① xib 里适配 iPhone X 的话,可以开启 UseSafeAreaLayoutGuides(但这需要在 iOS 9 之后才能用,需要看你的 App 最低支持的版本)。

图3.1 xib 属性

② 如果用的系统 SearchViewController,发现没有灰色蒙层了,可以这么试试。

图3.2 iOS 11 UISearchViewController适配

之所以可以这么改,是因为 iOS 11 的 NavigationBar 和 SearchViewController 集成在一块儿了。

③ 横屏下的 UITableView,SenctionHeader 的背景颜色不是设置的那个颜色。

图3.3 iOS 11 横屏 Tableview 的作用方式

这个问题的原因是:横屏下的 UITableView,Cell 都是和屏幕一样宽,但是 Cell 的 ContentView 会被 inset 到 SafeArea 区域。
解决方法是:可以通过调整 Tableview 的默认行为,改变 contentView 的属性(如上图 inset To SafeArea)来让 contentview 顶到边缘,弊端是会改变整个 cell 的内容显示,而且 contentView 的 layoutMargin 依然还是相对于 SafeArea 的。
最佳方案是:改变 UITableViewHeaderFooterView.backgroundView 的 backgroundColor。

图3.4 iOS 11 修改前后的样式对比

刘海打理初体验

① 我们来看下开头说的那个刷新之后首页顶上去的问题怎么处理。经过排查,这个问题属于“状态栏变高系列”,解决方案就是把固定的20pt高度改成 [[UIApplication sharedApplication] statusBarFrame].size.height]

② 搜索页面输入框的位置发生了偏移,这是因为 iOS 11 的导航栏的视图层级结构发生了变化,和 iPhone X 的并无直接关系。iOS 11 导航栏的视图层级关系如下:

图4.1 iOS 11 之后的 NavigationBar     图4.2 iOS 11 之前的 NavigationBar

适配方式是:取到这个 _UIButtonBarStackView 的位置和尺寸信息,然后更改 PFBNavigationBarContainerView 的 X 坐标。

③ “我的Tab” 页面多出来一块儿灰色的区域,经过排查发现这个是 Tableview 的背景色。也就是说其实是 Tableview 向下偏移了。

图4.3 iOS11 下“我的Tab” 页面 Tableview 发生偏移

出现这个的原因是:iOS 11 之后 scrollview 多出来一个 adjustedContentInset 区域。

图 4.4 iOS 11下 ScrollView 的新属性

通过打印这个值,我们发现正好和 contentoffset.y 相符合。

图 4.5 这个新属性在 iPhone X 上的值

那为什么会发生偏移?这个偏移的值又是怎么确定的?其实是当 Tableview 的 frame 超出了 safeArea 范围之后,系统会调整内容的位置。系统通过设置 adjustedContentInset 为 safeAreaInset 的值让 Tableview 偏移

图 4.6 iPhone X 上 safeAreaInset 的值

注意一下这个 adjustedContentInset 是 readOnly 的属性。我们可以通过设置 Tableview.contentInsetAdjustmentBehavior=UIScrollViewContentInsetAdjustmentNever 来纠正这个位置。当然还可以通过设置 tableview.contentOffset 来抵消这个值,但还是推荐第一种。

④ “我的Tab” 导航栏上,右边那个按钮全都发生了偏移,导致无法点击。这个问题也是在新的导航栏结构视图下会出现,原因是新的导航栏结构用了 AutoLayout 布局,我们这个并不是用常规的 UIBarButtonItem 方式实现的,而是一个 UIBarButtonItem ,他的 customView 包含了三个 Button,这几个 Button 都是 frame 布局,从而导致了在 AutoLayout 下的布局问题。

正常的解决方式是:修改成一个一个添加 UIBarButtonItem 和 UIBarButtonSystemItemFixedSpace。但是这样引出来另外一个问题,iOS 11 之前那种设置负宽度的 fixedspace 来调整间距的 trick 方式已经失效了!详情见https://forums.developer.apple.com/thread/80075

我们这边的方式是:依然用那种一个 CustomView 里包含三个 CustomButton 的方式,然后分别加上约束。CustomView 只需要加上宽高,包含的 Button 加上 left、top 和 size。

图 4.7 加约束修正后样式

以下是尝试修复这部分问题的代码:

// offset 问题
if (@available(iOS 11.0, *)) {
self.contentViewController.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
// UIBarButtonItem 问题
if (@available(iOS 11.0, *)) {
[messageButtonsContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(themeButton.width + settingButton.width + messageButton.width, 44));
}];
[themeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(messageButtonsContainerView);
make.left.equalTo(messageButtonsContainerView);
make.size.mas_offset(CGSizeMake(44, 44));
}];
[settingButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(messageButtonsContainerView);
make.left.equalTo(themeButton.mas_right);
make.size.mas_offset(CGSizeMake(44, 44));
}];
[messageButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(messageButtonsContainerView);
make.left.equalTo(settingButton.mas_right).offset(-10);
make.size.mas_offset(CGSizeMake(44, 44));
}];
} UIBarButtonItem *rightBarItem = [[UIBarButtonItem alloc] initWithCustomView:messageButtonsContainerView];
self.navigationItem.rightBarButtonItems = @[rightBarItem];

总结

当前发现这些问题的环境是 Xcode 9 GM版本(9A235)的模拟器。归结起来是三类问题:

  1. StatusBar 变高并且绝对布局。
  2. 导航栏的视图层级结构发生变化而导致 UI(titleView、UIBarButtonItem) 问题。(iPhone 6s iOS 11 上依然是旧的结构,是因为现在 AppStore 上的包依然是用 iOS 10 的 SDK 打出来的)。
  3. safeAreaInset 导致 Scrollview 偏移。

至于 Tabbar ,因为我们用的是系统的,所以目前并没有发现什么奇怪的地方。希望我们踩的这些坑可以让各位在适配的过程中少走一些弯路!

源:https://tech.meituan.com/iPhoneX%E5%88%98%E6%B5%B7%E6%89%93%E7%90%86%E6%8C%87%E5%8C%97.html

iPhone X 适配的更多相关文章

  1. iOS开发点滴:iPhone屏幕适配

    最近开始做iOS开发,遇到一些小问题和解决方法,记录下.   今天是iPhone屏幕适配 iPhone5出来之后屏幕就有iPhone就有了2种尺寸:3.5寸和4寸,xcode 5 的IB设计器里面界面 ...

  2. 大屏iPhone的适配 +iOS 图片尺寸要求

    摘自:http://blog.ibireme.com/2014/09/16/adapted_to_iphone6/ 苹果公司官网设计介绍到:Retina显示屏的超高像素密度已超过人眼能分辨的范围.Re ...

  3. iOS 11 & iPhone X 适配资料集

    本文主要简单谈谈并收集一些关于 iOS 11 & iPhone X 的适配及设计指南. iPhone X 众所周知,iPhone X 屏幕与其他的 iPhone 设备均不同,苹果称 iPhon ...

  4. 混合式App开发 Apicloud 官方iPhone X 适配

    iPhone X 适配 由于iPhone X的特殊造型,为了方便开发者对iPhone X进行适配,苹果在iOS 11中引入了Safe Area的概念,引擎也在api对象下添加了safeArea属性和s ...

  5. 微信小程序中的iPhone X适配问题

    微信小程序中的iPhone X适配问题 小程序中下方的导航会被iPhone X下面的那条黑线盖住[微笑脸],所以要专门为了iPhone X做样式上的适配[微笑脸] wx.getSystemInfo({ ...

  6. 移动端iPhone系列适配问题的一些坑

    完成移动端的开发项目之后,发现谷歌自带的调试器似乎没有什么太大的作用,整天借同事的苹果手机测bug,尽管同事不厌其烦,但还是觉得这iPhone系列适配问题适配到想逃逃逃,好在项目已经顺利完成,测试通过 ...

  7. iOS - iPhone屏幕适配/启动图适配/APP图标适配(iPhone最全尺寸包含iPhoneX/XR/XS/XS Max等)

    趁iPhone新品还没有发布,先整理一下屏幕适配.启动图适配.APP图标适配的笔记,方便以后查阅: 注:部分图片来源于网络 违删; (一)iPhone屏幕适配: (1)屏幕分辨率: ①设计尺寸规范(表 ...

  8. iPhone屏幕适配,历史及现状(http://hjcapple.github.io/2014/10/10/iphone-screen.html)

    iPhone屏幕适配,历史及现状 初代iPhone 2007年,初代iPhone发布,屏幕的宽高是320×480像素.下文也是按照宽度,高度的顺序排列.这个分辨率一直到iPhone 3GS的也保持不变 ...

  9. iPhone X适配方案

    iPhone X适配方案 https://github.com/Wscats/iPhone-X 绝对长度单位 英寸 厘米 毫米 磅 pc inch cm mm pt pica 相对长度单位 是网页设计 ...

  10. ipad和iphone的适配

    关于xib或者storybord下iphone的横竖屏的适配以及ipad的适配 ios8出现了Size Classes,解决了各种屏幕适配的问题,他把屏幕的宽和高分别分成了三种,把屏幕总共分成了九种情 ...

随机推荐

  1. 逐步搭建Lamp环境之Linux的运行模式

    首先先来看几个概念,分别是:单用户.单任务.多用户.多任务 单用户: 是指操作系统一般只能由一个人同时进行登录 单任务: 是指操作系统只能同时处理一个任务 多用户: 是指操作系统可以允许由多个用户同时 ...

  2. 【特征匹配】BRISK原文翻译

    原文:Stefan Leutenegger, Margarita Chli et al.<BRISK: Binary Robust Invariant Scalable Keypoints> ...

  3. 关于O(logN)的正确理解

    学计算机的或许对O(logN)这个符号并不陌生,快排.堆排.归并等等排序的平均时间复杂度. 问题来了,之前一直有个歧义就是:logN的底数到底是多少? 这个问题搁置着并没有去深究,仅仅是想应该是2吧. ...

  4. redis的list类型

    1.简单介绍 redis的list类型其实就是一个每个元素都是string类型的双向链表.所以lpush.rpush.lpop和rpop命令的时间复杂度是O(1),list会记录链表的长度,所以lle ...

  5. 数据分析与展示——Matplotlib基础绘图函数示例

    Matplotlib库入门 Matplotlib基础绘图函数示例 pyplot基础图表函数概述 函数 说明 plt.plot(x,y,fmt, ...) 绘制一个坐标图 plt.boxplot(dat ...

  6. IOS学习1——IOS应用程序的生命周期及基本架构

    一.应用程序的状态和多任务 有时系统会从app一种状态切换另一种状态来响应系统发生的事件.例如,当用户按下home键.电话打入.或其他中断发生时,当前运行的应用程序会切换状态来响应.应用程序的状态有以 ...

  7. tesserat训练中文备忘录

    最近用OCR识别身份证,用的tesseract引擎.但是google自带的中文库是在太慢了,尤其是对于性别.民族这样结果可以穷举的特征信息而言,完全可以自己训练字库.自己训练字库不仅可以提高识别速度, ...

  8. 507. Perfect Number

    We define the Perfect Number is a positive integer that is equal to the sum of all its positive divi ...

  9. ArcGIS API for JavaScript 4.2学习笔记[12] View的弹窗(Popup)

    看本文前最好对第二章(Mapping and Views)中的Map和View类有理解. 视图类有一个属性是Popup类型的popup,查阅API知道这个就是视图的弹窗,每一个View的实例都有一个p ...

  10. NP完整性| 集1(简介)

    我们一直在写关于高效算法来解决复杂问题,如最短路径,欧拉图,最小生成树等.这些都是算法设计者的成功故事. 在这篇文章中,讨论了计算机科学的失败故事. 计算机可以解决所有的计算问题吗? 存在计算问题,即 ...