带有 UIScrollView 的纯自动布局

Posted

技术标签:

【中文标题】带有 UIScrollView 的纯自动布局【英文标题】:Pure autolayout with a UIScrollView 【发布时间】:2014-08-08 13:33:53 【问题描述】:

我正在尝试让UIScrollView 使用自动布局定位和调整大小。我正在遵循this documentation 中的“纯自动布局方法”指南,但我很难让它发挥作用。

我的层次结构如下所示:

UICollectionViewCell -> UIView -> UIScrollView -> UIView

所有内容都使用自动布局约束进行定位,包括 UIScrollView(相对于其直接父级 UIView 定位)。 UICollectionViewCell 最终确实有一个固定的大小,因为它是由 collectionView:layout:sizeForItemAtIndexPath 设置的,但我认为这与这个问题无关。

我遇到的问题是最后一个 UIViewUIScrollView 的孩子)的内容没有出现。如果我手动给它一个框架大小,它会显示,但我真的想使用自动布局。

那篇文档文章中有一句话我不太明白:

Position and size your scroll view with constraints external to the scroll view.

这是否表明我可以使用自动布局在其父级中定位和调整滚动视图的大小,或者滚动视图有一个固定的框架?

【问题讨论】:

看看我的回答here @Levi 所以看起来你 are 仍然在滚动视图内的视图上设置固定的宽度和高度约束(尽管你使用自动布局约束来做到这一点)。有没有办法在不计算内容的固定大小的情况下做到这一点? 内容的大小不必固定,你只需要指定从子视图到滚动视图的上下左右约束,这就是滚动视图计算其内容大小的方式使用自动布局。也请查看this answer,也许它更适合您的问题。 【参考方案1】:

使用 UIScrollView 的自动布局一开始可能看起来太复杂了。考虑以下两件事:

1) UIScrollView 的外部行为与任何其他 UIView 相同。这意味着,您可以使用自动布局约束为其设置任何位置/大小。与 UIView 没有区别。

2) UIScrollView 内部可以(但不应该)根据给定的自动布局约束来计算它的内容大小。对于这种行为,您应该为其提供一个奇怪的显式水平和垂直约束。

说:你在 UIView 父级中有 UIView 子级。您将左、上、下、右从子级固定到父级。有足够的限制来计算孩子的位置和大小 - 没关系。 现在,您的 UIScollView 父级中确实有 UIView 子级 - 以及相同的约束集。没有足够的约束来计算滚动视图的内容大小。为了计算滚动视图的内容大小,您应该为您的 UIScrollView 父级设置例如等宽和等高约束。

尽管您没有提供足够的信息来找出您的问题,但我认为您很可能没有设置约束来限制您的 UIScrollView 在其父级中的大小/位置。之后 - 您可能没有在滚动视图内的每个方向上设置一个更明确的约束来计算其内容大小。

我强烈建议阅读 ray wenderlich 的 ios 6 教程自动布局部分 - 您将了解自动布局如何以及为何如此工作。

【讨论】:

让我看看我是否理解你:我需要为 UIScrollView 中的 UIView 提供一个 explicit 大小。是对的吗?根据文档,在我看来,您不应该必须为滚动视图内的视图指定大小(或者至少,您不应该提供内容大小)。跨度> 显式尺寸不像 200px 是强制性的。您可以设置类似“等于滚动视图的宽度,等于滚动视图的高度”(用于滚动,例如,滚动视图内的 UIImageView 集),或给出一些百分比。但从技术上讲,你是对的 - 为了计算内容大小,你应该设置一些显式规则来计算大小。从理论上讲,这可以是一个相等规则(如我的示例)或其他一些允许自动布局系统计算大小的设置 如果我无法知道滚动视图中单个 UIView 内容的大小会怎样? (我正在使用 drawRect 进行自定义绘图,所以这不仅仅是给 UIView 中的子视图一些大小的问题。) 澄清一下:我可以轻松设置滚动视图的宽度/高度。但除非我还为滚动视图内的视图设置宽度/高度,否则这无济于事。但是由于直到布局后我才知道子视图的宽度/高度是多少,所以我无法将其设置为任何合理的值! 没关系。我只是花时间想出一种方法来计算正确的子内容大小。【参考方案2】:

假设您正在使用高度为 568 的笔尖,内部视图为 650 高。

首先使滚动视图与内部视图高度相同。然后将滚动视图的四个边固定到其容器视图,但是您会注意到底部约束是一个负数 - 将其设为 0。

你会注意到底部约束有问题:

别担心,这将在下一步中解决。

现在将内部视图的所有四个边都固定到滚动视图的边上,以及它的宽度和高度:

您现在会注意到之前的错误已经消失,并且当您运行项目时,您现在应该可以滚动查看看不见的内容了。

【讨论】:

我不明白您所说的“然后将视图的宽度和高度固定在滚动视图中”是什么意思。这与“将滚动视图内的视图的所有侧面固定到滚动视图的边缘”不完全相同吗? 我已经用截图更新了我的答案,希望能有所帮助。固定宽度和高度与固定边缘不同。固定内部视图的宽度和高度是为滚动视图提供其内容大小的原因。 啊,我现在明白我的困惑了。我完全以编程方式执行此操作-我对 IB 没有任何经验。如果我添加这样的约束:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[innerView]|" options:0 metrics:nil views:views]];,是固定宽度还是固定到水平边缘? 我对视觉格式没有太多经验,但是我相信你是正确的,因为 H 表示水平,所以你也需要与 V 类似的垂直。

以上是关于带有 UIScrollView 的纯自动布局的主要内容,如果未能解决你的问题,请参考以下文章

使用自动布局约束在 UIScrollView 内为 UIView 设置动画

带有自动布局的 UIScrollView 中的 UITableViews

带有自动布局的 uiscrollview 的动态内容未按预期工作

我的带有自动布局约束的 Swift 4 UIScrollView 没有滚动

UIScrollView 在带有自动布局的 UITabBarController 中有一个无法解释的位置

带有自动布局的 UIScrollView:后代在查看区域之外,但视图不滚动