iOS页面布局:UIScrollView的布局问题

一、简述

在iOS11以后的系统中UIViewControllerautomaticallyAdjustsScrollViewInsets这个属性过期弃用了不再建议使用了。系统推荐我们使用UIScrollViewcontentInsetAdjustmentBehavior属性替代它。如果项目之前使用了self. automaticallyAdjustsScrollViewInsets = YES,并且设置scrollView.contentInset的值,此时升级到iOS11以上的系统时页面就会出现布局问题。下面简单的写下关于contentInsetAdjustmentBehavior这个属性的理解。关于这个属性提供了四种设置值。

备注:当UIScrollViewframe超出安全区域时,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.adjustedContentInset做任何事情,即不作任何调整。

  • 如何计算adjustContentInset值:

adjustContentInset = contentInset

4. UIScrollViewContentInsetAdjustmentAlways
内容的内边距总是考虑安全区域,只要UIScrollViewframe超出安全区域就调整相应top&bottom的超出值,调整的最大值不会超过安全区相应方向的距离的最大值。

  • 如何计算adjustContentInset值:

adjustContentInset = safeAreaInset + contentInset

三、测试

  • 测试一: 默认设置 contentInsetAdjustmentBehaviorAutomatic,页面延伸布局为整个屏幕,从屏幕顶端开始计算;
    图1

由图1可见,在默认配置下UITableView的内容显示正常,其内容的内边距计算考虑到了安全距离。

view.safeAreaInsets = {88, 0, 83, 0}
tableView.contentInset = {0, 0, 0, 0}
tableView.adjustedContentInset = {88, 0, 83, 0}
  • 测试二: 默认设置 contentInsetAdjustmentBehaviorAutomatic,页面延伸布局为整个屏幕,从屏幕顶端开始计算,并且设置UITableViewcontentInset的值为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}
  • 测试三: 默认设置 contentInsetAdjustmentBehaviorAutomatic,页面延伸布局为整个屏幕,从屏幕顶端开始计算,并且设置UITableView的frame的y值为50;
图3
view.safeAreaInsets = {88, 0, 83, 0}
tableView.contentInset = {0, 0, 0, 0}
tableView.adjustedContentInset = {38, 0, 83, 0}
  • 测试四: 默认设置 contentInsetAdjustmentBehaviorAutomatic,页面延伸布局为整个屏幕,从屏幕顶端开始计算,并且设置UITableView的frame的y值为-50;
图4
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,可证明调整的最大值不会超过安全区相应方向的距离的最大值。

  • 测试五: 设置 contentInsetAdjustmentBehaviorNever,页面延伸布局为整个屏幕,从屏幕顶端开始计算;
图五
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。

你可能感兴趣的:(iOS页面布局:UIScrollView的布局问题)