UIScrollView可滚动内容大小的歧义

624

各位开发者们, 我在Interface Builder中(Xcode 5 / iOS 7)遇到了AutoLayout的问题。 这是非常基础且重要的,因此我认为每个人都应该知道如何正确地使用它。如果这是Xcode中的一个bug,那么这是一个关键性的问题!

因此,每当我有像这样的视图层次结构时,我就会遇到麻烦:

>UIViewController
>> UIView
>>>UIScrollView
>>>>UILabel (or any other comparable UIKit Element)

UIScrollView的约束很稳定,例如:距每一侧50px(没有问题)。 然后我给UILabel添加了一个Top Space约束(没有问题)(我甚至可以固定标签的高度/宽度,这并没有改变什么,但由于标签的内在大小应该是不必要的)

当我给UILabel添加一个trailing constraint时问题就开始了:

例如,Trailing Space to: Superview Equals: 25

现在会发生两个警告 - 我不明白为什么:

A)可滚动内容大小不明确(滚动视图具有不明确的可滚动内容高度/宽度)

B)未放置正确的视图(Label Expected: x=-67 Actual:x=207)

我在全新的项目中进行了这个最小化的例子,你可以下载,并且我附上了一个屏幕截图。正如你所看到的,界面生成器希望Label坐落在UIScrollView的边界之外(橙色虚线矩形)。使用Resolve Issues Tool更新标签的框架将其移动到那里。

请注意:如果您用UIView替换UIScrollView,则行为与预期相符( Label的帧是正确的,符合约束),因此UIScrollView似乎存在问题或者我漏掉了一些重要内容。

如果我不像IB建议的那样更新标签框架,就可以很好地定位它,正好在其应该处的位置,并且UIScrollView是可滚动的。 如果我更新标签,则标签被隐藏,UIScrollView无法滚动。

帮帮我,欧比万·克诺比!为什么出现模糊的布局? 为什么视图被放错了?

你可以在这里下载示例项目并尝试找出问题: https://github.com/Wirsing84/AutoLayoutProblem

Interface Builder中问题的说明


9
尝试将UILabel放置在内容视图中,然后将标签的尾边设置为内容视图(普通UIView)。这个视频可能会对你有很大帮助:http://www.youtube.com/watch?v=PgeNPRBrB18&feature=youtu.be - erdekhayser
1
视频很棒,但是对于我来说没有修复警告。 :( - Mr Rogers
非常感谢这个视频 - 我从中学到了很多东西(相当令人惊讶)!然而,当我将视频的知识与https://dev59.com/nmMk5IYBdhLWcg3wyw_H?rq=1结合起来时,我可以修复警告。剩下的问题是:如何使scrollView的contentView大小仅为必要大小? - Wirsing
除了顶部和尾部间距之外,还要添加前导空间和底部空间。 - Ting Yi Shih
我刚刚在Size Inspector中将Ambiguity->Never Verify设置为了“不检查歧义”,这样就可以正常工作而不需要将UIView添加为子视图(实际上,这对我造成了一些问题)。我通常会在代码中完成其余工作。目前还没有发现任何问题。 - Paweł Pela
显示剩余5条评论
34个回答

7

Swift 4+方法:

1)将UIScrollView的顶部、底部、左侧和右侧边距设置为0。

2)在UIScrollView中添加一个UIView,并将其顶部、底部、前导和尾随边距设置为0(等于UIScrollView边距)。

3)最重要的部分是设置宽度和高度,其中高度约束应具有较低的优先级。

private func setupConstraints() {

    // Constraints for scrollView
    scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

    // Constraints for containerView
    containerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
    containerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    containerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
    containerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
    containerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true

    let heightConstraint = containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
    heightConstraint.priority = UILayoutPriority(rawValue: 250)
    heightConstraint.isActive = true
}

6

3
我通过使用“解决自动布局问题”> “添加缺失的约束条件”来解决了我看到的这种问题。为所选视图添加以下两个约束条件即可解决此问题:enter image description here
trailing = Stack View.trailing - 10
bottom = Stack View.bottom + 76

其中: trailing和bottom是UIScrollView的右边缘和底部


这对我有用,通过添加“到底部”的约束条件。现在我想起来了,这是很有道理的。 - SilverWolf

3
请见下文:在滚动视图中垂直和水平居中的内容视图。您可能会遇到歧义错误,请确保从您的内容视图中添加到滚动视图中的两个部分是1)按钮空间到容器。2)在屏幕截图中突出显示的约束的尾随空间。

这些约束意味着在滚动后您的内容视图高度或宽度之后,您可以滚动多少。

enter image description here

希望对您有所帮助。


3

在我的情况下,我遇到了iPad上的内容大小错误和内容大小不明确的问题,但在iPhone上可以正常工作。我已经在storyboard中做出以下更改来解决这个问题。

  1. 在UIView中添加UIScrollView,并添加约束leading、top、trailing和bottom为0,0,0,0。
  2. 根据需求设置UIScrollView的高度,比如100。
  3. 将UIView添加到UIScrollView中,并添加约束leading、top、trailing和bottom为0,0,0,0,以及居中对齐(X)和(Y)的约束。
  4. 在UIScrollView的size inspector中取消选择“Content Layout Guides”。

3

UIScrollView内使用UView作为容器,将其粘附到父视图(UIScrollView)的边缘(top, bottom, trailing, leading),并且contentView应该具有与父视图相等的equalwidthequalheight。这些是约束条件。然后调用方法:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    self.scrollView.contentSize = self.contentView.frame.size;
}

对我来说解决了问题。


2

如果您正在遇到uiscrollview无法滚动的问题,只需将内容视图的底部约束与最后一个视图的底部布局(位于内容视图内部)设置即可。不要忘记删除居中Y约束。

其余所有约束都与上面定义的相同。ScrollView只关心从其内容视图获取最大高度,而我们将其设置为最后一个视图的底部约束,这意味着ScrollView会自动更改其内容偏移量。

在我的情况下,最后一个视图是具有no of lines属性= 0的UILable(它根据其内容自动调整其高度),因此它动态增加uilable的高度,最终由于uilable的底部布局与我们的内容视图的底部对齐,使我们的可滚动区域增加,这迫使ScrollView增加其内容偏移量。


2
如果有人发现滚动条向右滚动但内容不动的现象,可能需要考虑以下事项:
引用文本:“您还可以在滚动视图的内容和滚动视图外部的对象之间使用约束来为滚动视图的内容提供固定位置,使该内容似乎漂浮在滚动视图上。”
这是来自苹果公司的文档。例如,如果您意外地将顶部标签/按钮/图片/视图钉到滚动区域外的视图(可能是页眉或仅位于scrollView上方的某些内容),而不是contentView,则会将整个contentView冻结在原地。

2

@Matteo Gobbi的回答很完美,但在我的情况下,scrollview无法滚动,我删除了“垂直居中”并添加了“高度>=1”,scrollview就可以滚动了。


2

我在YouTube上制作了一个视频
使用Xcode中的Storyboard仅滚动StackViews

我认为这里可能出现两种情况。

scrollView内部的视图 -

  1. 没有任何固有内容大小(例如UIView
  2. 具有自己的固有内容大小(例如UIStackView

对于垂直可滚动视图,您需要添加以下约束:

  1. 从顶部、左侧、底部和右侧4个约束。

  2. 与ScrollView相等的宽度(以停止水平滚动)

对于具有自己固有内容高度的视图,您不需要任何其他约束。

输入图像描述


对于没有任何固有内容高度的视图,您需要添加高度约束。只有当高度约束大于scrollView的高度时,视图才会滚动。

输入图像描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接