适配iOS11和iPhone X的经验总结

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/He_jiabin/article/details/79209415

     感觉好久没有静下心来总结和记录技术问题了,博客文章也好久没有更新了。。。虽然平时工作上也都会不断遇到新的问题和难点,但基于繁忙的业务开发和自己最近的一些私事缠身,遇到问题基本都是快速解决就草草了事了,没有深入的总结和记录,回想真是于“颓废”了。今天着手总结一下前一阵子适配iOS11和iPhone X遇到的一些问题和经验总结。

 一、iOS11引发的问题

1、在iOS11下tableview内容下移20pt或者60pt,iOS11之前页面没有问题。(下图tableview的frame设置为super view的frame,隐藏了系统导航栏。问题:tableview的内容下移了20pt ?)


如上图所示,从iOS11开始,系统增加了一个safe area概念。我们先来介绍safe area这个东西是用来做什么的。safe area即安全区域,安全区域帮助我们将view的内容放置在整个屏幕的可视的部分。它定义了view中可视内容的区域,保证不被系统的状态栏、导航栏等其他控件覆盖。即使把navigationbar设置为透明的,系统也认为安全区域是从navigationbar的bottom开始的。所以上图的安全区域是从状态栏的bottom开始的。

区别:IOS11之后控制tableview的内容和边缘距离的属性是adjustedContentInset,而在iOS11之前tableview是根据contentInset来确定内容与边缘的距离的。

我们先回顾iOS11之前的contentInset。contentInset是用来描述tableview内容的上下左右与边缘的距离的,它可以确定tableview显示内容的区域。iOS系统从iOS7开始使用视图边缘延伸特性,即全屏布局。这种特性下,就算你的视图里面有navigationbar和tabbar,view的frame仍然会是 (0, 0, SCREEN_WIDTH, SCREEN_HEIGHT),这样的结果就是navigationbar和tabbar会把view的顶部和底部区域覆盖住。所以controller在iOS7的时候新增了一个属性 automaticallyAdjustsScrollViewInsets,默认是YES。这个属性就是控制滚动视图内容和边缘距离的,即默认修改contentInset的值保证滚动视图的内容不会被导航栏、状态栏挡住。如果有navigationbar,那么contentInset就是(64, 0, 0 , 0),如果还有tabbar,那么contentInset就是(64, 0, 0 , 49)。

但是在iOS11之后,属性automaticallyAdjustsScrollViewInsets开始被废弃了,contentInset默认是(0, 0, 0 , 0)。增加了safe area概念。而体现safe area的是safeAreaInset属性,定义了view中可视内容的区域,保证不被系统的状态栏、导航栏等其他控件覆盖。如上图safeAreaInset是(20, 0, 0 , 0)。iOS11之后决定tableview内容和边缘距离的属性是adjustedContentInset。adjustedContentInset的值计算方式由contentInsetAdjustmentBehavior决定,默认情况下adjustedContentInset = contentInset + safeAreaInset 。

1. UIScrollViewContentInsetAdjustmentAutomatic: 如果scrollview在一个automaticallyAdjustsScrollViewInsets = YES的controller上,并且这个Controller包含在一个navigation controller中,这种情况下会设置在top & bottom上 adjustedContentInset = safeAreaInset + contentInset不管是否滚动。其他情况下与UIScrollViewContentInsetAdjustmentScrollableAxes相同

2. UIScrollViewContentInsetAdjustmentScrollableAxes: 在可滚动方向上adjustedContentInset = safeAreaInset + contentInset,在不可滚动方向上adjustedContentInset = contentInset;依赖于scrollEnabled和alwaysBounceHorizontal / vertical = YES,scrollEnabled默认为yes,所以大多数情况下,计算方式还是adjustedContentInset = safeAreaInset + contentInset

3. UIScrollViewContentInsetAdjustmentNever: adjustedContentInset = contentInset

