视图横向和纵向模糊,布局复杂

我的故事板上有一个UIViewController ,它有两个子视图水平并排。 我添加了约束条件来将前缘和后缘固定为一个常量(20点),另外还有一个约束来保持宽度相等。 如果我假设以下,应该有可能计算每个子视图的宽度将需要是什么:

  • 子视图不重叠
  • 没有其他意见(水平,至less)
  • 屏幕的宽度(超视图)是已知的

但是,XCode给我一个警告,我的观点是水平不明确的。 我猜测这意味着XCode没有做出这些假设之一,但是哪一个呢? 有没有办法指示XCode做出这样的假设?

编辑:好吧,玩了一下,并得到了警告消失,但它看起来不是第一个假设 – 它只是将每个子视图的宽度设置为superview.width - 40 ,并愉快地埋在另一个视图之下。 所以问题是如何阻止它们重叠?

编辑2:好吧,我的实际屏幕比我简单的例子更复杂。 这是我得到的:

在这里输入图像说明

所以在这个设置中,我有4个视图是垂直和水平交错的。 我想蓝色,红色和紫色视图都是相同的subview.frame.size.width = superview.width - 60 。 蓝色和紫色排列在左列,红色单列在右列,所有间隙(两列之间和每列与最近的边缘之间)都是恒定的(20点)。 这3个表格有一个可变的高度,我将按照詹姆斯在这里的回答中的描述来设置编程。 在底部是一个粉红色的视图,延伸屏幕的宽度(减去空白),并坐在一个恒定的20分以下的紫色或红色视图,以较低者为准(我试图通过给它一个对每个视图的> = 20的间隔约束,我希望它会为它们中的一个准确地select20)。 由于所有的高度是dynamic的,可能不一定适合在屏幕上同时,我做了他们的超级观点UIScrollView而不是正常的UIView

当所有的事情都说完之后,我仍然得到一个警告,那就是我的所有观点都是水平模糊的,而粉色条是垂直模棱两可的。 我觉得在实现什么应该是什么之后会遇到麻烦,这就是为什么它认为它是水平模糊的。 而且我认为把粉红色的酒吧放在紫色或红色的视图下方20点并不是挑剔的,这就是为什么它认为它是垂直模糊的。 任何人都可以确认或否认任何这些怀疑? 或者build议一个方法呢? 当我最后运行它时,我只是得到了这个(我把scroll view的背景变成了黄色,这是你在故事板屏幕截图中所看不到的):

在这里输入图像说明

垂直不明确

好吧,我想我已经解决了垂直歧义的部分。 我在粉色和紫色视图之间添加了两个垂直约束,在粉红色和红色视图之间添加了两个垂直约束。 对于每一对,第一个约束是它们之间的间隔必须> 20点,并且具有1000个优先级。 第二个约束是间距= 20点,但只有800点的优先级。

例如,如果紫色视图的底部低于红色视图的底部(就像在我的第一个屏幕截图中),Xcode应该尝试设置粉红色视图和红色视图之间的垂直距离= 20,但是它将认识到,与紫色和粉红色之间的空间> = 20的条件相冲突。由于> =约束具有更高的优先级,所以=约束将被忽略。 现在,当Xcode查看紫色和粉红色视图之间的间距= 20的约束时,它会检查约束条件,即粉红色和红色之间必须至less分隔20.由于红色视图的底部高于紫色视图的底部,红色和粉红色之间的> = 20约束依然通过。

所以TL,DR,你可以build立一个视图,在给定值(x)的情况下,从多个视图的最极端向一个给定值(x)分配一个具有1000个优先级的> = x约束,并给它一个<= 1000的约束您正在考虑的每个视图的优先级 – 我的垂直歧义问题已经解决。 我还没有针对所有4个视图的水平模糊的解决scheme。

水平不明确

好吧,我现在也弄清了水平不明确的部分。 归结起来,滚动视图(以及表视图)的约束条件与其他视图的约束条件不同。 这是一步一步的样子。

  • 放置UIScrollView
  • 将一个UIView放到UIScrollView ,作为该滚动视图的“ contentView
  • 添加约束来将contentView固定在滚动视图的所有四个angular上,并将其widthheight (因此contentView和它的超级视图之间有6个约束 – 比平常多2个)。 请注意, widthheight可以固定为比正常屏幕大得多的东西,这可能是为什么您使用滚动视图开始。
  • UIScrollViewUIButtonsUILabels等)中添加所有你想要的其他视图 – 我只是从这里假设UILabel ,所以我不必input太多,但任何types的UIView子类将工作)作为contentView子视图,而不是直接作为UIScrollView子视图

通过这个设置,给它们的超级视图约束的UILabel将约束到具有定义大小的contentView ,所以没有什么不明确的。

另外,如果你想修复你的UILabel的大小(或dynamic计算它们,取决于你的应用程序的function),并让contentView展开来保存它们:

  • 放置UIScrollView
  • 将一个UIView放到UIScrollView ,作为该滚动视图的“ contentView
  • 添加约束来将contentView到滚动视图的所有四个angular,并将其widthheight
  • contentViewwidth约束创build一个出口(假设我们将其命名为contentViewWidthConstraint
  • 放置UILabel
  • 修复UILabel的大小
  • UILabel上的width约束创build一个出口

然后在viewWillLayoutSubviews的代码中

  • 加起来所有UILabel的宽度以及它们之间的任何间隔(作为CGFloat ,我将其称为totalWidth
  • 设置contentViewWidthConstraint.constant = totalWidth

你很好走! 请注意,我假设你在这个例子中的大部分设置了宽度,但是它应该和高度一样。

问题是两个视图的许多不同宽度将满足您设置的约束。 这里有两个例子(我画了垂直堆叠的形状,以便更容易看到重叠的例子):

歧义示例

您可以添加值为0的水平空间约束。

截图