视图是水平和垂直模糊的,具有复杂的布局

时间:2013-10-08 17:03:14

标签: ios xcode ios7 autolayout

我的故事板上有一个UIViewController,它有两个水平左右的子视图。我添加了约束来将前沿和后沿修复为常量(20分),并添加另一个约束来保持宽度相等。如果我假设以下内容,则应该可以计算每个子视图的宽度:

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

然而,XCode给了我一个警告,我的观点是横向模糊的。我猜这意味着XCode没有做出这些假设之一,但它是哪一个?有没有办法让我指示XCode做出这个假设?

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

编辑2:好的,我的实际屏幕比我的简单示例复杂得多。这就是我得到的:

enter image description here

所以在这个设置中我有4个垂直和水平交错的视图。我希望蓝色,红色和紫色视图都是相同的subview.frame.size.width = superview.width - 60。蓝色和紫色在左列中排列,红色在右列中是单独的,并且所有间隙(两列之间以及每列之间和它的最近边缘)处于恒定(20点)。这3个表具有可变高度,我将按照James's answer here中的描述以编程方式设置。在底部是一个粉红色的视图,拉伸屏幕的宽度(减去间隙),并坐在紫色或红色视图下方的恒定20点,以较低者为准(我试图通过给它一个每个视图的间距约束> = 20,我希望它会为其中一个选择正好20个)。由于所有高度都是动态的,并且可能不一定同时适合屏幕,因此我将其超级视图设为UIScrollView而不是正常的UIView

当一切都说完了之后,我仍然会收到一个警告,我的所有4个视图都是水平模糊的,并且粉红色条是垂直模糊的。我认为它很难实现应该接下来的东西,这就是为什么它认为它是横向模糊的。而且我认为不会选择将粉红色的条纹放在紫色或红色视图下方20个点以下,这就是为什么它认为它是垂直模糊的。任何人都可以确认或否认这些怀疑吗?或建议一个方法呢?当我最终运行它时,我只是得到了这个(我将滚动视图的背景变为黄色,你在故事板截图中无法分辨):

enter image description here

2 个答案:

答案 0 :(得分:6)

垂直不明确

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

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

所以TL; DR,您可以设置一个视图,使其在多个视图中最极端的给定值(x)处有一个间距,方法是给它一个带有1000优先级的> = x约束并给它一个= x对于您正在考虑的每个视图的< 1000优先级的约束 - 我的垂直模糊问题已经解决。我还没有解决所有4个视图的水平模糊性问题。

水平模糊

好的,我现在修复了水平模糊的部分。它归结为滚动视图(以及表视图)中的约束与其他任何类型的视图的工作方式不同。以下是逐步说明的内容。

  • 放置UIScrollView
  • UIView放入UIScrollView以充当该滚动视图的“contentView
  • 添加约束以将contentView固定到滚动视图的所有4个角并将其固定为widthheight(因此contentView和它的超级视图之间有6个约束 - 比通常多2个)。请注意,widthheight可以固定为比正常屏幕尺寸大得多的东西,这可能就是您开始使用滚动视图的原因。
  • UIScrollViewUIButtonsUILabels等中添加您想要的所有其他观点 - 我将从这里开始假设UILabel我不必输入任何类型的UIView子类就可以了)作为contentView的子视图,而不是直接作为UIScrollView
  • 的子视图

通过此设置,对其超级视图赋予约束的UILabel将约束到具有已定义大小的contentView,因此不会有任何歧义。

或者,如果您想要修改UILabel的尺寸(或动态计算它们,具体取决于应用的功能),并让contentView展开以保留它们:

  • 放置UIScrollView
  • UIView放入UIScrollView以充当该滚动视图的“contentView
  • 添加约束以将contentView固定到滚动视图的所有4个角并将其固定为widthheight
  • width上的contentView约束创建一个出口(假设我们将其命名为contentViewWidthConstraint
  • 放置UILabel s
  • 修正UILabel s
  • 的尺寸
  • width
  • 上的UILabel约束创建一个出口

然后在viewWillLayoutSubviews

的代码中
  • 将所有UILabel的宽度和他们之间想要的任何差距相加(作为CGFloat,我称之为totalWidth
  • 设置contentViewWidthConstraint.constant = totalWidth

你很高兴去!请注意,我假设您在此示例的大部分内容中设置了宽度,但它应该适用于高度。

答案 1 :(得分:5)

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

Ambiguity example

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

Screenshot