网易100分 iPhone X适配小结

适配的过程有点蛋疼,之后却越看越顺眼。

适配前的准备


拥抱iPhone X的变化

开始适配前,先回顾下,iPhone X相比之前的iPhone设备,带来了哪些不一样的特性:

  1. iPhone X的屏幕尺寸

    iPhone X的宽度同iPhone 6/6s/7/8,但高度多出来145pt,垂直方向可以承载更多内容。对于大多数用ScrollView展示内容的页面来说,这个尺寸的变化对布局影响不大,但对一些内容固定,布局需要强依赖设备尺寸和比例的页面,就需要留意一下,例如整张图片铺满屏幕的页面、启动引导页面、功能引导蒙层。

    这类页面适配时,要注意图片缩放比例要合理,内容要撑满屏幕,不要四周留空白。

  2. 状态栏和导航栏

    iPhone X的刘海,让statusBar变为由原来的20pt变为44pt,导航栏高度默认情况下仍然是44pt,不过iOS 11中新增了一种大标题的导航栏样式,如果设置了prefersLargeTitles = YES,则高度变为96pt。所以在iPhone X上,状态栏加导航栏(默认)高度是88pt,而不是之前的64pt,如果之前有一些隐藏导航栏,或者使用自定义导航栏的页面,都要全部走查一遍。

  3. 安全区域

    iOS 11中新增了Safe Area的概念,它描述了视图不被其他内容遮挡的区域,避开了诸如导航栏,TabBar之类有可能挡住view的视图。iPhone X上默认的根视图的安全区域如下图:

                                                                                                                                                                                                                 

  • 关于安全区域的适配有几点要注意:

     a. 圆角及传感器部分避免用户交互;
     b. 避免干扰底部Home Indicator,要让这部分清晰可见;
     c. 避免干扰系统边缘手势(实在有需求的话,可以开启边缘保护)
    


Safe Area可以有两种方式来获取:safeAreaInsetssafeAreaLayoutGuidesafeAreaInsets属性反映了一个view距离该view的安全区域的边距。对于一个UIViewController的根视图而言,safeAreaInsets值包括了被statusbar和其他可视的bars覆盖的区域和其他通过additionalSafeAreaInsets自定义的insets值。而该视图层级上的其他viewadditionalSafeAreaInsets表示了该视图在父视图范围内的部分被覆盖的区域;

UIView不在视图层级或者屏幕上的时候,safeAreaInsets = UIEdgeInsetsZerosafeAreaLayoutGuide描述的区域也是跟自身一样大。所以要正确获取这两个属性的值,需要注意这两个值改变的时机。由于我们适配时,使用了简单粗暴的方法,这里不展开说明,具体细节可以参考这里


UIView不在视图层级或者屏幕上的时候,safeAreaInsets = UIEdgeInsetsZerosafeAreaLayoutGuide描述的区域也是跟自身一样大。所以要正确获取这两个属性的值,需要注意这两个值改变的时机。由于我们适配时,使用了简单粗暴的方法,这里不展开说明,具体细节可以参考这里

网易100分目前的用户界面布局现状

  • 最低支持系统版本iOS 8.0,无法使用Safe Area Layout Guides,对于旧的页面,以后也不打算使用Safe Area Layout Guides重新布局。
  • 主要的页面内容都是以UIScrollView或其子类来承载的,iOS 11之前,UIViewController默认的automaticallyAdjustsScrollViewInsets = YES可以让页面内容正常显示,在iOS 11之后,这个属性虽然被废弃了,但UIScrollView新增的属性contentInsetAdjustmentBehavior(默认值是UIScrollViewContentInsetAdjustmentAutomatic)也可以确保内容正确显示。
  • 布局时未使用过topLayoutGuidebottomLayoutGuide,基本都是参照superview,所以没有向Safe Area Layout Guides转换的问题。


简单粗暴的宏

为了快速适配,这里定义了几个宏(云课堂同事提供)。虽然有人吐槽这种适配方式扩展性不好,以后万一出现了更多机型,状态栏高度不是44pt了怎么办?最好的方式是都根据安全区域来适配。不过我觉得,就算这情况真的出现了,到时候也避免不了新一轮的适配吧。

