当前位置: 首页 > 知识库问答 >
问题:

setNeedsLayout vs. setNeds更新约束和布局如果需要 vs 更新约束需要

司寇灵均
2023-03-14

我知道自动布局链基本上由3个不同的过程组成。

  1. 更新约束
  2. 布局视图(这里是我们计算框架的地方)
  3. 显示

我并不完全清楚的是 -setNeedsLayout-setNeeds更新约束之间的内在区别。来自苹果文档:

设置需要布局

当您想要调整视图子视图的布局时,请在应用程序的主html" target="_blank">线程上调用此方法。此方法记下请求并立即返回。由于此方法不会强制立即更新,而是等待下一个更新周期,因此您可以使用它来使多个视图的布局失效,然后再更新这些视图中的任何一个。此行为允许您将所有布局更新合并到一个更新周期,这通常对性能更好。

setNeedsUpdateConstraints(设置需要更新约束)

当自定义视图的属性以会影响约束的方式更改时,您可以调用此方法来指示约束需要在将来的某个时间点进行更新。然后,系统将调用updateConstraints作为其正常布局过程的一部分。在需要之前一次性更新约束,可确保在布局过程之间对视图进行多次更改时,不会不必要地重新计算约束。

当我想在修改约束后对视图进行动画处理并对我通常调用的更改进行动画处理时,例如:

[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.5f initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        [self.modifConstrView setNeedsUpdateConstraints];
        [self.modifConstrView layoutIfNeeded];
    } completion:NULL];

我发现如果我使用-setNeedsLayout而不是-setNeedsUpdateConstraint,一切都按预期工作,但是如果我将-layoutIfNeed更改为-updateConstraintsIfNeed,动画就不会发生。
我试图做出自己的结论:

  • -updateConstraintsIfNeed仅更新约束,但不强制布局进入进程,因此仍保留原始帧
  • -setNeedsLayout也调用-updateContraint方法

那么什么时候可以使用一个而不是另一个呢?关于布局方法,我需要在约束发生变化的视图或父视图上调用它们吗?

共有2个答案

晁绍辉
2023-03-14

coverback的回答非常正确。然而,我想补充一些额外的细节。

下面是一个典型的UIView循环的图表,它解释了其他行为:

  1. 我发现如果我使用-setNeedsLayout而不是-setNeedsUpdateConstraint,一切都按预期工作,但如果我将-layoutIfNeed更改为-updateConstraintsIfNeed,动画就不会发生。

updateConstraint通常不做任何事情。它只是解决约束,直到调用layoutSubview才应用它们。所以动画确实需要调用layoutSubview

不,这不是必需的。如果您的约束尚未修改,UIView 将跳过对更新约束的调用。您需要显式调用 setNeeds更新约束以修改流程中的约束。

为了调用updateConstraint,您需要执行以下操作:

[view setNeedsUpdateConstraints];
[view setNeedsLayout]; 
[view layoutIfNeeded];
柳英豪
2023-03-14

你的结论是对的。基本方案是:

    < Li > < code > setNeedsUpdateConstraints 确保将来对< code > updateconstraintsifneed 的调用调用< code>updateConstraints。 < li> setNeedsLayout确保将来调用< code > layoutifneed 时调用< code>layoutSubviews。

布局子视图被调用时,它还调用更新约束IfNeeded,因此根据我的经验,手动调用它很少需要。实际上,除了调试布局时,我从未调用过它。

objc,使用setNeedsUpdateConstraints更新约束也很少见。io是关于自动布局的必读读物,他说:

如果随后发生的变化使您的某个约束无效,您应该立即移除该约束,并调用setNeedsUpdateConstraints。事实上,这是您必须触发约束更新过程的唯一情况。

此外,根据我的经验,我从来没有使约束无效,也没有在下一行代码中设置< code>setNeedsLayout,因为新的约束几乎是要求新的布局。

经验法则是:

  • 如果直接操作约束,请调用setNeedsLayout
  • 如果您更改了某些条件(如偏移量或smth),这些条件将更改重写的updateConstraints方法中的约束(顺便说一句,这是更改约束的推荐方法),请在这之后调用setNeedsUpdateConstraintsetNeeds Layout,大多数情况下还会调用setNeed Layout
  • 如果需要上述任何操作立即生效,例如在布局过程后需要了解新的帧高度时,请附加layoutIfNeeded

此外,在您的动画html" target="_blank">代码中,我认为不需要< code > setNeedsUpdateConstraints ,因为约束是在动画之前手动更新的,动画只是根据新旧视图之间的差异重新布局视图。

 类似资料:
  • 我有两个组件和。每个组件都是由<code>ConstraintLayout</code>创建的。现在,我从上面的组件创建<code>WelcomeScreen</code>。 用例1:使用静态< code>ConstraintLayout(在< code>ConstraintLayout内的< code>ConstraintLayout) 结果:布局预览不显示任何内容 用例2:<代码>Welcom

  • 截图显示了一种方法: 但即使在多次点击之后,重新启动Android Studio,我也无法更改它。我怎么改?

  • 我已经添加了约束到3标签关于holderview和也添加了约束holderview关于Superview 应用程序中有一个缩小圆圈的功能。我希望holderview及其子视图动态收缩。添加约束对holderview有效,但子视图未对齐。 为了缩小,我会随着超级视图帧的变化更新Holderview的帧大小。 有人能指出错误并指导我找到正确的解决方案吗?

  • 我的桌子有两个独特的列: 我想写保存或更新方法 My jooq code: 但我遇到了异常: “错误:没有唯一或排除约束匹配ON CONFLICT规范” 请帮助。

  • 我正在将错误消息添加到登录屏幕。 虽然代码运行良好,并且执行我希望它执行的操作。它会在执行时导致约束错误。 以下是受影响的约束: 下面是导致errorView出现的函数。 如何在不破坏约束的情况下更改约束? 我尝试self.view.update约束()-但是什么也没有做。我还尝试在添加约束之前删除它们,但是仍然有一个错误。 任何帮助都将不胜感激! 编辑: 我找到了一个Objective-c解决方

  • 我刚开始使用约束布局,我在编译设计文件时遇到断言错误,这个问题就会单独出现。解决此问题的正确方法是什么?我搞砸了洞日。这是我的XML设计。 和我的错误日志: java.lang.AssertionError:在Android.Support.Constraint.Solver.Widgets.Guideline.GetAnchor(Guideline.java:159)在Android.Suppo