各位开发者,我在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
@Matteo Gobbi的答案是完美的,但在我的情况下,scrollview无法滚动,我删除“对齐中心Y”并添加“height> = 1”,scrollview将变为可滚动
正在努力使用uiscrollview不滚动的人只需使用上一个视图的底部布局(位于内容视图内部)设置内容视图的底部约束。不要忘记删除中心Y约束。
休息所有约束与上面定义的相同。 Scrollview只关注从内容视图中获取最大高度,我们将其设置为最后视图的底部约束,这意味着scrollview会自动更改其内容偏移量。
在我的情况下,最后一个视图是UILable,没有行属性= 0(根据其内容自动调整其高度),因此它动态增加uilable的高度,最终我们的可滚动区域增加,因为uilable的底部布局与我们的内容视图的底部对齐,这会强制scrollview增加它的内容偏移量。
我在youTube上制作了一个视频 Scroll StackViews using only Storyboard in Xcode
我认为这里可以出现两种情景。
scrollView中的视图 -
UIView
)UIStackView
)对于两种情况下的垂直可滚动视图,您需要添加以下约束:
对于具有其内在内容高度的视图,您不需要任何其他约束。
对于没有任何内在内容高度的视图,您需要添加高度约束。仅当高度约束大于scrollView的高度时,视图才会滚动。
使用contentView(UView
)作为UIScrollView
内部的容器,坚持superview(top
)的边缘(bottom
,trailing
,leading
,UIScrollView
)和contentView
应该有equalwidth
和equalheight
到superview。这些是限制因素。并调用方法:
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
self.scrollView.contentSize = self.contentView.frame.size;
}
解决了我的问题。
我所做的是创建一个单独的内容视图,如下所示。
内容视图是自由形式的,并且可以使用与contentView相关的自己的约束添加所有子视图。
UIScrollView将添加到主视图控制器中。
以编程方式,我将通过IBOutlet链接的contentView添加到类中,并设置UIScrollView的contentView。
我得到了同样的错误..我做了以下
现在为scrollView(2)添加前导/尾随/顶部/底部,然后添加UIView(3)。
选择View(1)和View(3)设置相同的高度和重量..它解决了我的问题。
我做了有助于的视频:
[在XCode 7.2和iOS 9.2中测试]
为我设置故事板错误和警告的原因是将滚动视图和内容视图(在我的情况下是一个堆栈视图)的内在大小设置为占位符。此设置位于Storyboard中的“大小”检查器中。它说 - 设置设计时内在内容大小只影响在Interface Builder中编辑时的视图。视图在运行时不会具有此内在内容大小。
所以,我想通过设置它我们不会出错。
注意:在故事板中,我已将scrollview的所有边缘固定到superview,并将stackview的所有边缘固定到scrollview。在我的代码中,我为scrollview和stackview设置了translatesAutoresizingMaskIntoConstraints为false。我还没有提到内容大小。当堆栈视图动态增长时,故事板中设置的约束可确保堆栈可滚动。
故事板警告让我发疯,我不想让水平或垂直居中只是为了抑制警告。
如果有人发现你注意到右侧滚动条滚动但内容不移动的行为,这个事实可能值得考虑:
您还可以在滚动视图的内容和滚动视图外部的对象之间使用约束,以便为滚动视图的内容提供固定位置,使该内容看起来浮动在滚动视图上。
这是来自Apple的documentation。例如,如果您不小心将顶部的Label / Button / Img / View固定到滚动区域外的视图(也许是滚动视图上方的标题或某些内容?)而不是contentView,则会冻结整个contentView。
这个错误花了我一段时间来追踪,最初我尝试固定ScrollView的大小,但错误信息清楚地说“内容大小”。我确保从ScrollView顶部固定的所有内容也固定在底部。这样,ScrollView可以通过查找所有对象和约束的高度来计算其内容高度。这解决了模糊的内容高度,宽度非常相似......最初我在ScrollView中居住了大部分X,但我还必须将对象固定到ScrollView的侧面。我不喜欢这样,因为iPhone6可能有更宽的屏幕,但它会消除“模糊内容宽度”错误。
您只需要确保有一种方法可以从滚动视图的顶部到底部形成连续的约束线。 [-X-X-X]
在我的情况下 - 水平滚动滚动视图 - 我还需要为滚动视图的每个子项添加宽度和高度约束,尽管Apple's technical note没有告诉你这一点。
在Interface Builder的大小检查器中将ViewController(持有UIScrollView的那个)大小设置为Freeform,所有这些都应该有效。
Freeform setting in Size inspector in Interface Builder for the containing UIViewcontroller
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
}
滚动视图中的所有子视图必须具有触及滚动视图所有边缘的约束,如文档中所述,滚动视图的高度和宽度由子视图中的度量自动计算,这意味着您需要具有高度的宽度和顶部和底部约束的尾随和前导约束。
我认为从现在开始这是10秒钟的工作。我在XCode 7.3中观察到它并在其上制作了一个视频。点击这里:
https://www.youtube.com/watch?v=yETZKqdaPiI
所有你需要做的,为UIScrollView
添加一个子视图,宽度和高度相同。然后选择ViewController并按Reset to suggested constraint
。请查看视频以便清楚了解。
谢谢
这是我自己回答的问题UIScrollView + Centered View + Ambigous Scrollable Content Size + many iPhone sizes的答案。
但它也完全覆盖了你的情况!
Has ambiguous scrollable content width
和Has ambiguous scrollable content height
。重要提示:您必须添加尾随和/或底部约束。不是“领先和顶级” - 它不起作用!
您可以在我的example project中查看,以证明如何解决此问题。
附:
根据逻辑 - 这个动作应该导致“冲突的约束”。但不是!
我不知道为什么它工作以及Xcode如何检测哪个约束更优先(因为我没有为这些约束明确设置优先级)。如果有人解释,为什么它在下面的评论中起作用,我将感激不尽。
你需要创建一个UIView
作为UIScrollView
的子视图,如下所述:
UIViewController
UIView
'主视图'
UIScrollView
UIView
'容器视图'
[您的内容]第二步是制定UIScrollView
约束。我使用topView的top,bottom,leading和trailing约束来做到这一点。
接下来,我添加了UIScrollView
容器的约束,这是问题的开始。当您放置相同的约束(顶部,底部,前导和尾随)时,Storyboard会发出警告消息:
“具有模糊的可滚动内容宽度”和“具有模糊的可滚动内容高度”
继续上面的相同约束,只需将约束Equal Height
和Equal Width
添加到与主视图相关的容器视图中,而不是添加到UIScrollView
。换句话说,Container View的约束与UIScrollView
的superview相关联。
之后,您的故事板中不会出现警告,您可以继续为子视图添加约束。
iOS 12,Swift 4
使用autolayout
最简单的方法:
UIScrollView
并将其0,0,0,0
固定到superview(或您想要的大小)UIView
,将0,0,0,0
固定到所有4个边并将其中心horizontally
和vertically
。bottom
和align center Y
优先级更改为250.(对于水平滚动更改trailing
和align center X
)我知道我可能会迟到,但是下一个解决方案只需使用故事板就可以解决这类问题而无需额外的代码:
对于内容视图,您需要将前导/尾随/顶部/底部空间的约束设置为scrollview,这不会更改内容视图框架,如下所示:
当然,您需要为内容视图创建其他约束,以便滚动视图可以知道内容大小。例如,设置固定高度和中心x。
希望这可以帮助。
看看这个非常快速和关于如何使滚动视图工作和使用自动布局完全滚动的点教程。现在,唯一让我感到困惑的是为什么滚动视图的内容大小总是比必要的大..
http://samwize.com/2014/03/14/how-to-use-uiscrollview-with-autolayout/