ios UIScrollView 可滚动内容大小歧义
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19036228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UIScrollView Scrollable Content Size Ambiguity
提问by Wirsing
Fellow devs, I am having trouble with AutoLayout in Interface Builder (Xcode 5 / iOS 7). It's very basic and important so I think everyone should know how this properly works. If this is a bug in Xcode, it is a critical one!
各位开发人员,我在 Interface Builder (Xcode 5 / iOS 7) 中遇到了 AutoLayout 的问题。这是非常基本和重要的,所以我认为每个人都应该知道它是如何正常工作的。如果这是 Xcode 中的一个错误,那就是一个关键的错误!
So, whenever I have a view hierarchy such as this I run into trouble:
因此,每当我有这样的视图层次结构时,我就会遇到麻烦:
>UIViewController
>> UIView
>>>UIScrollView
>>>>UILabel (or any other comparable UIKit Element)
The UIScrollView has solid constraints, e.g., 50 px from every side (no problem). Then I add a Top Space constraint to the UILabel (no problem) (and I can even pin height / width of the label, changes nothing, but should be unneccessary due to the Label's intrinsic size)
UIScrollView 有坚实的约束,例如,每边 50 像素(没问题)。然后我向 UILabel 添加一个顶部空间约束(没问题)(我什至可以固定标签的高度/宽度,什么都不改变,但由于标签的固有大小应该是不必要的)
The trouble starts when I add a trailing constraint to the UILabel:
当我向 UILabel 添加尾随约束时,麻烦就开始了:
E.g., Trailing Space to: Superview Equals: 25
例如,尾随空间为:Superview 等于:25
Now two warnings occur - and I don't understand why:
现在出现两个警告 - 我不明白为什么:
A)Scrollable Content Size Ambiguity (Scroll View has ambiguous scrollable content height/width)
A)Scrollable Content Size Ambiguity(滚动视图具有不明确的可滚动内容高度/宽度)
B)Misplaced Views (Label Expected: x= -67 Actual: x= 207
B)错位的视图(标签预期:x= -67 实际:x= 207
I did this minimal example in a freshly new project which you can download and I attached a screenshot. As you can see, Interface Builder expects the Label to sit outside of the UIScrollView's boundary (the orange dashed rectangle). Updating the Label's frame with the Resolve Issues Tool moves it right there.
我在一个你可以下载的全新项目中做了这个最小的例子,我附上了一个截图。如您所见,Interface Builder 希望 Label 位于 UIScrollView 的边界(橙色虚线矩形)之外。使用解决问题工具更新标签的框架会将其移动到那里。
Please note: If you replace the UIScrollView with a UIView, the behaviour is as expected (the Label's frame is correct and according to the constraint). So there seems to either be an issue with UIScrollView or I am missing out on something important.
请注意:如果您将 UIScrollView 替换为 UIView,则行为符合预期(标签的框架是正确的,并且符合约束)。所以 UIScrollView 似乎有问题,或者我错过了一些重要的东西。
When I run the App without updating the Label's frame as suggested by IB it is positioned just fine, exactly where it's supposed to be and the UIScrollView is scrollable. If I DO update the frame the Label is out of sight and the UIScrollView does not scroll.
当我运行应用程序而不按照 IB 的建议更新标签的框架时,它的位置很好,正好在它应该在的位置,并且 UIScrollView 是可滚动的。如果我确实更新了框架,则 Label 不在视线范围内,并且 UIScrollView 不会滚动。
Help me Obi-Wan Kenobi! Why the ambiguous layout? Why the misplaced view?
帮助我欧比旺克诺比!为什么是模棱两可的布局?为什么是错位的观点?
You can download the sample project here and try if you can figure out what's going on: https://github.com/Wirsing84/AutoLayoutProblem
您可以在此处下载示例项目,并尝试弄清楚发生了什么:https: //github.com/Wirsing84/AutoLayoutProblem
回答by Matteo Gobbi
So I just sorted out in this way:
所以我只是这样整理:
Inside the
UIScrollView
addaUIView
(we can call thatcontentView
);In this
contentView
, set top, bottom, left and right margins to 0(of course from thescrollView
which is thesuperView
); Set also align center horizontally and vertically;
在里面
UIScrollView
添加一个UIView
(我们可以称之为contentView
);在 this 中
contentView
,将上、下、左、右页边距设置为 0(当然从scrollView
哪个是superView
);设置还水平和垂直居中对齐;
Finished.
完了。
Now you can add all your views in that contentView
, and the contentSize
of the scrollView
will be automatically resized according with the contentView
.
现在您可以在其中添加所有视图contentView
,并且contentSize
的scrollView
将根据 自动调整大小contentView
。
Update:
更新:
Some special case is covered by this videoposted by @Sergioin the comments below.
回答by self.name
This error took me a while to track down, initially I tried pinning the ScrollView's size but the error message clearly says "content size". I made sure everything I pinned from the top of the ScrollView was also pinned to the bottom. That way the ScrollView can calculate its content height by finding the height of all the objects & constraints. This solved the ambiguous content height, the width is pretty similar... Initially I had most things X centered in the ScrollView, but I had to also pin the objects to the side of the ScrollView. I don't like this because the iPhone6 might have a wider screen but it will remove the 'ambiguous content width' error.
这个错误花了我一段时间来追踪,最初我尝试固定 ScrollView 的大小,但错误消息明确指出“内容大小”。我确保从 ScrollView 顶部固定的所有内容也固定到底部。这样 ScrollView 就可以通过查找所有对象和约束的高度来计算其内容高度。这解决了不明确的内容高度,宽度非常相似......最初我将大多数东西 X 集中在 ScrollView 中,但我还必须将对象固定到 ScrollView 的一侧。我不喜欢这样,因为 iPhone6 的屏幕可能更宽,但它会消除“内容宽度不明确”错误。
回答by ?or?e Nilovi?
Xcode 11+
Xcode 11+
The simplest way using autolayout
:
最简单的使用方法autolayout
:
- Add
UIScrollView
and pin it0,0,0,0
to superview (or your desired size) - Add
UIView
in ScrollView, pin it0,0,0,0
to all 4 sides and center ithorizontally
andvertically
. - In size inspector, change
bottom
andalign center Y
priority to 250. (for horizontal scroll changetrailing
andalign center X
) - Add all views that you need into this view. Don't forgetto set the bottom constraint on the lowest view.
- Select the
UIScrollView
, select the size inspector and deselectContent Layout Guides
.
- 添加
UIScrollView
并固定0,0,0,0
到超级视图(或您想要的尺寸) - 添加
UIView
滚动型,将其固定0,0,0,0
到所有4个方面,并居中horizontally
和vertically
。 - 在尺寸检查器中,变化
bottom
和align center Y
优先〜250(对于水平滚动变化trailing
和align center X
) - 将您需要的所有视图添加到此视图中。不要忘记在最低视图上设置底部约束。
- 选择
UIScrollView
,选择尺寸检查器并取消选择Content Layout Guides
。
回答by skywinder
It's answer for my self-answered question UIScrollView + Centered View + Ambigous Scrollable Content Size + many iPhone sizes.
这是我的自我回答问题UIScrollView + Centered View + Ambigous Scrollable Content Size + many iPhone sizes的答案。
But it fully cover your case too!
但它也完全涵盖了您的情况!
So, here is the initial state for simplest case:
所以,这是最简单情况的初始状态:
- scrollView with 0 constraints to all edges
- Button centered Horizontal and Verticalwith fixed Width and Heightconstraints
- And, of course - annoying warnings
Has ambiguous scrollable content width
andHas ambiguous scrollable content height
.
- 对所有边缘具有 0 约束的 scrollView
- 具有固定宽度和高度约束的按钮居中水平和垂直
- 而且,当然 -烦人的警告
Has ambiguous scrollable content width
和Has ambiguous scrollable content height
.
All, that we have to do is:
我们要做的就是:
- Add 2 additional constraints, for example "0" for trailingand/or bottomspace for our view (look at the example on screenshot below).
- 添加 2 个额外的约束,例如为我们的视图添加尾随和/或底部空间的“0” (查看下面屏幕截图中的示例)。
Important:you have to add trailing and/or bottomconstraints. Not "leading and top" - it's not works!
重要提示:您必须添加尾随和/或底部约束。不是“领先和顶级” - 这是行不通的!
You can check it in my example project, that demonstrating how to fix this issue.
P.S.
聚苯乙烯
According logic - this action should cause "conflicting constraints". But no!
根据逻辑 - 此操作应导致“冲突约束”。但不是!
I don't know why it works and how Xcode detects which constraint is more prioritised (because I'm not set priority for these constraints explicity). I'll be thankful if someone explain, why it works in comments below.
我不知道它为什么起作用以及 Xcode 如何检测哪个约束的优先级更高(因为我没有明确地为这些约束设置优先级)。如果有人解释为什么它在下面的评论中有效,我将不胜感激。
回答by WantToKnow
Xcode 11+, Swift 5
Xcode 11+,Swift 5
If you are wondering why all of the answers does not work anymore, make sure that you have pinned the content view (the one you've put inside the scroll view) to Content Layout Guide of the scroll view and NOT to Frame Layout Guide.
如果您想知道为什么所有答案都不再起作用,请确保您已将内容视图(您已放入滚动视图的那个)固定到滚动视图的内容布局指南而不是框架布局指南。
Content view edges (leading, trailing, top, bottom) should not be pinned like leading on the image - to Frame Layout Guide
内容视图边缘(前导、尾随、顶部、底部)不应像图像前导那样固定 - 到框架布局指南
but like this - to Content Layout Guide.
但就像这样 - 内容布局指南。
And then the most of the answers will work for you.
然后大部分答案都会对你有用。
The most simple approach now is going like this:
现在最简单的方法是这样的:
- Put scroll view in the root view
- Pin all the sides of scroll view to the superview
- Take another UIView (will call it content view) and put it inside the scroll view
- Pin all the sides of the content view to scroll view's Content Layout Guide
- Pin the content view's width to be equal to scroll view's Frame Layout Guide
- Fix the content view height in any way you want (I used just constant height constraint in the example below)
- 将滚动视图放在根视图中
- 将滚动视图的所有侧面固定到超级视图
- 取另一个 UIView(将其称为内容视图)并将其放在滚动视图中
- 固定内容视图的所有侧面以滚动视图的内容布局指南
- 将内容视图的宽度固定为等于滚动视图的框架布局指南
- 以您想要的任何方式修复内容视图高度(我在下面的示例中仅使用了恒定高度约束)
Overall your structure in the simplest implementation will look like this
总体而言,您在最简单的实现中的结构将如下所示
回答by Thiago Monteiro
You need to create an UIView
as a subview of the UIScrollView
as described below:
您需要创建一个UIView
作为如下所述的子视图UIScrollView
:
UIViewController
UIView
'Main View'UIScrollView
UIView
'Container View'- [Your content]
UIViewController
UIView
'主视图'UIScrollView
UIView
'容器视图'- [您的内容]
The second step is to make the UIScrollView
constraints. I did this with the top, bottom, leading and trailing constraints to its superView.
第二步是做UIScrollView
约束。我使用其 superView 的顶部、底部、前导和尾随约束来完成此操作。
Next I added the constraints for the container of UIScrollView
and here is where the problem begins. When you put the same constraints (top, bottom, leading and trailing) the Storyboard gives a warning message:
接下来我添加了容器的约束UIScrollView
,这就是问题开始的地方。当您放置相同的约束(顶部、底部、前导和尾随)时,Storyboard 会发出警告消息:
"Has ambiguous scrollable content width" and "Has ambiguous scrollable content height"
“具有不明确的可滚动内容宽度”和“具有不明确的可滚动内容高度”
Continue with the same constraints above, and just add the constraints Equal Height
and Equal Width
to your Container Viewin relation to the Main Viewand not toyour UIScrollView
. In other words the Container View's constraints are tied to the UIScrollView
's superview.
与上述相同的约束继续,只是添加的约束Equal Height
和Equal Width
你的容器视图相对于主视图,并没有你UIScrollView
。换句话说,容器视图的约束与UIScrollView
的超视图相关联。
After that you will not have warnings in your Storyboard and you can continue adding the constraints for your subviews.
之后,您的 Storyboard 中将不会有警告,您可以继续为您的子视图添加约束。
回答by William T.
I finally figured this out, I hope this is easier to understand.
我终于想通了,我希望这更容易理解。
You can often bypass that warning by adding a base UIView to the scrollview as a "content view", as they mentioned and make it the same size as your scroll view and, on this content view, set these 6 parameters.
您通常可以通过将基本 UIView 添加到滚动视图作为“内容视图”来绕过该警告,正如他们所提到的,并使其与滚动视图的大小相同,并在此内容视图上设置这 6 个参数。
As you can see, you need 6 total parameters! Which.. under normal circumstances, you're duplicating 2 constraints but this is the way to avoid this storyboard error.
如您所见,您总共需要 6 个参数!在正常情况下,您会复制 2 个约束,但这是避免此情节提要错误的方法。
回答by Yodagama
回答by Borzh
I know I may be late, but next solution solves this kind of problems without additional code, just using storyboards:
我知道我可能会迟到,但下一个解决方案无需额外代码即可解决此类问题,只需使用故事板:
For your content view you need to set constraints for leading/trailing/top/bottom spaces to scrollview and this will not change content view frame, like this:
对于您的内容视图,您需要为滚动视图设置前导/尾随/顶部/底部空间的约束,这不会更改内容视图框架,如下所示:
Of course you need to create additional constraints for content view so scroll view could know content size. For example set fixed height and center x.
当然,您需要为内容视图创建额外的约束,以便滚动视图可以知道内容大小。例如设置固定高度和中心 x。
Hope this helps.
希望这可以帮助。
回答by Mike Simz
Check out this really quick and to the point tutorial on how to get the scroll view working and fully scrollable with auto layout. Now, the only thing that is still leaving me puzzled is why the scroll view content size is always larger then necessary..
查看这个非常快速和重点的教程,了解如何使用自动布局使滚动视图工作和完全滚动。现在,唯一让我感到困惑的是为什么滚动视图的内容大小总是比必要的大。
http://samwize.com/2014/03/14/how-to-use-uiscrollview-with-autolayout/
http://samwize.com/2014/03/14/how-to-use-uiscrollview-with-autolayout/