我试图动画一个受约束的视图(iconVerticalConstraint),使其位于超级视图的中心Y (+100),特别是在动画之后到达它的右侧(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
})
})我试着跟踪this question's answer,但这并没有帮助,因为在我的例子中,我的视图包含更多的子视图,本质上是链接的,并且将layoutIfNeeded()放在动画块中将使整个视图动画化,而不仅仅是这个约束。否则,这种方法根本不做动画。
发布于 2017-05-03 10:01:54
经过几个小时的时间来理解基本的机制,我可以提供我自己的答案,为所有将发现自己在我的处境。
layoutIfNeeded()告诉视图调整其所有子视图的位置。相反,animate或animateKeyframes或您正在使用的所有其他选项都告诉视图按照在animate函数中指定的方式执行动画块内的任何指令(默认情况下,使用options: .easeInOut)。
回到问题:问题在于animate和layoutIfNeeded被称为animate,因此实际上,动画块中的每条指令都是在layoutIfNeeded指令之前执行的,这使得它变得毫无用处。解决方案不是像SeanLintern88建议的那样在动画块中放置SeanLintern88指令,因为这样我们可以告诉视图根据动画选项调整子视图的位置。这才是关键。
答案有点简单。将动画部分移动到子视图本身的上,特别是当您知道superview已经被“自动设置”(例如viewDidAppear)时,因此约束已经定义并执行,现在您可以更改它。在这一点上,代码应该如下所示:
UIView.animateKeyframes(withDuration: 2, delay: 0, animations: {
self.view.layoutIfNeeded()
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
})
})因为您希望能够让动画化自动收费表。
另一个选项(例如,如果您不/不想为您的子视图创建类)是在父视图的bounds/center函数中更改子视图本身的viewDidAppear。这是因为,如果您在父视图中,您知道在这一点上,汽车布局已经注册,但没有执行,在更精确的意义上,边界和中心已经改变了根据自动布局。
如果然后更改它们,您将获得所需的动画(但请记住:自动布局仍然处于打开状态,因此必须以反映动画的最终位置的方式更改约束;如果愿意,可以在completion部分的animate函数中这样做)。
发布于 2017-05-02 13:27:10
不断变化的约束,如
self.iconVerticalConstraint.constant -= 20应该在动画块之外,在里面只需调用
self.view.layoutIfNeeded() 我想是因为你想做2,然后打电话给
self.view.layoutIfNeeded() 它们都发生过一次,考虑改为:
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)
}编辑:解释
更改约束时,视图直到下一个布局周期才会更新,通常是在退出当前范围时。因此,当您想要动画一个约束时,您可以在动画块之前更改常量,然后在您调用的layoutIfNeeded()动画块中,这会告诉它动画化现在强制的布局周期。
现在,在您的示例中,您将调用layoutIfNeeded() --在这一点上它什么也不做,然后更改2个常量,而不通知布局为动画,所以当作用域退出时,UI将不使用动画进行布局。
在您的示例中,您希望链接两个常量的更改,但是在第一个动画完成后,您没有办法更改第二个常量(80),如果设置这两个常量,这两个常量都将在第一个layoutIfNeeded()上进行调整,因此,动画的链接将继续与您省略的其他动画一起工作,只要在第一个关键帧中添加第一个动画块,如果它们在第二个关键帧中,则添加第二个动画块。
最后编辑:
此外,您还可以将当前应用于self.view的self.view更改为它所影响的视图上的实际值,在本例中,如果它是一个附加到另一个视图的视图,则可以将其顶部附加到视图底部,如果您想要动画,则必须对其影响的每个视图调用layoutIfNeeded()。
https://stackoverflow.com/questions/43739056
复制相似问题