各位开发者,我在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的内在大小,应该是不必要的)
The trouble starts when I add a trailing constraint to the 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不会滚动 .
Help me Obi-Wan Kenobi! Why the ambiguous layout? Why the misplaced view?
你可以在这里下载示例项目,如果你能弄清楚发生了什么就试试:https://github.com/Wirsing84/AutoLayoutProblem
24 回答
我认为从现在开始这是一个10秒的工作 . 我在XCode 7.3中观察到它并在其上制作了一个视频 . 点击这里:
https://www.youtube.com/watch?v=yETZKqdaPiI
所有你需要做的,添加一个子视图到
UIScrollView
具有相同的宽度和高度 . 然后选择ViewController并按Reset to suggested constraint
. 请查看视频以便清楚了解 .谢谢
滚动视图中的所有子视图必须具有触及滚动视图的所有边缘的约束,如文档中所述,滚动视图的高度和宽度由子视图中的度量自动计算,这意味着您需要具有宽度的顶部和前导约束以及高度的顶部和底部约束 .
我知道我可能会迟到,但是下一个解决方案 solves this kind of problems without additional code ,只是使用故事板:
对于内容视图,您需要将前导/尾随/上/下空格的约束设置为scrollview和 this will not change content view frame ,如下所示:
当然,您需要为内容视图创建其他约束,以便滚动视图可以知道内容大小 . 例如,设置固定高度和中心x .
希望这可以帮助 .
如前面的答案所述,您应该在滚动视图中添加自定义视图:
将所有子视图添加到内容视图中 . 在某些时候,您将看到滚动内容视图具有不明确的内容大小警告,您应该选择内容视图并单击“解决自动布局问题”按钮(位于IB布局的右下角),然后选择“添加缺失”约束“选项 .
从现在开始运行项目时,滚动视图将自动更新其内容大小,无需其他代码 .
我得到了同样的错误..我做了以下
查看(超级视图)
ScrollView 0,0,600,600
在ScrollView中的
UIView:0,0,600,600
UIView包含图像视图,标签
现在为scrollView(2)添加前导/尾随/顶部/底部,然后添加UIView(3) .
选择View(1)和View(3)设置相同的高度和重量..它解决了我的问题 .
我做了有助于的视频:
https://www.youtube.com/watch?v=s-CPN3xZS1A
NOTE: On iOS > 10.0, this hasn't been tested; therefore the solution could be incomplete in certain situations.
所以我只是以这种方式整理出来:
UIScrollView
add aUIView
(我们可以称之为contentView
);在
contentView
, set top, bottom, left and right margins to 0 (当然是scrollView
,即superView
); Set also align center horizontally and vertically ;Finished .
现在,您可以在
contentView
中添加所有视图,scrollView
的contentSize
将根据contentView
自动调整大小 .Update:
video在下面的评论中发布了一些特殊情况video .
我终于弄明白了,我希望这更容易理解 .
您可以通过向滚动视图添加基本UIView作为“内容视图”来绕过该警告,正如他们所提到的那样,并使其与滚动视图的大小相同,并在此内容视图中设置这6个参数 .
如您所见,您需要总共6个参数!哪个..在正常情况下,你复制2个约束,但这是避免这个故事板错误的方法 .
如果有人发现你注意到右侧滚动条滚动但内容不移动的行为,这个事实可能值得考虑:
那个's from Apple' s documentation . 例如,如果您不小心将顶部的Label / Button / Img / View固定到滚动区域外的视图(也许是滚动视图上方的 Headers 或某些内容?)而不是contentView,您可以将整个contentView冻结到位 .
看看这个非常快速,关于如何使滚动视图工作和使用自动布局完全滚动的点教程 . 现在,唯一仍然让我困惑的事情是为什么滚动视图内容大小总是大于必要..
http://samwize.com/2014/03/14/how-to-use-uiscrollview-with-autolayout/
我在youTube上制作了一个视频
Scroll StackViews using only Storyboard in Xcode
我认为这里可以出现2种情景 .
scrollView中的视图 -
没有任何内在内容大小(例如
UIView
)确实有自己的内在内容大小(例如
UIStackView
)对于两种情况下的垂直可滚动视图,您需要添加以下约束:
4顶部,左侧,底部和右侧的约束 .
滚动视图的相等宽度(停止水平滚动)
对于具有其内在内容高度的视图,您不需要任何其他约束 .
对于没有任何内在内容高度的视图,您需要添加高度约束 . 仅当高度约束大于scrollView的高度时,视图才会滚动 .
在Interface Builder的大小检查器中将ViewController(持有UIScrollView的那个)大小设置为Freeform,所有这些都应该可以工作 .
Freeform setting in Size inspector in Interface Builder for the containing UIViewcontroller
这是我自己回答的问题的回答UIScrollView + Centered View + Ambigous Scrollable Content Size + many iPhone sizes .
但它也完全覆盖了你的情况!
所以,这是最简单情况的初始状态:
scrollView对所有边都有0个约束
按钮 centered Horizontal and Vertical ,带有 fixed Width and Height 约束
当然 - annoying warnings
Has ambiguous scrollable content width
和Has ambiguous scrollable content height
.所有,我们要做的是:
Important: 你必须添加 trailing and/or bottom 约束 . 不是"leading and top" - 它不起作用!
您可以在我的example project中查看它,以证明如何解决此问题 .
P.S.
根据逻辑 - 这个动作应该导致“冲突的约束” . 但不是!
我不知道它为什么会起作用以及Xcode如何检测哪个约束更优先(因为我没有为这些约束明确设置优先级) . 如果有人解释,为什么它在下面的评论中起作用,我将感激不尽 .
请参阅以下内容:scrollview中的内容视图纵向和横向集中 . 你有歧义错误,总是确保从你的内容视图添加到scrollview中的两个是1).button space to container.2)尾随空间到约束,在截图中突出显示
滚动中的这些约束意味着您可以在内容视图高度或宽度之后滚动多少 .
它可能会帮助你 .
我所做的是创建一个单独的内容视图,如下所示 .
内容视图是自由形式的,并且可以使用与contentView相关的自己的约束添加所有子视图 .
UIScrollView将添加到主视图控制器中 .
以编程方式,我将通过IBOutlet链接的contentView添加到类中,并设置UIScrollView的contentView .
使用contentView(UView)作为UIScrollView中的容器,坚持superview(UIScrollView)的边缘(顶部,底部,尾部,前导),contentView应具有与superview相等的宽度和高度 . 这些是限制因素 . 并调用方法:
解决了我的问题 .
这个错误花了我一段时间来追踪,最初我尝试固定ScrollView的大小,但错误信息清楚地说“内容大小” . 我确保从ScrollView顶部固定的所有内容也固定在底部 . 这样,ScrollView可以通过查找所有对象和约束的高度来计算其内容高度 . 这解决了模糊的内容高度,宽度非常相似......最初我在ScrollView中居住了大部分X,但我还必须将对象固定到ScrollView的侧面 . 我不喜欢这样,因为iPhone6可能有更宽的屏幕,但它会消除“模糊内容宽度”错误 .
@Matteo Gobbi 's answer is perfect, but in my case, the scrollview can' t滚动,我删除“ align center Y " and add " height >=1 ”,scrollview将变为可滚动
对我来说,添加一个
contentView
并认为这是个大问题 . 对我来说最有效的只是 turn off the ambiguity-checking 为我scrollView
. 一切都很顺利,所以我认为在像我这样的简单案例中也没关系 . 但请记住,如果你的scrollView
的其他限制中断,Interface-Builder将不再警告你了 .[在XCode 7.2和iOS中测试过9.2]
为我设置故事板错误和警告的原因是将滚动视图的 intrinsic size 和内容视图(在我的情况下,是一个堆栈视图)设置为占位符 . 此设置位于Storyboard中的“大小”检查器中 . 它说 - 设置设计时内在内容大小只影响在Interface Builder中编辑时的视图 . 视图在运行时不会具有此内部内容大小 .
所以,我想通过设置它我们不会出错 .
注意:在故事板中,我已将scrollview的所有边缘固定到superview,并将stackview的所有边缘固定到scrollview . 在我的代码中,我为scrollview和stackview设置了translatesAutoresizingMaskIntoConstraints为false . 我还没有提到内容大小 . 当堆栈视图动态增长时,故事板中设置的约束可确保堆栈可滚动 .
故事板警告让我发疯,我不想让水平或垂直居中只是为了抑制警告 .
在我的情况下 - 水平滚动滚动视图 - 我还需要为滚动视图的每个子项添加宽度和高度约束,尽管Apple's technical note没有告诉你这一点 .
iOS 12, Swift 4
使用autolayout的最简单方法:
添加UIScrollView并将其固定为0,0,0,0到superview(或您想要的大小)
在ScrollView中添加UIView,将它0,0,0,0固定到所有4个边并使其水平和垂直居中 .
在尺寸检查器中,将'bottom'和'align center Y' priority更改为250.(对于水平滚动更改'trailing'和'align center X')
将所需的所有视图添加到此视图中 . Don't forget 在最低视图上设置底部约束 .
我遇到了同样的问题,在搜索完文档后没有找到可接受的解决方案 . 您需要创建一个UIView作为UIScrollView的子视图,如下所述:
UIViewController
UIView 'Main View'
UIScrollView
UIView 'Container View'
[您的内容]
第二步是制定UIScrollView约束 . 我使用topView的top,bottom,leading和trailing约束来做到这一点 .
接下来,我添加了UIScrollView容器的约束,这是问题的开始 . 当您放置相同的约束(顶部,底部,前导和尾随)时,Storyboard会发出警告消息:
“具有模糊的可滚动内容宽度”和“具有模糊的可滚动内容高度”
继续使用上面相同的约束,只需将约束“ Equal Height " and " Equal Width ”添加到与 Main View 相关的 Container View ,而不是添加到UIScrollView . 换句话说就是Container View 's constraints are tied to the UIScrollView'的超级视图 .
之后,您的故事板中不会出现警告,您可以继续为子视图添加约束 .
我希望这可以帮助别人 .
正在努力使用uiscrollview不滚动的人只需使用上一个视图的底部布局(位于内容视图内部)设置内容视图的底部约束 . 不要忘记删除中心Y约束 .
休息所有约束与上面定义的相同 . Scrollview只关注从内容视图中获取最大高度,我们将其设置为最后视图的底部约束,这意味着scrollview会自动更改其内容偏移量 .
在我的情况下,最后一个视图是UILable,没有行属性= 0(根据其内容自动调整其高度),因此它动态增加uilable的高度,最终我们的可滚动区域增加,因为uilable的底部布局与我们的内容视图的底部对齐,这会强制scrollview增加它的内容偏移量 .
我通过使用"Resolve auto layout issues"> "Add missing constraints"为选定视图解决了我的视图这种问题
以下两个约束解决了我的问题:
其中:trailing,bottom是UIScrollView的尾随底部