3

有一件事真的让我对自动布局感到疯狂,我正在做我的测试,发现如果你将 UIView 子类化并且你放置一些带有约束的视图是不可能知道计算值的。
假设我们有一个继承自的 TestViewClass UIView,我们里面有一些子视图。我们想将它用于 iPhone 和 iPad,所以我们使用两种尺寸,假设 100x100 和 200x200 我们设置了约束以使一切正常。我们构建这个视图,将这些子视图放置在某些位置。
现在我们需要构建另一个子视图,其中包含许多按钮作为子视图(contentView),其编号是在运行时给出的。
该算法将选择此内容视图的大小并放置正确数量的按钮,以计算它们之间的间距,使它们彼此之间的距离相同,但覆盖整个内容视图的宽度。例如,contentView 的宽度为 200 点,按钮为 3,边长为 60。它们一起覆盖 180,所以我们还剩下 20 点,应该作为按钮之间的空间 -> 10 点。
这很容易,在自动布局之前做了数千次。为此,我需要 contentView 的宽度,它对其超级视图有一些限制,使其根据超级视图大小调整其宽度,问题是我在 UIView 实现中找不到任何可以得到最终值的地方内容视图的大小。
我试过查看-layoutSubviews, -updateConstraints, -didMoveToSuperview, 价值展示总是原始的。何时计算新帧?
我显然没有得到关于自动布局的一些东西......



我发现这个问题试图设置表格视图单元格高度,试图通过表格视图的大小使它们独立地出现在屏幕上。这是相关问题other question

4

2 回答 2

9

最后,我得到了我所缺少的关于自动布局的东西,它是一个基本概念。

自动布局不像自动调整蒙版那样工作,新帧不会立即更新,而是根据请求更新。

这有很大的不同,它似乎与 CATransaction 渲染周期同步,这是有道理的,因为布局计算可能是一项昂贵的任务,并且在您真正需要它之前是无用的,大部分时间在渲染期间。
当然也有少数例外,比如这个,我们如何强制自动布局来进行这个计算呢?我们可以做设置-setNeedsLayout方法和-layoutIfNeeded。第一种方法将视图标记为“脏”,第二种方法强制立即布局。如果您在-didMoveToSuperview获得正确的更新帧后立即调用这两种方法。
希望这会有所帮助,安德里亚

于 2013-06-18T06:04:15.673 回答
2

您可以使用视图控制器viewDidLayoutSubviews,它会在视图布局时通知您。如果所有这些都是在 custom 中添加约束UIView,您可以简单地为您的视图编写一个方法,viewDidLayoutSubviews并让视图控制器在视图控制器接收到它时调用该方法。此时,容器的尺寸应该正确配置。

但是,有几种方法可以在不知道容器视图大小的情况下甚至间隔一堆按钮:

  1. 我在容器中用于均匀间隔控件的一种方法是创建我所谓的“间隔”视图(存在的视图,但只有clearColor背景,因此您无法直观地看到它们)。然后,您可以有效地使用以下内容创建一系列约束:

    H:|[spacer1][button1(60)][spacer2(==spacer1)][button2(60)][spacer3(==spacer1)][button3(60)][spacer4(==spacer1)]|
    

    constraintsWithVisualFormat如果您的按钮数量是固定的,您可以像上面一样在单个 中执行此操作。如果它是可变数量的按钮,您可以遍历它们,为每对按钮和垫片构建一个 VFL 字符串(例如,第一个按钮将使用 VFL

    H:|[spacer][button(60)]
    

    所有后续的将创建另一个按钮和另一个垫片并使用以下 VFL:

    H:[previousButton][spacer(==originalSpacer)][button(60)]
    

    然后我在最后添加一个最后的垫片:

    H:[lastButton][spacer(==originalSpacer)]|
    

    这有点麻烦,但正如您所见,您的控件布局完美,间距均匀,您永远不需要知道容器的尺寸。

  2. 另一种方法是使用NSLayoutFormatAlignAllCenterX, 属性。这绕过了创建所有这些间隔的需要,但是如果你使用像我下面这样的简单算法,中心将在它们之间均匀分布。因此,除了按钮的标准垂直约束和水平宽度约束之外,您还可以通过以下方式控制按钮的水平放置:

    [containerView addConstraint:[NSLayoutConstraint constraintWithItem:button[i]
                                                              attribute:NSLayoutAttributeCenterX
                                                              relatedBy:NSLayoutRelationEqual
                                                                 toItem:containerView
                                                              attribute:NSLayoutAttributeCenterX
                                                             multiplier:2.0 * (double) (i + 0.5) / (double) n
                                                               constant:0.0]];
    

    wherei是您为其设置此水平约束的按钮的从零开始的索引,并且n是按钮的数量。

于 2013-06-18T04:01:55.613 回答