UIScrollView可滚动内容大小模糊

问题描述 投票:437回答:25

各位开发者,我在Interface Builder(Xcode 5 / iOS 7)中遇到AutoLayout问题。这是非常基本和重要的,所以我想每个人都应该知道这是如何正常运作的。如果这是Xcode中的一个错误,它是一个关键的错误!

所以,每当我有一个像这样的视图层次结构时,我遇到了麻烦:

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

UIScrollView具有可靠的约束条件,例如每边50 px(没问题)。然后我向UILabel添加一个Top Space约束(没问题)(我甚至可以固定标签的高度/宽度,不做任何改变,但由于Label的内在大小,应该是不必要的)

当我向UILabel添加尾随约束时,麻烦就开始了:

例如,尾随空间:Superview Equals:25

现在出现了两个警告 - 我不明白为什么:

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

B)错位视图(预期标签:x = -67实际值:x = 207

我在一个新的项目中做了这个最小的例子,你可以下载并附上截图。如您所见,Interface Builder期望Label位于UIScrollView边界之外(橙色虚线矩形)。使用Resolve Issues Tool更新Label的框架会将其移动到那里。

请注意:如果用UIView替换UIScrollView,行为就像预期的那样(Label的框架是正确的,并且根据约束条件)。所以似乎UIScrollView存在问题,或者我错过了重要的事情。

当我按照IB的建议运行应用程序而不更新Label的框架时,它定位得很好,正好在它应该是的位置,并且UIScrollView是可滚动的。如果我更新框架,标签不在视线范围内,UIScrollView不会滚动。

帮助我Obi-Wan Kenobi!为什么模棱两可的布局?为什么错位的观点?

你可以在这里下载示例项目,如果你能弄清楚发生了什么就试试:https://github.com/Wirsing84/AutoLayoutProblem

ios swift uiscrollview autolayout interface-builder
25个回答
944
投票

注意:在iOS> 10.0上,尚未经过测试;因此,在某些情况下解决方案可能不完整。

所以我只是这样整理出来:

  1. UIScrollView里面添加一个UIView(我们可以称之为contentView);
  2. 在这个contentView中,将顶部,底部,左侧和右侧边距设置为0(当然来自scrollView,即superView);设置水平和垂直对齐中心;

成品。

现在,您可以在contentView中添加所有视图,contentSizescrollView将根据contentView自动调整大小。

更新:

video在下面的评论中发布了这个@Sergio的特例。


2
投票

@Matteo Gobbi的答案是完美的,但在我的情况下,scrollview无法滚动,我删除“对齐中心Y”并添加“height> = 1”,scrollview将变为可滚动


2
投票

对我来说,添加一个contentView并没有像建议的那样真正起作用。此外,由于添加了视图,它会产生开销(尽管我不认为这是一个大问题)。对我来说最有效的只是关闭我的scrollView的歧义检查。一切都很顺利,所以我认为在像我这样的简单案例中也没关系。但请记住,如果你的scrollView的其他限制中断,Interface-Builder将不再警告你了。

enter image description here


2
投票

正在努力使用uiscrollview不滚动的人只需使用上一个视图的底部布局(位于内容视图内部)设置内容视图的底部约束。不要忘记删除中心Y约束。

休息所有约束与上面定义的相同。 Scrollview只关注从内容视图中获取最大高度,我们将其设置为最后视图的底部约束,这意味着scrollview会自动更改其内容偏移量。

在我的情况下,最后一个视图是UILable,没有行属性= 0(根据其内容自动调整其高度),因此它动态增加uilable的高度,最终我们的可滚动区域增加,因为uilable的底部布局与我们的内容视图的底部对齐,这会强制scrollview增加它的内容偏移量。


2
投票

我通过使用“解决自动布局问题”>“为所选视图添加缺少的约束”enter image description here解决了我的观点这种问题

以下两个约束解决了我的问题:

trailing = Stack View.trailing - 10
bottom = Stack View.bottom + 76

其中:trailing,bottom是UIScrollView的尾随底部


1
投票

我在youTube上制作了一个视频 Scroll StackViews using only Storyboard in Xcode

我认为这里可以出现两种情景。

scrollView中的视图 -

  1. 没有任何内在的内容大小(例如UIView
  2. 确实有自己的内在内容大小(例如UIStackView

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

  1. 顶部,左侧,底部和右侧有4个约束。
  2. 滚动视图的宽度相等(停止水平滚动)

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

enter image description here

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

enter image description here


1
投票

使用contentView(UView)作为UIScrollView内部的容器,坚持superview(top)的边缘(bottomtrailingleadingUIScrollView)和contentView应该有equalwidthequalheight到superview。这些是限制因素。并调用方法:

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

解决了我的问题。


0
投票

我所做的是创建一个单独的内容视图,如下所示。

内容视图是自由形式的,并且可以使用与contentView相关的自己的约束添加所有子视图。

UIScrollView将添加到主视图控制器中。

以编程方式,我将通过IBOutlet链接的contentView添加到类中,并设置UIScrollView的contentView。


0
投票

我得到了同样的错误..我做了以下

  1. 查看(上海华)
  2. ScrollView 0,0,600,600
  3. UIView里面的ScrollView:0,0,600,600
  4. UIView包含图像视图,标签

现在为scrollView(2)添加前导/尾随/顶部/底部,然后添加UIView(3)。

选择View(1)和View(3)设置相同的高度和重量..它解决了我的问题。

我做了有助于的视频:

https://www.youtube.com/watch?v=s-CPN3xZS1A


0
投票

[在XCode 7.2和iOS 9.2中测试]

为我设置故事板错误和警告的原因是将滚动视图和内容视图(在我的情况下是一个堆栈视图)的内在大小设置为占位符。此设置位于Storyboard中的“大小”检查器中。它说 - 设置设计时内在内容大小只影响在Interface Builder中编辑时的视图。视图在运行时不会具有此内在内容大小。

所以,我想通过设置它我们不会出错。

注意:在故事板中,我已将scrollview的所有边缘固定到superview,并将stackview的所有边缘固定到scrollview。在我的代码中,我为scrollview和stackview设置了translatesAutoresizingMaskIntoConstraints为false。我还没有提到内容大小。当堆栈视图动态增长时,故事板中设置的约束可确保堆栈可滚动。

故事板警告让我发疯,我不想让水平或垂直居中只是为了抑制警告。


0
投票

如果有人发现你注意到右侧滚动条滚动但内容不移动的行为,这个事实可能值得考虑:

您还可以在滚动视图的内容和滚动视图外部的对象之间使用约束,以便为滚动视图的内容提供固定位置,使该内容看起来浮动在滚动视图上。

这是来自Apple的documentation。例如,如果您不小心将顶部的Label / Button / Img / View固定到滚动区域外的视图(也许是滚动视图上方的标题或某些内容?)而不是contentView,则会冻结整个contentView。


93
投票

这个错误花了我一段时间来追踪,最初我尝试固定ScrollView的大小,但错误信息清楚地说“内容大小”。我确保从ScrollView顶部固定的所有内容也固定在底部。这样,ScrollView可以通过查找所有对象和约束的高度来计算其内容高度。这解决了模糊的内容高度,宽度非常相似......最初我在ScrollView中居住了大部分X,但我还必须将对象固定到ScrollView的侧面。我不喜欢这样,因为iPhone6可能有更宽的屏幕,但它会消除“模糊内容宽度”错误。


0
投票

如前面的答案中所述,您应该在滚动视图中添加自定义视图:

The custom view is the ContentView marked in the image

将所有子视图添加到内容视图中。在某些时候,您将看到滚动内容视图具有不明确的内容大小警告,您应该选择内容视图并单击“解决自动布局问题”按钮(在IB布局的右下角),然后选择“添加缺失”约束“选项。

enter image description here

从现在开始运行项目时,滚动视图将自动更新其内容大小,无需其他代码。


0
投票

您只需要确保有一种方法可以从滚动视图的顶部到底部形成连续的约束线。 [-X-X-X]

在我的情况下 - 水平滚动滚动视图 - 我还需要为滚动视图的每个子项添加宽度和高度约束,尽管Apple's technical note没有告诉你这一点。


0
投票

在Interface Builder的大小检查器中将ViewController(持有UIScrollView的那个)大小设置为Freeform,所有这些都应该有效。

Freeform setting in Size inspector in Interface Builder for the containing UIViewcontroller


0
投票

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
}

-2
投票

滚动视图中的所有子视图必须具有触及滚动视图所有边缘的约束,如文档中所述,滚动视图的高度和宽度由子视图中的度量自动计算,这意味着您需要具有高度的宽度和顶部和底部约束的尾随和前导约束。


-3
投票

我认为从现在开始这是10秒钟的工作。我在XCode 7.3中观察到它并在其上制作了一个视频。点击这里:

https://www.youtube.com/watch?v=yETZKqdaPiI

所有你需要做的,为UIScrollView添加一个子视图,宽度和高度相同。然后选择ViewController并按Reset to suggested constraint。请查看视频以便清楚了解。

谢谢


60
投票

这是我自己回答的问题UIScrollView + Centered View + Ambigous Scrollable Content Size + many iPhone sizes的答案。

但它也完全覆盖了你的情况!

So, here is the initial state for simplest case:

  1. scrollView对所有边都有0个约束
  2. 按钮居中水平和垂直,具有固定的宽度和高度约束
  3. 而且,当然 - 恼人的警告Has ambiguous scrollable content widthHas ambiguous scrollable content height

All, that we have to do is:

  • 添加2个附加约束,例如“0”表示我们视图的尾部和/或底部空间(请参阅下面屏幕截图中的示例)。

重要提示:您必须添加尾随和/或底部约束。不是“领先和顶级” - 它不起作用!

您可以在我的example project中查看,以证明如何解决此问题。

附:

根据逻辑 - 这个动作应该导致“冲突的约束”。但不是!

我不知道为什么它工作以及Xcode如何检测哪个约束更优先(因为我没有为这些约束明确设置优先级)。如果有人解释,为什么它在下面的评论中起作用,我将感激不尽。


47
投票

你需要创建一个UIView作为UIScrollView的子视图,如下所述:

  • UIViewController
  • UIView'主视图' UIScrollView UIView'容器视图' [您的内容]

第二步是制定UIScrollView约束。我使用topView的top,bottom,leading和trailing约束来做到这一点。

接下来,我添加了UIScrollView容器的约束,这是问题的开始。当您放置相同的约束(顶部,底部,前导和尾随)时,Storyboard会发出警告消息:

“具有模糊的可滚动内容宽度”和“具有模糊的可滚动内容高度”

继续上面的相同约束,只需将约束Equal HeightEqual Width添加到与主视图相关的容器视图中,而不是添加到UIScrollView。换句话说,Container View的约束与UIScrollView的superview相关联。

之后,您的故事板中不会出现警告,您可以继续为子视图添加约束。


24
投票

我终于弄明白了,我希望这更容易理解。

您可以通过向滚动视图添加基本UIView作为“内容视图”来绕过该警告,正如他们所提到的那样,并使其与滚动视图的大小相同,并在此内容视图中设置这6个参数。

enter image description here

如您所见,您需要总共6个参数!哪个..在正常情况下,你复制2个约束,但这是避免这个故事板错误的方法。


24
投票

iOS 12,Swift 4

使用autolayout最简单的方法:

  1. 添加UIScrollView并将其0,0,0,0固定到superview(或您想要的大小)
  2. 在ScrollView中添加UIView,将0,0,0,0固定到所有4个边并将其中心horizontallyvertically
  3. 在大小检查器中,将bottomalign center Y优先级更改为250.(对于水平滚动更改trailingalign center X
  4. 将所需的所有视图添加到此视图中。不要忘记在最低视图上设置底部约束。

15
投票

我知道我可能会迟到,但是下一个解决方案只需使用故事板就可以解决这类问题而无需额外的代码:

对于内容视图,您需要将前导/尾随/顶部/底部空间的约束设置为scrollview,这不会更改内容视图框架,如下所示:

当然,您需要为内容视图创建其他约束,以便滚动视图可以知道内容大小。例如,设置固定高度和中心x。

希望这可以帮助。


6
投票

看看这个非常快速和关于如何使滚动视图工作和使用自动布局完全滚动的点教程。现在,唯一让我感到困惑的是为什么滚动视图的内容大小总是比必要的大..

http://samwize.com/2014/03/14/how-to-use-uiscrollview-with-autolayout/


3
投票

请参阅以下内容:scrollview中的内容视图纵向和横向集中。你有歧义错误,总是确保从你的内容视图添加到scrollview中的两个是1).button space to container.2)尾随空间到约束,在屏幕截图中突出显示,

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

enter image description here

它可能会帮助你。

© www.soinside.com 2019 - 2024. All rights reserved.