以编程方式从超级视图中删除视图后更新约束/框架(自动布局)

Posted

技术标签:

【中文标题】以编程方式从超级视图中删除视图后更新约束/框架(自动布局)【英文标题】:Updating Constraints/Frames After a View is Programmatically Removed from Superview (Autolayout) 【发布时间】:2014-07-10 20:06:05 【问题描述】:

我在 IB 中使用自动布局。我的屏幕布局如下所示:

+-----------------+
| +--+ +--+ +--+  |
| |  | |  | |  |  |
| |  | |  | |  |  |
| |1 | |2 | |3 |  |
| |  | |  | |  |  |
| |  | |  | |  |  |
| +--+ +--+ +--+  |
+-----------------+

我的目标是创建一个灵活的动态视图。每当从视图中删除其中一个中心框时([object removeFromSuperview]),我都希望更新约束,在所有对象之间保持统一的空间。

例如,在移除中心对象后,视图应该如下更新:

+-----------------+
| +--+ +--+       |
| |  | |  |       |
| |  | |  |       |
| |1 | |3 |       |
| |  | |  |       |
| |  | |  |       |
| +--+ +--+       |
+-----------------+

目前我有大小限制、底部空间限制和前导空间限制 - 都是统一的。

在调用 removeFromSuperview 之后,我尝试调用 layoutIfNeeded、updateConstraints 等。没有效果。对象只是停留在原来的位置。

这有可能实现吗?

【问题讨论】:

正如@rdelmar 所建议的那样,我正在使用一组子视图,我以编程方式添加到超级视图中,并以编程方式配置约束。它工作得很好,甚至不需要那么多代码。 【参考方案1】:

您可能在视图 23 之间有间距限制。

当您删除视图2 时,您必须在视图13 之间创建一个新的约束。

如果视图的数量是真正动态的,并且每个视图的大小都是一致的,那么您可能应该改用UICollectionView

【讨论】:

如果有任何意义的话,我会假设约束是“到最近对象的剩余空间”而不是“到对象 x 的剩余空间”。似乎它不应该与对象一起删除......我会尝试一下。集合视图似乎太重了,这实际上只是 UITableViewCell 中的一个小 UI 元素。【参考方案2】:

如果您只有这 3 个视图,则可以在 1 和 3 之间创建水平间距约束。在删除 2 后对其进行编辑以赋予您想要的值,并将其优先级更改为小于 1000,例如 900。所以, 3 将对 1 和 2 都有间距约束,但在视图 2 被删除之前,1 到 2 将优先。如果你有超过 3 个视图,它会变得有点复杂,但你可以使用类似的方法。

【讨论】:

嗯...如果第一个视图被删除而不是中心怎么办?我现在至少有四个视图,将来可能会更多。 @cdstamper,你需要 2 来对左边缘有一个较低优先级的约束来处理删除 1 的情况。当您获得 4 个或更多视图时,事情会很快变得复杂。我将不得不考虑是否有更好的更通用的方法来做到这一点。您有时会删除多个视图吗?我们是否也必须考虑这种可能性? 是的,我有时会删除两三个项目。集合视图可能是合适的,但我不会将一个嵌入到我所有的表格视图单元格中...... @cdstamper,我不会像我在回答中所说的那样尝试这样做,我认为它会变得太复杂。我会保留我的视图数组,删除后,删除所有水平约束,然后从左边缘的一个开始添加它们,无论视图是数组中的第一个视图,然后从第二个到创建新视图第一个、第三个到第二个等等。如果你在循环中执行此操作,它实际上不会涉及那么多代码。 这实际上是一个非常好的解决方案。我要和这个一起去。谢谢@rdelmar!

以上是关于以编程方式从超级视图中删除视图后更新约束/框架(自动布局)的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式将视图的底部约束从安全区域更改为超级视图?

以编程方式创建一个视图,将框架设置为超级视图的框架?

iOS 从超级视图中删除对象会破坏自动布局并禁用滚动视图

为啥我以编程方式创建的视图会忽略其约束?

如何删除视图和更新约束?

以编程方式修改自动布局约束时视图不更新