4. UIScrollViewContentInsetAdjustmentAlways: adjustedContentInset = safeAreaInset + contentInset

        当contentInsetAdjustmentBehavior设置为UIScrollViewContentInsetAdjustmentNever的时候,adjustContentInset值不受SafeAreaInset值的影响。

        那么什么情况下会出现上述问题?

        当tableView的frame超出安全区域范围时,系统会自动调整内容的位置保证内容在安全区域内,这时SafeAreaInsets值不为0,于是影响tableView的adjustContentInset值,进而影响tableView的内容展示,导致tableView的content下移了SafeAreaInsets的距离。正常情况下SafeAreaInsets的值为0

        如何解决上述问题?

        如果tableview内容下移20pt或者60pt,说明tableView的frame超出了安全区域范围,这个时候safeAreaInset的值不为0。

        第一个方法:我们可以通过设置contentInset的值来巧妙抵消safeAreaInset的值,使adjustedContentInset的值为0。即 0 = safeAreaInset + contentInset。

        第二个方法:设置contentInsetAdjustmentBehavior=UIScrollViewContentInsetAdjustmentNever,这个时候 adjustedContentInset = contentInset,这样tableView的内容调整就和安全区域无关了,只由contentInset控制。

2、在iOS11下默认开启Self-Sizing

我们都知道tableview的加载机制是这样的:当调用reloadData时,tableview会先计算出contentSize的大小,因为要先确定contentView的大小和位置才能决定内容的滚动区域。所以会先调用方法heightForRowAtIndexPath: 。假设tableview有50行,那么这个方法会调用50次,计算出contentSize的大小,然后才会调用cellForRowAtIndexPath:去创建cell。

在iOS8引入Self-Sizing 之后,我们可以通过实现estimatedRowHeight相关的属性来展示动态的内容,不用一次性把所有的行高都计算出来。实现了estimatedRowHeight属性后,得到的初始contenSize是个估算值,是通过estimatedRowHeight 乘以 cell的个数得到的,并不是最终的contenSize,tableView就不会一次性计算所有的cell的高度了,只会计算当前屏幕能够显示的cell个数再加上几个。然后在滑动的时候,tableView不停地创建新的cell,不断的更新自己的contenSize,在滑到最后的时候,就会得到正确的contenSize。这样的好处就是更高效了,滑动更顺滑了。

如果以前没有使用estimateRowHeight属性,那么在iOS11下就要注意一个问题:因为开启Self-Sizing之后,tableView是使用estimateRowHeight属性的,这样就会造成contentSize和contentOffset值的变化,如果是有动画是观察这两个属性的变化进行的,就会造成动画的异常,因为在估算行高机制下,contentSize的值是一点点地变化更新的,所有cell显示完后才是最终的contentSize值。而且tableview不会缓存正确的行高,所以reloadData的时候,会重新计算contentSize。

iOS11下不想使用Self-Sizing的话,可以通过以下方式关闭:

    self.tableView.estimatedRowHeight = 0;
    self.tableView.estimatedSectionHeaderHeight = 0;
    self.tableView.estimatedSectionFooterHeight = 0;
    

二、适配iPhone X

1、APP界面上的变化





2设计和技术实现上的变化

        界面设计上,大方向的标注和控件布局依旧按照原先iPhone 8及以前的机型进行设计:


3开发处理iPhone X相关代码处理

        


展开阅读全文

iPhone X 适配

10-26

