【问题标题】:Working with Top Layout Guide in UIScrollView through Auto Layout通过自动布局在 UIScrollView 中使用顶部布局指南
【发布时间】:2014-06-23 21:48:09
【问题描述】:

我想通过自动布局在UIScrollView 中使用Top Layout Guide。如果没有UIScrollView 自动布局与Top Layout Guide 一起使用,效果很好。

但是当我将UIButton 嵌入UIScrollView 时,它没有。

我知道这是因为UIScrollViewTop Layout Guide 的层次结构不同。但我认为可能有一个很好的解决方案来解决这个问题。

【问题讨论】:

    标签: ios uiscrollview interface-builder autolayout


    【解决方案1】:

    在添加间距约束时,Xcode 不会显示与您的视图有负距离的项目。您似乎在UIScrollViewUIView 之间添加了垂直空间约束。删除该约束,将滚动视图移动到下面 Top Layout Guide 并在UIScrollViewTop Layout Guide 之间添加一个新的垂直空间约束。

    【讨论】:

    • 但是我不能使用这个效果:image link
    • 如果这是问题所在,您只需将内容插入添加到滚动视图中。
    【解决方案2】:

    你感到困惑是对的。这有点违反直觉,但是顶部和底部布局指南与配置 UIScrollView 无关,因此它的可滚动内容将覆盖半透明导航栏,这是您想要实现的效果。

    做什么

    鉴于您在第二张图片中显示的视图层次结构,这就是您需要在 iOS8 上执行的操作:

    1. 配置视图控制器,以便选中“在顶栏下延伸边缘”(在代码中,使用 edgesForExtendedLayout)。这将确保视图控制器布局其根视图,使其位于导航栏下方。

    2. 配置滚动视图约束,使滚动视图的顶部边缘与其父视图顶部边缘的偏移为零,而不是顶部布局指南的零空间。这将确保集合视图填充根视图并因此也覆盖导航栏,这是滚动视图的内容能够在导航栏下滚动所必需的。 (IB 可能会在这方面与您抗衡。请参阅下面的脚注。)

    3. 那么现在如何确保滚动视图知道导航栏的位置,以便(例如)它不会总是将其内容定位在导航下方酒吧?答案与布局指南无关。在视图控制器中,选中“调整滚动视图插图”框(或在代码中,automaticallyAdjustsScrollViewInsets)。这将导致视图控制器自动调整滚动视图的contentInset 属性,以便滚动视图正确定位其内容。

    这会起作用。

    发生了什么

    那么为什么是这个答案呢?为什么会如此混乱?

    坦率地说,很容易混淆,因为顶部和底部的布局指南作为元素突出显示给我们,这些元素传达了有关半透明叠加元素的布局信息。然而,它们并不是唯一的“半透明感知”布局机制。它们仅与“普通”子视图的定位直接相关,即不是视图控制器的根视图,也不是 UIScrollView 中的内容。

    滚动视图(或 UICollectionView 和 UITableView 等子类)中的内容将始终以涉及滚动视图本身的更复杂的方式定位,受contentInsetcontentOffset 等属性的影响。(真的,如果滚动视图布局是一件简单的事情,为什么 Apple 会在过去四年中专门举办 WWDC 会议来滚动视图布局?!)

    总而言之,如上述步骤所示,用于管理布局的三种不同的半透明感知机制如下:

    1. Extends Edges 确定视图控制器是否定位其根视图,使其位于导航栏下方。

    2. Layout Guides 提供了一个衡量“主要”内容区域在哪里的指标,并考虑了半透明条。您可以将它们与 Auto Layout 一起使用来定位普通视图,使其不会重叠。或者您可以访问代码中的数值。

    3. Scroll View Insets 是确保滚动视图的内容可以重叠但并不总是重叠的正确方法。视图控制器上的 automaticallyAdjustsScrollViewInsets 属性可以在简单的情况下自动为您完成此操作。 (据推测,此属性只会导致视图控制器根据它通过布局指南公开的相同值更新滚动视图的contentInset。因此,如果您需要自己管理插入,这就是您应该这样做的方式。)

    对抗 IB 的布局指南狂热

    关于“与 IB 战斗”的脚注:

    不幸的是,当您尝试将滚动视图边缘约束到其父视图的边缘时,Interface Builder 可能会与您发生冲突。如果您从滚动视图到超级视图执行 ctrl-drag,当它弹出要在这些视图之间添加的可能约束的菜单时,它可能会尝试让您将滚动视图约束到视图控制器的布局指南。这是因为当超级视图是根视图时,IB 盲目地更喜欢布局指南而不是超级视图边缘。但是当您使用滚动视图时,这是错误的事情

    为什么?例如,假设您接受针对布局指南的约束。然后,您将在滚动视图上得到一个顶部约束,将其约束到 topLayoutGuide-64.0。 -64.0 是一个硬编码值,用于补偿导航栏的确切高度。那么当导航栏不等于 64pt 时会发生什么?或者当您完全关闭导航栏时?或者想在没有导航栏的情况下重新使用这个场景?答案:那么你会得到一个损坏的布局。

    那么如何强制 IB 将约束从滚动视图添加到其父视图的边缘,而不是布局指南?据我所知,答案是您无法通过在视图之间执行 ctrl-drag 在 IB 中正确添加该约束。

    相反,您需要选择视图,然后使用画布底部的“Pin”控件。这是一个看起来像大写 H 中间有一个盒子的那个。在 Pin 弹出对话框的顶部,带有显示超级视图空间约束的小图表的部分,您可以使用文本字段旁边的下拉控件来配置空间约束是否绑定布局指南或超级视图。如下所示:

    演示项目的 Github 链接:https://github.com/algal/ScrollViewUnderlapDemo

    【讨论】:

    • 要对抗 IB 的布局指南狂热,您可以简单地将视图移动到顶部布局指南上方(实际上在 0 和 topLayoutGuide.length 之间)并使用 i.fantattitude.me/1j 添加约束,每次都对我有用!
    • 谢谢,这是一个很棒的提示!
    • 另一个“对抗 IB”的技巧,当你从 Scroll View 拖动到 Superview 并松开时,按住 Alt 键,“垂直间距到顶部布局指南”将变为“顶部空间到容器边距”。
    • 应该注意的是,从 iOS 9 开始自动调整滚动视图插入不再起作用,除非滚动视图是视图控制器的根视图。因此,为了使这项工作可靠,您需要将视图层次结构中的根“View”的类设置为“UIScrollView”。感谢this answer
    【解决方案3】:

    虽然藻类的答案似乎在 iOS 9.0 之前有效,但它在 iOS 9.0 之后不必要地复杂和损坏。在 iOS 9.0 之后也可以使用并且不需要与自动布局交互的更简单的方法是简单地执行以下操作:

    1. 确保在 Interface Builder 中为 ViewController 检查 Adjust Scroll View Insets(或以编程方式将 automaticallyAdjustsScrollViewInsets 设置为 true)。
    2. 在 Interface Builder 中将 ViewController 的根 View 的类设置为 UIScrollView(或在代码中手动将其 (self.view) 替换为 UIScrollView)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-15
      • 2014-06-24
      • 2015-09-08
      • 1970-01-01
      • 2013-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多