如果调用layoutIfNeeded(),UIView 约束将不会动画

Ale*_*ati 0 cocoa animation uiview ios swift

我正在尝试对一个被约束 ( iconVerticalConstraint) 位于+100超级视图中心 Y ( ) 的视图进行动画处理,特别是0在动画后到达其右侧 ( ) 位置。这是我的代码:

self.view.layoutIfNeeded()

UIView.animateKeyframes(withDuration: 2, delay: 0, animations: {

    UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 0.25, animations:{
        self.iconVerticalConstraint.constant -= 20
    })

    UIView.addKeyframe(withRelativeStartTime: 0.25, relativeDuration: 0.75, animations:{
        self.iconVerticalConstraint.constant -= 80
    })
})
Run Code Online (Sandbox Code Playgroud)

我尝试遵循这个问题的答案,但这没有帮助,因为在我的情况下,我的视图包含更多子视图,本质上链接,并且放入layoutIfNeeded()我的动画块将使整个视图动画化,而不仅仅是那个约束。否则这种方法根本不会产生动画。

Sea*_*ern 5

改变约束,例如

self.iconVerticalConstraint.constant -= 20
Run Code Online (Sandbox Code Playgroud)

应该在动画块之外并且在您只需调用的内部

self.view.layoutIfNeeded() 
Run Code Online (Sandbox Code Playgroud)

我想是因为你正在尝试做 2,并且打电话

self.view.layoutIfNeeded() 
Run Code Online (Sandbox Code Playgroud)

它们都发生一次,考虑更改为:

    self.iconVerticalConstraint.constant -= 20

    UIView.animate(withDuration: 0.25, animations: {
        self.view.layoutIfNeeded()
    }) { (finished) in
     
        self.iconVerticalConstraint.constant -= 80

        UIView.animate(withDuration: 0.75, animations: {
            self.view.layoutIfNeeded()
        }, completion: nil)
    }
Run Code Online (Sandbox Code Playgroud)

编辑:解释

当您更改约束时,视图直到下一个布局周期才会更新,通常是在您退出当前范围时。因此,当您想要对约束进行动画处理时,您可以在动画块之前更改常量,然后在动画块内调用layoutIfNeeded()This 告诉它对现在强制的布局周期进行动画处理。

现在,在您的示例中,您调用layoutIfNeeded()which 此时不会执行任何操作,然后更改 2 个常量,而不告诉布局进行动画处理,因此当范围退出时,UI 将在没有动画的情况下进行布局。

(80)在您的情况下,您想要链接两个常量的更改,但是在第一个动画完成后您没有办法更改第二个常量,并且如果您设置这两个常量,则两个常量将在第一个时进行调整layoutIfNeeded(),因此,动画的链接,它仍然可以与您省略的其他动画一起使用,只需将 then 添加到第一个动画块(如果它们位于第一个关键帧中)和第二个动画块(如果它们位于第二个关键帧中)。

最终编辑:

layoutIfNeeded()此外,您还可以将当前应用于 self.view 的实际内容更改为它影响的视图,在这种情况下iconVerticalConstraint,如果它是附加到另一个视图的视图,例如附加到视图底部的顶部,如果您想要动画,则必须调用layoutIfNeeded()在它影响的每个视图上