iOS 11适配:contentInsetAdjustmentBehavior解析

之前写过一篇文章描述了下影响页面布局的几个属性,如今iOS 11出来后变化挺大的,在这里重新梳理下。

01.png

可以看到在iOS 11中,UIViewController的automaticallyAdjustsScrollViewInsets属性被弃用了,系统推荐我们使用UIScrollViewcontentInsetAdjustmentBehavior属性替代之。关于这个属性,系统提供了四种行为模式:

UIScrollViewContentInsetAdjustmentAutomatic
UIScrollViewContentInsetAdjustmentScrollableAxes
UIScrollViewContentInsetAdjustmentNever
UIScrollViewContentInsetAdjustmentAlways

第3、4种看起来比较清晰,要么不调整,要么"一直"调整。但估计不少朋友看到第1、2种会一脸懵逼,包括第4种里“一直”这个词。在这解释之前我们先分析下为什么automaticallyAdjustsScrollViewInsets会被弃用。

在我看来原因可能之前使用automaticallyAdjustsScrollViewInsets的方案太单调粗暴了。回顾以前所说的,当处于 ①(文末)情况时的scrollView,系统会自动修改其contentInset属性,举个例子:如果存在状态栏导航栏,则contentInsettop值则会被修改为64,内容自动下移64。当底部存在系统UITabBar时,则bottom值修改为49,即下方额外增加49的滚动距离。

我们知道iOS 11后引入了安全区的概念safeAreaInsets

02.jpg

以不带UITabBariPhone X为例:NavigationController的rootViewController.view(以下用self代称该rootViewController),其safeAreaInsets{88, 0, 34, 0},在contentInsetAdjustmentBehavior属性出现之前,系统是根据①情况进行的调整。而现在,系统将会根据ScrollView视图大小(包括其类族UITableView等)是否超过了安全区来进行调整,需要注意的有两点:

  1. 这个"调整"不再是直接修改scrollView.contentSize,而是scrollView.adjustedContentInset
  2. 调整的值将根据具体超出多少值来确定,但最大值不能超过安全区的相应EdgeInsets方向的值。以self.view的safeAreaInsets{88, 0, 34, 0}为例。此时添加一个tableView,其高度为self.view.short_height + 25,那么tableView.adjustedContentInsetbottom则为25。但如果超出高度为134,bottom最高也只会是34,这样就会由于表格高度超过屏幕100,而出现"拉不到底部"的情况。

第二点的效果相比以前的automaticallyAdjustsScrollViewInsets方案,可以说智能很多,因为当处于①情况时,哪怕你的scrollView的布局位置根本就没被导航栏挡住,它都会给你调整64。然后你就发现莫名起妙内容就被下移了。

内容被下移64.PNG
tableView.frame = CGRectMake(0, 80, self.view.short_width, self.view.short_height - 80)
tableView.backgroundColor = [UIColor orangeColor];

接下来我们再说回contentInsetAdjustmentBehavior属性的这四个值:

  1. 首先是UIScrollViewContentInsetAdjustmentNever,如名所示:就算你的ScrollView超出了safeAreaInsets,系统不会对你的scrollView.adjustedContentInset做任何事情,即不作任何调整;
  2. UIScrollViewContentInsetAdjustmentAlways: 只要超了安全区,就调整相应的超出值,调整的最大值不会超过安全区相应EdgeInsets方向的最大值,如刚刚上述第2点;
  3. UIScrollViewContentInsetAdjustmentScrollableAxes:系统会根据ScrollView的滚动方向来进行判断,假设我只是一个横向滚动的ScrollView,那即便我的布局起点和高度值超过了self.view的安全区,那么系统也不会调整scrollView.adjustedContentInset对应的topbottom方向值,只可垂直方向滚动同理,直接设置scrollView.scrollEnabled = NO也同理;
  4. UIScrollViewContentInsetAdjustmentAutomatic:系统默认值。文档上是这样说的:

Similar to .scrollableAxes, but for backward compatibility will also adjust the top & bottom contentInset when the scroll view is owned by a view controller with automaticallyAdjustsScrollViewInsets = YES inside a navigation controller, regardless of whether the scroll view is scrollable

其实文档已经说的很清楚了,它与UIScrollViewContentInsetAdjustmentScrollableAxes行为相似,但是为了兼容以前①这种情况,即使scrollView是不可滚动,也会根据safeAreaInsets超出范围进行调整。(具体效果可以试着自己上手调试,这里就不贴代码和示意图了)。

关于刚才说的注意点二,我想补充的是,当出现表格过高(比如超出了100)而导致"拉不到底部"的情况时,你可以选择额外设置tableView.contentInset属性,bottom方向设为100,或者选择修改self.additionalSafeAreaInsets的属性。前者影响tableView.adjustedContentInset值,后者影响self.view.safeAreaInsets。你会发现刚好是两数之和,事实上adjustedContentInset的值正是由contentSize加上contentInsetAdjustmentBehavior所调整的值。而self.view.safeAreaInsets会在原来的基础上,加上你的additionalSafeAreaInsets。由于我们很少直接修改contentSize,所以基本上tableView.adjustedContentInset都是系统的调整值。


以上都是个人拙见,如果有误的话欢迎朋友在评论中指出。还有点想说的是,苹果可能本意是方便开发者,但事实上如果你对这些属性的来龙去脉不太了解清楚的话,确实是挺不方便的。。。因此可能现在很多的人做法都是一开始就设置之前的automaticallyAdjustsScrollViewInsets为NO,设置新的contentInsetAdjustmentBehaviorUIScrollViewContentInsetAdjustmentNever。就我个人看来,如果你需要实现类似系统默认那种表格穿透半透明导航栏或者底部半透明TabBar的效果时,这个属性使用起来就很舒服,直接tableView.frame = self.view.bouds 或者make.edges.equal.to(self.view)就好了。而无需再设置额外的contentSize。如果不需要类似的穿透,那可以选择直接将其禁止。


① scroll view is owned by a view controller with automaticallyAdjustsScrollViewInsets = YES inside a navigation controller
PS:并且该scollView是第一个被添加的子视图

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容