ios 视图在水平和垂直方向上不明确,布局复杂
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19253937/
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
Views are Horizontally and Vertically Ambiguous with complex layout
提问by GeneralMike
I have a UIViewController
on my storyboard that has 2 subviews side-to-side horizontally. I added constraints to fix the leading and trailing edges to a constant (20 pts), and another constraint to keep the widths equal. If I assume the following, it should be possible to calculate what the width of each subview will need to be:
UIViewController
我的故事板上有一个横向排列的 2 个子视图。我添加了约束以将前缘和后缘固定为常量(20 pts),并添加另一个约束以保持宽度相等。如果我假设以下内容,应该可以计算每个子视图的宽度需要是多少:
- the subviews do not overlap
- there are no other views present (horizontally, at least)
- the width of the screen (the superview) is known
- 子视图不重叠
- 没有其他视图存在(至少在水平上)
- 屏幕的宽度(超级视图)是已知的
However, XCode gives me a warning that my views are horizontally ambiguous. I'm guessing that means that XCode is not making one of these assumptions, but which one is it? And is there a way for me to instruct XCode to make that assumption?
但是,XCode 警告我我的观点在水平方向上不明确。我猜这意味着 XCode 没有做出这些假设之一,但它是哪一个?有没有办法让我指示 XCode 做出这个假设?
EDIT: Okay, played with it a bit and got the warning to go away, but it looks like it's not making the first assumption - it's just setting each subview's width to superview.width - 40
, and happily burying one view underneath the other. So the question is how to I stop them from overlapping?
编辑:好的,玩了一会儿,警告消失了,但看起来它没有做出第一个假设 - 它只是将每个子视图的宽度设置为superview.width - 40
,并愉快地将一个视图埋在另一个下面。所以问题是如何阻止它们重叠?
EDIT 2: Okay, my actual screen is a lot more complicated than my simple example. Here's what I got:
编辑 2:好的,我的实际屏幕比我的简单示例复杂得多。这是我得到的:
So in this setup I have 4 views that are vertically and horizontally staggered.? I want the blue, red, and purple views to all be the same subview.frame.size.width = superview.width - 60
. The blue and purple are lined up in the left column, and the red is alone in the right column, and all the gaps (between the two columns and between each column and it's nearest edge) are at a constant (20 pts). These 3 tables have a variable height, which I will be setting programmatically as described in James's answer here. At the bottom is a pink view that stretches the width of the screen (minus gaps), and sits at a constant 20 pts below either the purple or the red view, whichever is lower (which I'm attempting to do by giving it a spacing constraint of >= 20 to each view, and I hope that it will pick exactly 20 for one of them). Since all of the heights are dynamic and may not necessarily fit on the screen at the same time, I made their superview a UIScrollView
instead of the normal UIView
.
所以在这个设置中,我有 4 个垂直和水平交错的视图。?我希望蓝色、红色和紫色视图都相同subview.frame.size.width = superview.width - 60
。蓝色和紫色排在左列,红色单独在右列,所有间隙(两列之间以及每列之间及其最近的边缘之间)都为常数(20 pts)。这 3 个表的高度可变,我将按照James 的回答中所述以编程方式进行设置. 底部是一个粉红色的视图,它拉伸了屏幕的宽度(减去间隙),并且位于紫色或红色视图下方 20 pts 处,以较低者为准(我试图通过给它一个每个视图的间距约束 >= 20,我希望它会为其中一个选择恰好 20 个)。由于所有高度都是动态的,可能不一定同时适合屏幕,因此我将它们的超级视图设为 aUIScrollView
而不是正常的UIView
.
When all is said and done, I'm still getting a warning that all 4 of my views are horizontally ambiguous, and that the pink bar is vertically ambiguous. I think it's having trouble realizing what is supposed to go next to what, which is why it thinks it's horizontally ambiguous. And I think it's not picking to place the pink bar exactly 20 pts below either the purple or red views, which is why it thinks it's vertically ambiguous. Can anyone confirm or deny any of these suspicions? Or suggest a way around it? When I run it in the end, I just get this (I made the background of the scroll view yellow, which you can't tell in the storyboard screenshot):
当一切都完成后,我仍然收到一条警告,即我的所有 4 个视图在水平方向上都是不明确的,而粉红色条在垂直方向上是不明确的。我认为它很难意识到什么应该放在什么旁边,这就是为什么它认为它是横向模糊的。而且我认为将粉色条放置在紫色或红色视图下方 20 pts 处并不是选择,这就是它认为它在垂直方向上不明确的原因。任何人都可以证实或否认任何这些怀疑吗?或者提出解决方法?当我最后运行它时,我得到了这个(我将滚动视图的背景设置为黄色,这在情节提要屏幕截图中是看不出来的):
回答by GeneralMike
Vertically Ambiguous
纵向模糊
Okay, I think I've solved the vertical ambiguous part. I added two vertical constraints between the pink and purple views and two vertical constraints between the pink and red views. For each pair, the first constraint is that the spacing between them must be > 20 pts, and it has 1000 priority. The second constraint is that the spacing is = 20 pts, but it only has an 800 priority.
好的,我想我已经解决了垂直模糊部分。我在粉红色和紫色视图之间添加了两个垂直约束,在粉红色和红色视图之间添加了两个垂直约束。对于每一对,第一个约束是它们之间的间距必须> 20 pts,并且优先级为1000。第二个约束是间距= 20 pts,但它只有800的优先级。
For example, if the bottom of the purple view ends up being lower than the bottom of the red view (as it is in my first screenshot), Xcode should try to set the vertical distance between the pink and red views = 20, but it will realize that that conflicts with condition that the space between the purple and pink being >= 20. Since the >= constraint has higher priority, the = constraint will be ignored. Now, when Xcode looks at the constraint that the spacing between the purple and pink views being = 20, it checks that against the constraint that the pink and red must be separated by at least 20. Since the bottom of the red view is higher than the bottom of the purple view, the >= 20 constraint between the red and the pink still passes.
例如,如果紫色视图的底部最终低于红色视图的底部(就像在我的第一个屏幕截图中一样),Xcode 应该尝试设置粉红色和红色视图之间的垂直距离 = 20,但它将意识到这与紫色和粉红色之间的空间 >= 20 的条件相冲突。由于 >= 约束具有更高的优先级,因此 = 约束将被忽略。现在,当 Xcode 查看紫色和粉色视图之间的间距 = 20 的约束时,它会根据粉色和红色必须至少间隔 20 的约束进行检查。由于红色视图的底部高于紫色视图的底部,红色和粉色之间的 >= 20 约束仍然通过。
So TL;DR, you can set up a view to have a spacing at a given value (x) from the most extreme of multiple views by giving it a >= x constraint with 1000 priority and giving it a = x constraint with <1000 priority for each view you are considering - and my vertical ambiguity problem has been solved. I do not yet have a solution for the horizontal ambiguity for all 4 of the views.
因此,TL;DR,您可以设置一个视图,使其与多个视图中最极端的给定值 (x) 有一个间距,方法是给它一个 >= x 约束和 1000 优先级,并给它一个 = x 约束 <1000您正在考虑的每个视图的优先级 - 我的垂直模糊问题已经解决。我还没有解决所有 4 个视图的水平歧义的解决方案。
Horizontally Ambiguous
横向模糊
Okay, I got the horizontally ambiguous part fixed now as well. What it boils down to is that constraints in scroll views (and therefore table views) work differently than they do for any other kind of view. Here's what the step-by-step looks like.
好的,我现在也修复了水平不明确的部分。归结为滚动视图(以及表格视图)中的约束与它们在任何其他类型的视图中的工作方式不同。下面是分步的样子。
- Place the
UIScrollView
- Place a
UIView
into theUIScrollView
to serve as a "contentView
" for that scroll view - Add constraints to pin the
contentView
to all 4 corners of the scroll view AND pin it'swidth
andheight
(so 6 constraints between thecontentView
and it's superview - 2 more than usual). Note that thewidth
and theheight
can be pinned to something much larger than the normal screen size, which is probably why you are using a scroll view to begin with. - Add all of your other views you want in the
UIScrollView
(UIButtons
,UILabels
, etc. - I'm just going to assumeUILabel
from here on so I don't have to type as much, but any kind ofUIView
subclass will work) as subviews of thecontentView
, NOT directly as subviews of theUIScrollView
- 放置
UIScrollView
- 将 a
UIView
放入UIScrollView
作为contentView
该滚动视图的“ ” - 添加约束以将 固定
contentView
到滚动视图的所有 4 个角width
并固定它和height
(因此在contentView
超级视图和超级视图之间有 6 个约束- 比平时多 2 个)。请注意,width
和height
可以固定到比正常屏幕尺寸大得多的东西上,这可能是您开始使用滚动视图的原因。 - 在
UIScrollView
(UIButtons
、UILabels
等) 中添加您想要的所有其他视图- 我只是UILabel
从这里开始假设,所以我不必输入那么多,但任何类型的UIView
子类都可以) 作为 的子视图contentView
,不直接作为UIScrollView
With this setup, the UILabel
s that are given constraints to their superview will constrain to the contentView
, which has a defined size, so nothing is ambiguous.
通过这种设置,UILabel
被赋予其父视图约束的s 将约束到contentView
具有定义大小的 ,因此没有什么是模棱两可的。
Alternatively, if you want to fix the sizes of your UILabel
s (or dynamically calculate them, depending on the functionality of your app) and let the contentView
expand to hold them:
或者,如果您想固定UILabel
s的大小(或动态计算它们,具体取决于您的应用程序的功能)并让contentView
扩展来容纳它们:
- Place the
UIScrollView
- Place a
UIView
into theUIScrollView
to serve as a "contentView
" for that scroll view - Add constraints to pin the
contentView
to all 4 corners of the scroll view AND pin it'swidth
andheight
- create an outlet for the
width
constraints on thecontentView
(let's say we name itcontentViewWidthConstraint
) - place the
UILabel
s - fix the sizes of the
UILabel
s - create an outlet for the
width
constraints on theUILabel
s
- 放置
UIScrollView
- 将 a
UIView
放入UIScrollView
作为contentView
该滚动视图的“ ” - 添加约束以将 固定
contentView
到滚动视图的所有 4 个角width
并固定它和height
- 为
width
约束创建一个出口contentView
(假设我们命名它contentViewWidthConstraint
) - 放置
UILabel
s - 固定
UILabel
s的大小 - 为s
width
上的约束创建一个出口UILabel
Then in the code for viewWillLayoutSubviews
然后在代码中 viewWillLayoutSubviews
- add up the widths of all of the
UILabel
s and any gaps you want between them (as aCGFloat
, which I'll calltotalWidth
) - set
contentViewWidthConstraint.constant = totalWidth
- 将所有
UILabel
s的宽度以及它们之间所需的任何间隙相加(作为CGFloat
,我将称之为totalWidth
) - 放
contentViewWidthConstraint.constant = totalWidth
And you're good to go! Note that I assumed you were setting the width in most of this example, but it should be just as applicable to height.
一切顺利!请注意,我假设您在本示例的大部分内容中设置了宽度,但它应该同样适用于高度。
回答by Greg
The problem is that many different widths of the two views will satisfy the constraints that you've set up. Here are two examples (I drew the shapes stacked vertically to make it easier to see the overlap example):
问题是两个视图的许多不同宽度将满足您设置的约束。这里有两个例子(我画了垂直堆叠的形状,以便更容易看到重叠的例子):
You can add a horizontal space constraint with a value of 0.
您可以添加值为 0 的水平空间约束。