![](/img/trans.png)
[英]Updating Frame/Constraints for programmatically added UIView on orientation change
[英]Animate UIView with constraints after it was added programmatically
我有一个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]))
}
多数民众赞成,视图在视图控制器的(0,0)左右两侧添加了所需的空间。
我想要实现的是视图从视图控制器的底部动画到中心,然后从中心到顶部进行动画制作。 首先,我试图将它设置为动画,使其从当前位置(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)
})
那么视图位于中心,但它不是动画。 它直接跳到它。
我搜索并找到了很多答案,说我必须设置约束的常量,然后调用layoutIfNeeded()
但所有这些示例都使用对之前设置为IBOutlet的约束的引用,我没有添加我的以编程方式查看。
如何正确地为视图设置动画,从底部到中心然后从中心到顶部?
谢谢你!
问候
编辑1
好的,我会更进一步解释我想要实现的目标。 在我的视图控制器上,在向用户显示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方法实例化问题视图并为其分配约束
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()
}
在此之前,我将yConstraint定义为Duncan C建议的实例变量,如下所示:
var yConstraint:NSLayoutConstraint?
所以我对现在的期望是:
创建问题视图,它的中心位于视图控制器的中心+屏幕的高度。 这使它在屏幕底部的可见视图之外。 然后它在1秒内从该位置滑动到屏幕的中心Y(0.0)。
但它现在做的是,从屏幕顶部滑动到屏幕的中心Y,同时它调整到左右边距,就像它在第一个约束中设置一样
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[view]-10-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":questionView]))
我现在完全糊涂了,希望我的解释有所帮助,有人有个主意。
谢谢!
由于我不知道您的视图是如何从您的软件包中创建的,因此我根据您的代码将一个快速示例混合在一起。
关键是self.view.layoutIfNeeded()
被调用两次。 一旦添加了视图,第二次在动画块中。 并且约束的修改不在动画块内。
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!)
}
}
创建约束并将其保存在实例变量中。 然后,当您想要为其设置动画时,更改约束上的常量并从动画块调用layoutIfNeeded,就像为动画基于故事板的约束设置动画一样。
在你的情况下,不要在你的函数中使用let constraint = ...
相反,使用:
var centerConstraint: NSLayoutConstraint?
在viewWillAppear中:
centerConstraint = NSLayoutConstraint(item: myView,
attribute: .centerY,
relatedBy: .equal,
toItem: self.view,
attribute: .centerY,
multiplier: 1,
constant: CGFloat(0.0))
self.view.addConstraint(center)
当你想要动画时:
UIView.animate(withDuration: 1.0,
animations:
{
centerConstraint.constant = newValue //(Your value here.)
myView.layoutIfNeeded()
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.