首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如果调用UIView (),那么layoutIfNeeded约束就不会活跃

如果调用UIView (),那么layoutIfNeeded约束就不会活跃
EN

Stack Overflow用户
提问于 2017-05-02 13:23:25
回答 2查看 3.3K关注 0票数 0

我试图动画一个受约束的视图(iconVerticalConstraint),使其位于超级视图的中心Y (+100),特别是在动画之后到达它的右侧(0)位置。这是我的密码:

代码语言:javascript
运行
复制
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()放在动画块中将使整个视图动画化,而不仅仅是这个约束。否则,这种方法根本不做动画。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-03 10:01:54

经过几个小时的时间来理解基本的机制,我可以提供我自己的答案,为所有将发现自己在我的处境。

layoutIfNeeded()告诉视图调整其所有子视图的位置。相反,animateanimateKeyframes或您正在使用的所有其他选项都告诉视图按照在animate函数中指定的方式执行动画块内的任何指令(默认情况下,使用options: .easeInOut)。

回到问题:问题在于animatelayoutIfNeeded被称为animate,因此实际上,动画块中的每条指令都是在layoutIfNeeded指令之前执行的,这使得它变得毫无用处。解决方案不是像SeanLintern88建议的那样在动画块中放置SeanLintern88指令,因为这样我们可以告诉视图根据动画选项调整子视图的位置。这才是关键。

答案有点简单。将动画部分移动到子视图本身的上,特别是当您知道superview已经被“自动设置”(例如viewDidAppear)时,因此约束已经定义并执行,现在您可以更改它。在这一点上,代码应该如下所示:

代码语言:javascript
运行
复制
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函数中这样做)。

票数 2
EN

Stack Overflow用户

发布于 2017-05-02 13:27:10

不断变化的约束,如

代码语言:javascript
运行
复制
self.iconVerticalConstraint.constant -= 20

应该在动画块之外,在里面只需调用

代码语言:javascript
运行
复制
self.view.layoutIfNeeded() 

我想是因为你想做2,然后打电话给

代码语言:javascript
运行
复制
self.view.layoutIfNeeded() 

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

代码语言:javascript
运行
复制
    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()

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43739056

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档