#define JYFUHeightNavBar          44
#define JYFUHeightSystemStatus    (JY_IS_IPhoheX ? 44 : 20)
#define JYFUHeightTopBar          (JYFUHeightNavBar + JYFUHeightSystemStatus)   //status bar和nav bar高度
#define JYFUHeightBottomGap       (JY_IS_IPhoheX ? 34 : 0)
#define JYFUHeightTabBar          (49 + JYFUHeightBottomGap)
#define JYFULeftContentMargin     (JY_IS_Protrait ? 0 : (JY_IS_LandScapeLeft ? JYFUHeightBottomGap : JYFUHeightSystemStatus))  //全屏时iphoneX内容左边距,用于假旋转
#define JYFURightContentMargin    (JY_IS_Protrait ? 0 : (JY_IS_LandScapeLeft ? JYFUHeightSystemStatus : JYFUHeightBottomGap))  //全屏时iphoneX内容右边距,用于假旋转


开始适配


启动图

适配iPhone X的第一步就是要给它提供一张启动图,系统是根据是否设置了相应机型的启动图来判断该机型是否适配。

启动图设置有三种方式:

  1. 使用LauchScreen.xib,这是官方推荐的方式,是Xcode6/iOS8的加入的功能,Xcode7之后默认添加的是LauchScreen.storyboard
  2. 使用静态LaunchImage图片集合,网易100分目前使用的方式,在这个图片合集中添加一张1125px × 2436px大小,@3x的图片即可,命名无所谓;
  3. 放在工程下的普通文件夹中,这种古老的方式就比较麻烦一点,对图片命名有要求,添加完之后需要在.plist文件中进行配置。


TopBar变化适配

由于iPhone X上状态栏高度的变化,导致页面顶部的一些布局异常,主要有两种场景:自定义导航栏或者没有导航栏的情况。

  1. 自定义导航栏

    这部分页面的自定义导航栏高度是写死的64pt,要全部改为JYFUHeightTopBar,特别是有些复杂的页面,页面布局要依赖导航栏高度的,改的时候也要非常谨慎。

  2. 无导航栏

    没有导航栏的页面,顶部内容通常会需要延伸至状态栏区域。如果内容是以UIScrollView承载,那我们需要修改

    scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    

    以前这部分扩展区域高度是20pt,在iPhone X上是44pt,因此紧贴着状态栏下面的这块视图高度需要重新计算。由于这部分不是宽高等比的,多余的部分会被截掉,所以需要视觉出图时注意图片里内容的布局。

    另外还有一种情况,像下面这个页面,轮播图是可以点击的,但是延伸至状态栏的部分是无法响应用户操作。调试发现UIScrollView有个私有属性,effectiveSafeAreaInset,其值为{44, 0, 0, 0},这个inset.top的值刚好是状态栏的高度,即当前页面的安全区域与屏幕顶部的距离。


有交互功能的控件避开安全区域

非安全区域,可以平铺内容用作展示,但是不能存在可交互的控件。

  1. 竖屏:

    在我们项目中,顶部按钮相对独立,只需要调整距离约束就可以,而且也不多。但底部控件落入非安全区域的情况就比较多了,一些页面底部带有类似工具栏的容器视图,还有大量的浮窗,自定义action sheet等。这些情况可能就不是拔高底部内容这么简单了(大多数情况,视觉会觉得不好看,底部内容会重新设计),这部分的适配工作量还是很可观的。

  2. 横屏:

    主要是一些需要全屏显示的页面,例如播放器之类,播放器上一般来说有不少控件,都需要往中间缩进,收到安全区域内。


其他要注意的问题

  • iPhone X上,非必要的话,最好不要隐藏状态栏。
  • UTableView在横屏时,UITableViewCellcontentView会自动insertsafe area
  • 内嵌WebView的页面的适配,内容加载出来之前,底部可能会出现黑色一条,这是由于scrollVIew的底部缩进引起的。另外,涉及到H5内容的适配,以及页面底部存在悬浮视图的情况,这个就需要Web端同事配合了。具体可参考这里

参考

  1. Update your apps for iPhone X
  2. Human Interface Guidelines
  3. iOS 11 safeArea详解 & iphoneX 适配
  4. Designing Websites for iPhone X


本文来自网易实践者社区,经作者吴丽君授权发布。