你感到困惑是对的。这有点违反直觉,但是顶部和底部布局指南与配置 UIScrollView 无关以便其可滚动内容将位于半透明导航栏下方,这就是您想要实现的效果。
该怎么办
鉴于第二张图片中显示的视图层次结构,这就是您在 iOS8 上需要执行的操作:
配置视图控制器,以便选中“在顶部栏下延伸边缘”(在代码中,使用edgesForExtendedLayout
)。这将确保视图控制器布局其根视图,使其位于导航栏下方。
配置滚动视图约束,以便滚动视图的顶部边缘与其超级视图的顶部边缘的偏移量为零,not距顶部布局指南的空间为零。这将确保集合视图填充根视图,从而也覆盖导航栏,这是滚动视图的内容能够在导航栏下方滚动所必需的。 (IB 可能会在这个问题上与你争论。请参阅下面的脚注。)
那么现在如何确保滚动视图知道导航栏在哪里,以便(例如)它不知道always将其内容放置在导航栏下方?答案与布局指南无关。在视图控制器中,选中“调整滚动视图插入”框(或在代码中,automaticallyAdjustsScrollViewInsets
)。这将导致视图控制器自动调整滚动视图的contentInset
属性,以便滚动视图适当地定位其内容。
这会起作用。
这是怎么回事
那么为什么这是这个答案呢?为什么如此令人困惑?
坦率地说,很容易混淆,因为顶部和底部布局指南作为传达有关半透明覆盖元素的布局信息的元素突出地呈现给我们。然而,它们并不是唯一的“半透明感知”布局机制。它们仅与“普通”子视图的定位直接相关,即与视图控制器的根视图无关,并且与 UIScrollView 中的内容无关。
滚动视图(或 UICollectionView 和 UITableView 之类的子类)中的内容始终以更复杂的方式定位,涉及滚动视图本身,受诸如以下属性的影响contentInset
, contentOffset
等等(真的,如果滚动视图布局是一件简单的事情,为什么苹果在过去四年里专门举办 WWDC 会议来讨论滚动视图布局?!)
总而言之,如上述步骤所示,three用于管理布局的不同半透明感知机制如下:
延伸边缘确定视图控制器是否定位其根视图,使其位于导航栏下方。
布局指南提供一个指标来告诉“主要”内容区域在哪里,并考虑到半透明条。您可以将它们与自动布局一起使用来定位普通视图,这样它们就不会重叠。或者您可以访问代码中的数值。
滚动视图插图是确保滚动视图的内容可以重叠但并不总是重叠的正确方法。这automaticallyAdjustsScrollViewInsets
在简单的情况下,视图控制器上的属性可以自动为您执行此操作。 (大概,这个属性只会导致视图控制器更新滚动视图的contentInset
基于它通过布局指南公开的相同值。因此,如果您需要自己管理插图,那么您就可以这样做。)
对抗IB的布局指南狂热
关于“与IB战斗”的脚注:
不幸的是,当您尝试将滚动视图边缘限制到其父视图的边缘时,Interface Builder 可能会与您对抗。如果您从滚动视图按住 Ctrl 键拖动到超级视图,则当它弹出要在这些视图之间添加的可能约束的菜单时,它可能会尝试让您根据视图控制器的布局指南来约束滚动视图。这是因为当超级视图是根视图时,IB 盲目地更喜欢布局指南而不是超级视图边缘。但是当你使用滚动视图时,这是错误的事情.
为什么?例如,假设您接受针对布局指南的约束。然后,您的滚动视图将受到顶部约束,将其限制为 topLayoutGuide-64.0。 -64.0 是一个硬编码值,用于补偿导航栏的确切高度。那么,当天气好的时候导航栏不等于 64pt 时会发生什么情况呢?或者当您完全关闭导航栏时?或者想在没有导航栏的情况下重复使用这个场景?答案:那么你会得到一个损坏的布局。
那么,如何强制 IB 添加从滚动视图到其父视图边缘的约束,而不是布局指南呢?据我所知,答案是您无法通过在视图之间按住 Ctrl 键拖动来在 IB 中正确添加该约束。
相反,您需要选择视图,然后使用画布底部的“固定”控件。这个看起来像一个大写的 H,中间有一个盒子。在“固定”弹出对话框的顶部部分(带有显示超级视图空间限制的小图表的部分),您可以使用文本字段旁边的下拉控件来配置空间限制是否绑定布局指南或超级视图。如下所示:
演示项目的 Github 链接:https://github.com/algal/ScrollViewUnderlapDemo https://github.com/algal/ScrollViewUnderlapDemo