ios - 以编程方式添加后,使用约束为 UIView 设置动画

标签 ios animation constraints

我有一个 UIView,我像这样以编程方式添加到我的 UIViewController 中:

if let myView = Bundle.main.loadNibNamed("MyView", owner: self, options: nil)?.first as? MyView
    {
        self.view.addSubview(myView)
        myView.translatesAutoresizingMaskIntoConstraints = false
        //Horizontal orientation
        self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[view]-10-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":myView]))
    }

很好, View 在 View Controller 的 (0,0) 左右添加了所需的空间。

我想要实现的是 View 从 View Controller 的底部到中心进行动画处理,然后从中心到顶部进行动画处理。 所以首先我尝试将它设置为从当前位置 (0,0) 居中

所以我做的是:

UIView.animate(withDuration: 1.0,
                   animations:
    {
        let center = NSLayoutConstraint(item: myView, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1, constant: CGFloat(0.0))
        self.view.addConstraint(center)
    })

好吧, View 位于中心,但它不是动画。它直接跳转到它。

我搜索并找到了很多答案说我必须设置约束的常量然后调用 layoutIfNeeded() 但所有这些示例都使用对之前设置为 IBOutlet 的约束的引用,我没有,因为我以编程方式添加我的 View 。

如何正确地为 View 设置动画,从底部到中心然后从中心到顶部?

已经谢谢你了!

问候

编辑 1

好吧,我要更进一步解释我想要实现的目标。 在我的 View Controller 上,在向用户显示 5 秒计时器后,我想一个接一个地显示几个问题。

我想要一个问题从底部滑入中心,得到回答,然后从中心滑出到顶部。然后下一个问题从底部到中心出现,回答滑出等等。

因此,在 5 秒计时器后,我调用了名为 slideInQuestion 的方法,该方法创建了一个问题并将其设置为动画:

func slideInQuestion()
{
    let question:QuestionView = createQuestion()
    UIView.animate(withDuration: 1.0,
                   animations:
    {
        self.yConstraint?.constant = CGFloat(0.0)
        self.view.layoutIfNeeded()
    })

createQuestion 方法实例化问题 View 并为其分配约束

func createQuestion() -> QuestionView
{
    if let questionView = Bundle.main.loadNibNamed("QuestionView", owner: self, options: nil)?.first as? QuestionView
    {
        self.view.addSubview(questionView)
        questionView.translatesAutoresizingMaskIntoConstraints = false
        //Horizontal orientation
        self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[view]-10-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":questionView]))
        yConstraint = NSLayoutConstraint(item: questionView,
                                              attribute: .centerY,
                                              relatedBy: .equal,
                                              toItem: self.view,
                                              attribute: .centerY,
                                              multiplier: 1,
                                              constant: CGFloat(UIScreen.main.bounds.height))
        self.view.addConstraint(yConstraint!)
        return questionView
    }
    return QuestionView()
}

之前,我按照 Duncan C 的建议将 yConstraint 定义为实例变量,如下所示:

    var yConstraint:NSLayoutConstraint?

所以我期望我现在拥有的是:

问题 View 已创建,它的中心位于 View Controller 的中心 + 屏幕的高度。这使得它在屏幕底部的可见 View 之外。然后在1秒内从这个位置滑到屏幕的centerY(0.0)。

但它现在所做的是从屏幕顶部滑动到屏幕的 centerY 并且同时它调整到左右边距,就像在第一个约束中设置的那样

self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[view]-10-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":questionView]))

我现在完全糊涂了,希望我的解释能有所帮助,希望有人有想法。

谢谢!

最佳答案

因为我不知道你的 View 是如何从你的包中创建的,所以我已经根据你的代码拼凑了一个简单的例子。

关键是 self.view.layoutIfNeeded() 被调用了两次。添加 View 后一次,第二次在动画 block 中。并且约束的修改不在动画 block 内。

import UIKit

class ViewController: UIViewController {

    var yConstraint:NSLayoutConstraint?

    override func viewWillAppear(_ animated: Bool) {

        self.createView()

        self.view.layoutIfNeeded()

        self.yConstraint?.constant = 32
        UIView.animate(withDuration: 1.0) {
            self.view.layoutIfNeeded()
        }

    }

    func createView(){

        let questionView = UIView()
        questionView.backgroundColor = UIColor.red

        let heightConstraint = NSLayoutConstraint(item: questionView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: self.view.bounds.height-64)
        questionView.addConstraint(heightConstraint)

        self.view.addSubview(questionView)

        questionView.translatesAutoresizingMaskIntoConstraints = false

        //Horizontal orientation
        self.view.addConstraints(
            NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[view]-10-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":questionView]))

        yConstraint = NSLayoutConstraint(item: questionView,
                                         attribute: .top,
                                         relatedBy: .equal,
                                         toItem: self.view,
                                         attribute: .top,
                                         multiplier: 1,
                                         constant: CGFloat(UIScreen.main.bounds.height))
        self.view.addConstraint(yConstraint!)
    }
}

关于ios - 以编程方式添加后,使用约束为 UIView 设置动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42447423/

相关文章:

ios - 通过 instagram API 删除 instagram 媒体上的评论

ios - Application.Current.properties 在最新的 xamarin 表单版本中被破坏了吗?

android object animator transition 和 alpahn

ios - UIView组动画

javascript - 如何在 css 关键帧中存储内容或元数据?

ios - 如何在 Swift 中使用自动布局设置可重用 UIView 的约束?

MySQL 更新唯一约束

ios - 隐藏 View 的视觉约束

ios - 加载指定初始化程序核心数据失败

objective-c - Objective-C : How to fix aspect ratio of image (and not change to fit imageview frame)