动画约束导致不同的初始位置

Posted

技术标签:

【中文标题】动画约束导致不同的初始位置【英文标题】:Animating constraint results in different initial position 【发布时间】:2017-06-23 11:45:39 【问题描述】:

我有一个绿色视图,它固定在顶视图的边缘。顶部是一个蓝色视图,它也是顶视图的子视图,使用以下代码对齐...

import UIKit

class ViewController: UIViewController 

    @IBOutlet weak var blueView: UIView!
    @IBOutlet weak var greenView: UIView!

    override func viewDidLoad() 

        super.viewDidLoad()

        blueView.translatesAutoresizingMaskIntoConstraints = false

        blueView.widthAnchor.constraint(equalTo: greenView.widthAnchor).isActive = true
        blueView.leftAnchor.constraint(equalTo: greenView.leftAnchor).isActive = true

        blueView.heightAnchor.constraint(equalTo: greenView.heightAnchor).isActive = true

        let top = blueView.topAnchor.constraint(equalTo: greenView.topAnchor)
        top.priority = 800
        top.isActive = true

        view.layoutIfNeeded()

        UIView.animate(withDuration: 5) 

            let bottom = self.blueView.topAnchor.constraint(equalTo: self.greenView.bottomAnchor)
            bottom.priority = 1000
            bottom.isActive = true

            self.view.layoutIfNeeded()
        
    

如果我把动画代码注释掉,就是这个样子……

使用动画块,蓝色视图在正确的位置结束,但它从屏幕顶部开始,而不是与绿色视图的顶部对齐。

为什么动画块会导致蓝色视图在屏幕上进一步启动?

【问题讨论】:

根据您的代码,您将Blue 设置为与Green 相同的大小和位置......然后动画块向下滑动Blue 直到它完全离开屏幕。这就是你所看到的吗?这不是你想要的吗? 这就是我想要的,主要是它在做什么。问题是动画似乎导致蓝色从屏幕顶部开始,而不是在与绿色相同的位置。 【参考方案1】:

好的 - 蓝色视图没有从绿色视图的顶部开始,因为您在初始布局完成之前开始动画。

您可以将动画块移动到延迟后触发的函数中,或移动到viewDidAppear

import UIKit

class AnimViewController: UIViewController 

    @IBOutlet weak var blueView: UIView!
    @IBOutlet weak var greenView: UIView!

    override func viewDidLoad() 

        super.viewDidLoad()

        blueView.translatesAutoresizingMaskIntoConstraints = false

        blueView.widthAnchor.constraint(equalTo: greenView.widthAnchor).isActive = true
        blueView.leftAnchor.constraint(equalTo: greenView.leftAnchor).isActive = true

        blueView.heightAnchor.constraint(equalTo: greenView.heightAnchor).isActive = true

        let top = blueView.topAnchor.constraint(equalTo: greenView.topAnchor)
        top.priority = 800
        top.isActive = true

    

    override func viewDidAppear(_ animated: Bool) 
        super.viewDidAppear(animated)

        UIView.animate(withDuration: 5) 

            let bottom = self.blueView.topAnchor.constraint(equalTo: self.greenView.bottomAnchor)
            bottom.priority = 1000
            bottom.isActive = true

            self.view.layoutIfNeeded()
        
    

【讨论】:

没有办法在开始动画之前强制更新吗? viewDidLoad 在视图控制器的活动顺序中非常早。 viewDidAppear 是一个非常适合开始 5 秒动画的地方。 例如,如果您想将所有这些代码放在点击处理程序上怎么办?您是在暗示需要添加延迟? 不...当您加载并显示视图控制器时,必须发生很多事情。 viewDidLoad 在过程中早期,子视图、手势、约束等还没有被操作系统完全“解决”。你有 viewDidLoad viewWillAppear viewWillLayoutSubviews viewDidLayoutSubviews viewDidAppear 等等。对按钮点击采取行动是完全不同的情况 - 你正在对已经存在的对象进行操作(除非你的意思是按钮点击加载一个新的控制器, 在这种情况下,请参阅以前的 cmets)。 是的,动态添加的视图控制器的动画问题正是导致问题的原因。抱歉,您指的是以前的哪些 cmets?

以上是关于动画约束导致不同的初始位置的主要内容,如果未能解决你的问题,请参考以下文章

动画 UITableView 的自动布局顶部约束导致崩溃,有啥线索吗?

宽度约束动画时UITextfield文本位置没有动画

同时使用不同的动画曲线为 AutoLayout 约束设置动画

iOS以编程方式添加约束导致错误

[iOS]:删除和添加约束时自动布局动画更改框架位置

约束动画之前的跳跃图像