【问题标题】:Views are Horizontally and Vertically Ambiguous with complex layout视图水平和垂直不明确,布局复杂
【发布时间】:2013-10-15 17:51:27
【问题描述】:

我的故事板上有一个UIViewController,它水平方向有 2 个子视图。我添加了约束以将前缘和后缘固定为常数(20 分),并添加了另一个约束以保持宽度相等。如果我假设以下,应该可以计算出每个子视图的宽度需要:

  • 子视图不重叠
  • 不存在其他视图(至少在水平方向上)
  • 屏幕宽度(超级视图)已知

但是,XCode 给了我一个警告,我的观点在水平方向上是模棱两可的。我猜这意味着 XCode 没有做出这些假设之一,但它是哪一个?有没有办法让我指示 XCode 做出这样的假设?

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

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

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

说完了,我仍然收到一个警告,我的所有 4 个视图在水平方向上都是模棱两可的,而粉色条在垂直方向上是模棱两可的。我认为它很难意识到什么应该放在什么旁边,这就是为什么它认为它在水平方向上是模棱两可的。而且我认为将粉红色条放置在紫色或红色视图下方 20 点的位置并不合适,这就是它认为它在垂直方向上模棱两可的原因。谁能证实或否认这些怀疑?或者建议一种解决方法?当我最后运行它时,我得到了这个(我将滚动视图的背景设置为黄色,你在故事板屏幕截图中看不到):

【问题讨论】:

  • 你需要告诉 XCode 子视图之间的空间。

标签: ios xcode ios7 autolayout


【解决方案1】:

垂直模糊

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

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

所以 TL;DR,您可以设置一个视图,使其与多个视图中最极端的一个视图具有给定值 (x) 的间距,方法是给它一个具有 1000 优先级的 >= x 约束并给它一个 = x 约束对于您正在考虑的每个视图,优先级

水平模糊

好的,我现在也修复了水平方向模糊的部分。它归结为滚动视图(以及表视图)中的约束与任何其他类型的视图中的约束不同。这是分步的样子。

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

使用此设置,为其父视图指定约束的UILabels 将约束为具有定义大小的contentView,因此没有什么是模棱两可的。

或者,如果您想固定 UILabels 的大小(或动态计算它们,取决于您的应用的功能)并让 contentView 展开以容纳它们:

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

然后在viewWillLayoutSubviews的代码中

  • 将所有UILabels 的宽度以及您希望它们之间的任何间隙相加(作为CGFloat,我将其称为totalWidth
  • 设置contentViewWidthConstraint.constant = totalWidth

你可以走了!请注意,我假设您在此示例的大部分内容中都设置了宽度,但它应该同样适用于高度。

【讨论】:

  • 解决了我的问题!解决方案是有 2 个约束,其中一个必须在 700 左右。如果两者之间的差异很小,则它将不起作用,例如一个是 1000,另一个是 999。
【解决方案2】:

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

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

【讨论】:

  • 是的,这适用于这个例子。我认为我过度简化了我的问题。我可能很快就会更新...
  • 在我的情况下,我没有设置两个视图中的任何一个的高度,我为其中一个视图设置了高度约束,并且“垂直模糊”警告消失了。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 2017-03-02
  • 1970-01-01
  • 1970-01-01
  • 2015-03-04
相关资源
最近更新 更多