一、简述
在iOS11以后的系统中UIViewController
的automaticallyAdjustsScrollViewInsets
这个属性过期弃用了不再建议使用了。系统推荐我们使用UIScrollView
的contentInsetAdjustmentBehavior
属性替代它。如果项目之前使用了self. automaticallyAdjustsScrollViewInsets = YES
,并且设置scrollView.contentInset
的值,此时升级到iOS11以上的系统时页面就会出现布局问题。下面简单的写下关于contentInsetAdjustmentBehavior
这个属性的理解。关于这个属性提供了四种设置值。
备注:当
UIScrollView
的frame
超出安全区域时,contentInsetAdjustmentBehavior
决定了adjustContentInset
的计算方式是否会受到safeAreaInset
安全区域值的影响,进而影响了adjustContentInset
的最终值。最终影响到UIScrollView
的content的内边距。
typedef NS_ENUM(NSInteger, UIScrollViewContentInsetAdjustmentBehavior) {
UIScrollViewContentInsetAdjustmentAutomatic,
UIScrollViewContentInsetAdjustmentScrollableAxes,
UIScrollViewContentInsetAdjustmentNever,
UIScrollViewContentInsetAdjustmentAlways,
}
二、UIScrollViewContentInsetAdjustmentBehavior 和 adjustContentInset
1. UIScrollViewContentInsetAdjustmentAutomatic
默认值,scrollView会根据页面的安全区域的值自动调整计算,系统在计算content的edgeInset
时会考虑到安全区域自动计算和适应顶部和底部的内边距。即使UIScrollView
不可滚动,也会自动设置content的内边距。其他情况下行为与UIScrollViewContentInsetAdjustmentScrollableAxes
相同。
- 如何计算adjustContentInset值:
adjustContentInset = safeAreaInset + contentInset
2. UIScrollViewContentInsetAdjustmentScrollableAxes
也是自动调整计算,但是会考虑滚动方向,系统会根据UIScrollView
的滚动方向进行判断内容的内边距是否要考虑安全区域,依赖于scrollEnabled和alwaysBounceHorizontal / vertical = YES。
eg. 如果是一个横向滚动的UIScrollView
,及便布局起点和高度值超过了页面的安全区,那么系统也不会调整。
- 如何计算adjustContentInset值:
可滚动方向:
adjustContentInset = safeAreaInset + contentInset
不可滚动方向:
adjustContentInset = contentInset
3. UIScrollViewContentInsetAdjustmentNever
内容的内边距从不考虑安全区域,当contentInsetAdjustmentBehavior
设置为Never
的时候,adjustContentInset
值不受SafeAreaInset
值的影响。
eg. 就算UIScrollView
超出了safeAreaInsets
,系统不会对你的scrollView.adjustedContentInse
t做任何事情,即不作任何调整。
- 如何计算adjustContentInset值:
adjustContentInset = contentInset
4. UIScrollViewContentInsetAdjustmentAlways
内容的内边距总是考虑安全区域,只要UIScrollView
的frame
超出安全区域就调整相应top&bottom的超出值,调整的最大值不会超过安全区相应方向的距离的最大值。
- 如何计算adjustContentInset值:
adjustContentInset = safeAreaInset + contentInset
三、测试
- 测试一: 默认设置
contentInsetAdjustmentBehavior
为Automatic
,页面延伸布局为整个屏幕,从屏幕顶端开始计算;
图1
由图1可见,在默认配置下UITableView
的内容显示正常,其内容的内边距计算考虑到了安全距离。
view.safeAreaInsets = {88, 0, 83, 0}
tableView.contentInset = {0, 0, 0, 0}
tableView.adjustedContentInset = {88, 0, 83, 0}
- 测试二: 默认设置
contentInsetAdjustmentBehavior
为Automatic
,页面延伸布局为整个屏幕,从屏幕顶端开始计算,并且设置UITableView
的contentInset
的值为UIEdgeInsetsMake(40, 0, 0, 0)
;
图2
由图2可见,在此配置下UITableView
的内容显示不正常,UITableView
的内容的内边距向下偏移了40
view.safeAreaInsets = {88, 0, 83, 0}
tableView.contentInset = {40, 0, 0, 0}
tableView.adjustedContentInset = {128, 0, 83, 0}
- 测试三: 默认设置
contentInsetAdjustmentBehavior
为Automatic
,页面延伸布局为整个屏幕,从屏幕顶端开始计算,并且设置UITableView
的frame的y值为50;
view.safeAreaInsets = {88, 0, 83, 0}
tableView.contentInset = {0, 0, 0, 0}
tableView.adjustedContentInset = {38, 0, 83, 0}
- 测试四: 默认设置
contentInsetAdjustmentBehavior
为Automatic
,页面延伸布局为整个屏幕,从屏幕顶端开始计算,并且设置UITableView
的frame的y值为-50;
view.safeAreaInsets = {88, 0, 83, 0}
tableView.contentInset = {0, 0, 0, 0}
tableView.adjustedContentInset = {88, 0, 83, 0}
由图3可见,在UITableView
的顶部偏移父view的顶端50像素,下移,在此配置下UITableView
的内容显示正常,并且调整值小于安全区域垂直方向的最大值;
由图4可见,在UITableView
的顶部偏移父view的顶端-50像素,上移,在此配置下UITableView
的内容显示不正常,并且调整值为安全区域垂直方向的最大值;
结合图3和图4,可证明调整的最大值不会超过安全区相应方向的距离的最大值。
- 测试五: 设置
contentInsetAdjustmentBehavior
为Never
,页面延伸布局为整个屏幕,从屏幕顶端开始计算;
view.safeAreaInsets = {88, 0, 83, 0}
tableView.contentInset = {0, 0, 0, 0}
tableView.adjustedContentInset = {0, 0, 0, 0}
由图5可见,在设置为Never
时,UITableView
的内容内边距不会再考虑安全区域,因此系统计算adjustedContentInset
的调整至为0,页面布局显示异常,此时adjustedContentInset = contentInset。