公司app适配起来比较琐碎,很多第三方库编译的时候没有支持模拟器的版本,所以我只好把这些库删掉,然后调试界面后再加进去,是不是听起来就很[img=https://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/003/monkey/2.gif][/img]。(我这个女程序媛水平不高没办法)。rnrn适配iPhone X给我带来的最大教训就是:千万不要写死代码,之前用了很多20,49,44,诸如此类的高度,导致我不得一一改掉,而且吧,如果是多人合作的app,一开始就要说好一些常用的变量放在哪,不要每次你加一个,我加一个,不但重复后期还会有很多麻烦产生。rnrn好了,下面说下我适配的过程:rn[color=#0000FF]rn[b]首先适配之前我们要知道5.8英寸的iPhone X到底有什么变化。rn[/b]rn[/color]1.屏幕像素尺寸:1125 * 2436. rn2.开发尺寸:375 * 812 (你懂得),高度比iphone 6,7,8多了145pt。rnrn[img=https://img-bbs.csdn.net/upload/201710/26/1508985139_829982.png][/img]rnrn那么苹果规定的适配准则是:rn1.必须保证布局充满整个屏幕。你设计的产品核心内容不能被“齐刘海”,圆角和底部home指示器遮挡。核心内容要在safearea,如下图的位置。rn(大部分使用标准,系统UI的,比如导航栏,tableView和collections 的,都会自动调整适配iPhone X,但是如果你是自定义控件,那么它的高度什么的都要相应修改才行。)rn[img=https://img-bbs.csdn.net/upload/201710/26/1509001722_327298.png][/img]rnrn2.提供全屏体验。要让你的背景填充整个屏幕,包括指示器的位置。对于像tables和collections,要一直到屏幕最底部。但是要保证指示器的位置不能有有交互性的控件,以免影响用户体验。rnrn3.最基本的内容不能被圆角,“齐刘海”或者home键指示器剪切掉,就是不能被他们遮挡住内容。rnrn4。注意status bar的高度变化。iPhone X中status bar高度比其他所有设备都高。如果之前你代码中是写死20的高度,界面完全用这个高度来布局,那么还是改成动态的status bar的高度吧。现在iPhone X上它的高度可是44pt。rnrn5.加入你之前隐藏了status bar,那么建议在iPhone X上显示出来。现在iPhone X有更高的屏幕,status bar显示的内容对用户是有用的,他最好只在必要的时候隐藏掉。比如看视频或者照片预览。rnrn6.一些图片资源要重新设计。有的图在iPhone X上合适,其他设备可能就会被裁切掉很多,所以要保证设备显示的资源核心内容都在。不会被裁切掉。rnrn7.避免有交互的控件出现在屏幕底部也就是home指示器的位置或者出现在“齐刘海”两边的圆角处。因为底部指示器使用了滑动手势来显示主屏幕,这些手势可能会去掉这些控件的交互。圆角的位置呢对用户使用也不友好。rnrn8.不要尝试用一些黑色的控件填充隐藏掉圆角及指示器的位置。也不要在这些位置加一些奇怪的东西来装饰他们。rnrn9.允许在特定的时候隐藏掉home功能的指示器。但是用户触屏屏幕后,指示器要再次出现。比如播放视频和图片浏览时。rnrn10.tabbar默认高度其他设备是49pt,iPhone X的默认高度是83pt。rnrn[color=#0000FF][b]下面说下我们自己app里面的适配:[/b][/color]rnrn1.status bar高度被写死成20,这次要改成动态获取的。rn[code=objc][[UIApplication sharedApplication] statusBarFrame].size.heightrn[/code]rnrn2.tabbar另一个同事写的自定义的,高度也固定为49,这里也要改,iPhone X上tabbar高度默认是83,其实就是49 + 34,home指示器的高度是34pt。具体就不写了。大家看明白就行。rnrn3.也是其他一些节目的微调,其实改的东西不多,但是很麻烦,特别是有的界面各个控件的高度是根据status bar ,tabbar这些的高度变化的就麻烦了,比较琐碎。rn[color=#FF0000]rn总之,只要遵守上面的一些原则,适配也不是很难。上面的原则是根据苹果适配文档理解翻译的,大家参考。图片也是引用的苹果文档里面的。如果有说的不对的,也麻烦指出。[img=https://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/003/monkey/43.gif][/img][/color]rnrnrnrn 论坛

没有更多推荐了,返回首页