UIScrollView不使用自动布局约束。

79

我有一个滚动视图和一个位于其后面的图像视图,我正在使用nibs填充它们。我正在使用自动布局。这两个视图都有底部和顶部与父视图的间距。图像视图正好实现了我想要的效果。对于iPhone 5,它在我想要的位置。对于其他iPhone,它始终位于屏幕底部上方,因此可以正确调整大小。滚动视图在iPhone 5上看起来很好,但在其他手机上它没有被调整大小,所以会滚动到应用程序视图之外。我在日志中收到以下消息:

 2012-11-21 10:42:38.576 LCHApp[12604:907] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. 
  Try this: (1) look at each constraint and try to figure out which you don't expect;
  (2) find the code that added the unwanted constraint or constraints and fix it.
 (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer
  to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 

"<NSLayoutConstraint:0x1d8ea080 UIScrollView:0x1d8413b0.bottom == UIImageView:0x1d892110.bottom>",
"<NSAutoresizingMaskLayoutConstraint:0x1d8cca10 h=-&- v=-&- ScheduleViewNib:0x1d853630.height == UIScrollView:0x1d8413b0.height - 386>",
"<NSLayoutConstraint:0x1d8e5340 V:[UIImageView:0x1d892110]-(64)-|   (Names: '|':ScheduleView:0x1d8efc30 )>",
"<NSAutoresizingMaskLayoutConstraint:0x1d8cf520 h=--& v=--& V:[ScheduleView:0x1d8efc30(480)]>",
"<NSLayoutConstraint:0x1d8eaed0 V:|-(45)-[UIScrollView:0x1d8413b0]   (Names: '|':ScheduleView:0x1d8efc30 )>"


 Will attempt to recover by breaking constraint 
 <NSLayoutConstraint:0x1d8ea080 UIScrollView:0x1d8413b0.bottom ==      UIImageView:0x1d892110.bottom>

我已经尝试过了

[self setTranslatesAutoresizingMaskIntoConstraints:YES];

并且

[self.myScrollView setTranslatesAutoresizingMaskIntoConstraints:YES];

据我所见,这只是将视图中的所有限制都移除了。而这并不是我想要的。

2
苹果公司的技术笔记TN2154:UIScrollView和Autolayout详细介绍了这个问题。 - smileyborg
4个回答

178
UIScrollView和自动布局的关系与自动布局的其他方面不同。基本上,如果允许简单的自动布局操作,那么什么都不会滚动。例如,如果滚动视图的子视图以正常方式通过约束与滚动视图顶部的10个点固定连接,它将完全固定在那里;无论如何滚动滚动视图,它都永远不会移动。
为了解决这个问题,使用autolayout的UIScrollView以全新的方式运作。因此,当你说“我正在使用autolayout”时,必须准备好事情会与以前非常不同。你必须要么使用一个带有translatesAutoresizingMaskIntoConstraints = YES和明确内容大小的单个滚动视图子视图,要么每个子视图都必须具有translatesAutoresizingMaskIntoConstraints = NO,并且内容大小将基于子视图的约束隐式推导出来。
这在https://developer.apple.com/library/content/releasenotes/General/RN-iOSSDK-6_0/index.html中有很好的说明。

5
您可能会对这个问题感兴趣:https://dev59.com/B2Yq5IYBdhLWcg3wpyRE(不仅因为有赏金!)我认为这是一个滚动视图/自适应布局的问题,但在我看来它读起来像是一个bug - 在这种情况下,滚动视图是一个表格视图,在旋转时内容尺寸没有正确调整。 - jrturton
3
@matt,我不知道你是否遇到过这种情况,但是如果你只使用布局约束来定义滚动视图的内容大小,就会出现一个错误:将内容偏移量从(0,0)滚动,转到另一个标签页或模态视图控制器,再返回时,滚动视图的子视图都会被内容偏移量移动,并且你无法回到原来的位置。如果您能确认并帮我复制我的雷达,我将非常感激:http://openradar.appspot.com/radar?id=2932404 - edelaney05
3
我可以确认这个 bug,但在提交给苹果之前,你应该制作一个演示项目,特别是因为在 http://openradar.appspot.com/radar?id=2932404 中复制和粘贴的代码甚至都无法编译(你把 constraintsWithVisualFormat:options:metrics:views: 的名称拼错了)。始终使用真正可行的实际代码。此外,在实际项目中,您可以包含实际图像。苹果的人没有想象力,也没有时间;您必须提前为他们做好所有工作。 - matt
3
“@edelaney05 肩膀 consectetur pancetta”??? :) 好的。我实际上根据他们的代码编写了一个更加相似的版本,其中图像视图的大小适合大图片。通过给滚动视图设置红色背景颜色,并记录日志,非常清楚地看到滚动视图认为一切都没问题(内容大小、内容偏移量),但是它在错误的位置绘制图像视图,即偏移了我们离开视图时的内容偏移量的数量。” - matt
2
@matt http://baconipsum.com!:-)太棒了。我看到的行为完全相同。滚动视图报告一切都是“正常”的,但绘图偏移量不正确。谢谢你确认我不是疯了(但只是关于这个错误!)。 - edelaney05
显示剩余15条评论

163

使用自动布局时非常重要的一点是,您必须将最后一个子视图的右侧和/或底部固定在滚动视图的右侧和/或底部。这就是滚动视图知道内容大小的方式。例如:

[scrollView addConstraint:[NSLayoutConstraint constraintWithItem:lastSubView
                                                 attribute:NSLayoutAttributeRight
                                                 relatedBy:NSLayoutRelationEqual
                                                    toItem:scrollView
                                                 attribute:NSLayoutAttributeRight
                                                multiplier:1.0
                                                  constant:0]];

感谢这个网站提供了完美的例子。

因此我浪费了很多时间,希望能够避免其他人的痛苦。


4
非常好,我一直在寻找像链接中那样简单的例子。谢谢! - pgpb.padilla
虽然Matt的回答很好,但这个回答对于解决我使用它时遇到的问题更加实用。 - dmur
22
“虽然马特的回答很好,但这个回答更加实用。” - 伙计,这也是我的回答。他从我的书里找到了代码/解释!很高兴我能帮忙两次。 :)))” - matt
根据您布置scrollView及其子视图的方式,您可能需要将内容固定在左侧或顶部。在我的情况下,我不得不将所有内容都固定在左侧。 - ArtSabintsev
您也可以通过界面构建器添加约束。非常好的答案! - Moisés Olmedo

0
为了让UIScrollviews与约束条件良好地配合使用,我使用了这种方法here。在那个答案中,我解决了如何使垂直滚动的滚动视图在设备旋转时也能正常工作的问题。您可以调整该方法以适用于水平滚动的滚动视图。对于双向滚动的滚动视图,请不要添加匹配宽度的大小约束技巧。但是其他所有操作都相同。

-3

几件事情:

  1. 确保自动布局已打开(IB中在“文件检查器”选项卡中)
  2. 确保您没有进行任何涉及边界、框架等的更改 - 这些都由自动约束完成
  3. 请远离AutoResizingMask。这将与您的新设置竞争。 如果做对了,现在可以布置您的按钮并且它将会非常好用。以下是如何操作。

此错误说明您的nib或其中一个控件未使用自动布局。


1
但UIScrollView是特殊的,你的答案没有考虑到这一点。 - matt

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