iOS:带有 1 个标签和 3 个按钮的简单自动布局

Posted

技术标签:

【中文标题】iOS:带有 1 个标签和 3 个按钮的简单自动布局【英文标题】:iOS: Simple AutoLayout with 1 Label and 3 Buttons 【发布时间】:2012-11-16 14:43:41 【问题描述】:

我正在玩 AutoLayout,我真的想把我的头撞到墙上,因为它似乎应该是一个非常简单的解决方案。

    我有一列垂直控件:1 个标签和 3 个按钮。 我希望标签的高度为 40 像素(点),并根据其父视图的宽度(左侧、顶部和右侧的标准间距)自动调整其宽度。 我希望 3 个按钮在该标签下方垂直排列。 我希望它们的宽度像标签一样自动调整大小。 我希望它们的间距为标准(水色?)间距(8 点,对吗?)。 我希望 3 个按钮的高度相同。

我可以得到我想要的工作,但我在运行时不断在控制台中收到错误,我想弄清楚我为什么会得到它们以及如何避免得到它们。我在 AutoLayout 上观看了 WWDC 视频,这是我目前尝试过的:

UILabel *label = [self Label];
MMGlossyButton *button1 = ...
MMGlossyButton *button2 = ...
MMGlossyButton *button3 = ...
[[self view] addConstraints:
    [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[label]-|"
    options:0
    metrics:nil
    views:NSDictionaryOfVariableBindings(label)]];
[[self view] addConstraints:
    [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button1]-|"
    options:0
    metrics:nil
    views:NSDictionaryOfVariableBindings(new)]];
[[self view] addConstraints:
    [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button2]-|"
    options:0
    metrics:nil
    views:NSDictionaryOfVariableBindings(existing)]];
[[self view] addConstraints:
    [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[button3]-|"
    options:0
    metrics:nil
    views:NSDictionaryOfVariableBindings(provider)]];
[[self view] addConstraints:
    [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[label(40)]-[button1(>=25)]-[button2(==button1)]-[button3(==button1)]-|"
    options:0
    metrics:nil
    views:NSDictionaryOfVariableBindings(label, button1, button2, button3)]];

因此,这适用于以动态大小的方式显示视图,但控制台中会弹出以下错误:

Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. 
Try this: 
    (1) look at each constraint and try to figure out which you don't expect; 
    (2) find the code that added the unwanted constraint or constraints and fix it. 
        (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you 
               don't understand, refer to the documentation for the UIView 
               property translatesAutoresizingMaskIntoConstraints) 

// A whole bunch of constraint stuff that doesn't appear to be important...

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7554c40 V:[MMGlossyButton:0x7554b40(99)]>

所以,最后一点似乎表明我在视图上的第一个按钮静态大小为 99 磅高。 这是它在视图上的大小。 这是完全任意的。 我不想分配,但无法找到取消分配的方法。

虽然我得到了我想要的(某种程度上,最终),但这似乎是一种真正迂回的方式来完成非常简单的事情。我是否缺少有关 AutoLayout 的一些基本知识,或者它的功能是否需要如此复杂?

【问题讨论】:

如何将按钮和标签添加到视图中?在情节提要中,还是在代码中? 另外,“一大堆看起来并不重要的约束”可能,你能把它包括进来吗? 我可以,但它的内容很多,而且只是我在我展示的代码中定义的约束。此外,按钮放置在使用 IB 的 XIB 上。这就是 99 点高度的由来。 【参考方案1】:

您遇到错误是因为您将代码中生成的约束与界面生成器添加的约束混合和匹配。界面生成器不允许您生成模棱两可的布局,因此几乎按照定义,如果您添加额外的约束,您将收到"Unable to simultaneously satisfy" 错误,这是许多婚姻的失败。

要解决这个问题,您要么需要在界面生成器中定义所有需要的约束,要么需要将特定的约束标记为出口并在代码中删除它们,然后再添加您自己的。

在您的情况下,约束很简单,可以在 IB 中创建。

您可以在选择标签时使用 IB 中的此按钮固定到特定高度:

中间的那个,看起来像一个大梁。这将为您提供以下有用的菜单:

选择其中之一允许您针对标签创建一个新约束,然后您可以通过选择它进行编辑:

然后您可以添加按钮,选择所有三个按钮,并使用相同的菜单创建等高约束。

在 IB 中创建的约束不是特别灵活,因此如果您决定需要在代码中创建或修改它们,最好创建特定约束的出口,然后删除并重新创建它们,或在运行时修改constant 值。

【讨论】:

我认为 Xcode 之类的可能存在错误。我按照你的指示,这符合我的直觉,符合逻辑,但它就是行不通。当然,除非当我将视图的大小从 Retina 4 切换到 Retina 3.5 时,有什么我不知道的。我可以使用 Retina 4 让布局按我的意愿工作,但是当我切换到 Retina 3.5 时,会出现一大堆不同的约束,并且布局似乎在更改视图大小之前被“冻结”。想法? 我的主要想法是IB中的约束编辑做得很差!我在回答这个问题时做了一个示例项目,但我没有在两种 iPhone 尺寸之间进行更改。当我回到我的 Mac 时,我会看看。 谢谢。也许只是我,或者也许是 Xcode。似乎很难隔离导致问题的原因。如果我很乐意在代码中完成所有约束,但仍想在 IB 中进行原始布局,这可能吗?我该怎么做? 从 3.5 英寸更改为 4 英寸对我的示例项目中的约束没有影响,它们保持完全相同。所以我不确定你的情况如何。我在 Xcode 4.5.2 上。至于你的其他问题,你可以通过删除和重新添加约束来做到这一点,但老实说,当你完成所有这些时,你还不如用代码构建整个东西。 赞成这个只是因为“无法同时满足”错误,这是许多婚姻的失败。部分。 +1

以上是关于iOS:带有 1 个标签和 3 个按钮的简单自动布局的主要内容,如果未能解决你的问题,请参考以下文章

iOS 使按钮和标签在一段时间后出现

使用自动布局创建带有文本和图像的 iOS 7 UIButton

iOS自动布局,列对齐

iOS 自动布局和拥抱内容

如何在标签栏控制器视图上创建后退按钮?

iOS两个标签栏按钮与segue相同的navigationcontroller