如何在Swift中用约束animationUIView?

在我devise的例子中,我有以下一个观点:

在这里输入图像说明

正如你所看到的,它包含一些简单的约束:

  1. alignment水平和垂直中心,
  2. 高度(设置为常量)
  3. 前后空格(设置为常量)

我想要达到的是从顶部看这个微红/粉红色的视angular。 传统上,在一个约束更less的世界里,我只是简单的修改UIView.animateWithDuration里面的UIView.animateWithDuration ,但是我不确定我是如何在约束世界中做类似的。

为了重申我的问题,我怎样才能使我的观点从现实中跳出来,并使从上到下的观点animation化?

我已经考虑了垂直中心约束的animation(后来调用layoutIfNeeded ),但是没有达到预期的效果。

谢谢你的帮助。

你可以做的是在你的viewDidAppear方法中添加下面的代码。 您首先创build视图的中心Y约束的IBOutlet属性,然后更改其常量值。

 self.centerYConstraint.constant = 500.0 self.view.layoutIfNeeded() UIView.animateWithDuration(Double(0.5), animations: { self.centerYConstraint.constant = 0 self.view.layoutIfNeeded() }) 

你想要的其实是相当简单的,我会详细说明应该如何做,而不是搞乱优先级或时髦的常量。 这样我们可以得到一个可以在任何屏幕尺寸上工作的animation。

TL; DR是您需要configuration您的约束,然后调用您的animation块中的layoutIfNeededanimation的变化。 欲了解更多, 请参阅此SOpost 。

所以我们需要两套约束来隐藏和显示视图。 在viewDidLoad ,视图将被隐藏,然后在viewDidAppear或者我们希望该视图滑入的任何地方。

故事板/ XIB设置

因此,首先要configuration在IB(或代码,无论哪个方面都适合)中不会改变的约束条件。 即; 红色视图的高度,以及容器的前后空间。 所以你的约束可能看起来像这样( 注:我没有设置宽度约束,但让前导和尾随空格定义宽度):

约束

现在您会看到IB会警告您没有为视图的Y位置configuration约束(因此红色虚线)

查看警告

您现在可以将顶部空间添加到容器约束,并将其设置为占位符约束(checkbox“生成时删除”)。 我们这样做是因为我们想要控制视图的编程方式。

在这里输入图像说明

这意味着一旦视图被加载,这个约束就不存在,而是用来消除所有的警告,因为你告诉IB你在加载视图的时候知道如何处理这个约束。

编码时间

现在我们需要一种方法来隐藏视图,一种显示视图的方法。 为此,我们将在视图上存储Y定位约束,然后对其进行animation处理。 我们的viewController可能是这样的:

 @IBOutlet weak var redView: UIView! var redViewYPositionConstraint: NSLayoutConstraint? override func viewDidLoad() { super.viewDidLoad() self.hideRedViewAnimated(false) } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) self.showRedViewAnimated(true) } 

我们隐藏视图的方法可以简单地删除位置约束,然后添加一个红色视图底部等于视图控制器的视图顶部:

 func hideRedViewAnimated(animated: Bool) { //remove current constraint self.removeRedViewYPositionConstraint() let hideConstraint = NSLayoutConstraint(item: self.redView, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: 0) self.redViewYPositionConstraint = hideConstraint self.view.addConstraint(hideConstraint) //animate changes self.performConstraintLayout(animated: animated) } 

显示

同样,我们的show约束会将视图的中心Y移动到控制器中心Y:

 func showRedViewAnimated(animated: Bool) { //remove current constraint self.removeRedViewYPositionConstraint() let centerYConstraint = NSLayoutConstraint(item: self.redView, attribute: .CenterY, relatedBy: .Equal, toItem: self.view, attribute: .CenterY, multiplier: 1, constant: 0) self.redViewYPositionConstraint = centerYConstraint self.view.addConstraint(centerYConstraint) //animate changes self.performConstraintLayout(animated: animated) } 

便利方法

为了完整性,我使用的便利方法如下所示:

 func performConstraintLayout(animated animated: Bool) { if animated == true { UIView.animateWithDuration(1, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.6, options: .BeginFromCurrentState, animations: { () -> Void in self.view.layoutIfNeeded() }, completion: nil) } else { self.view.layoutIfNeeded() } } func removeRedViewYPositionConstraint() { if redViewYPositionConstraint != nil { self.view.removeConstraint(self.redViewYPositionConstraint!) self.redViewYPositionConstraint = nil } } 

你也可以使用CGRectmath来检查红色视图是否可见:

 func isRedViewVisible() -> Bool { return CGRectContainsPoint(self.view.bounds, self.redView.frame.origin) } 

尝试这个:

 class ViewController: UIViewController { // red view @IBOutlet weak var myView: UIView! // vertical align contraint @IBOutlet weak var verticalConstraint: NSLayoutConstraint! override func viewDidLoad() { super.viewDidLoad() verticalConstraint.constant = (myView.bounds.height + self.view.bounds.height)/2 } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) self.view.layoutIfNeeded() UIView.animateWithDuration(0.5) { self.verticalConstraint.constant = 0 self.view.layoutIfNeeded() } } } 

在约束中要注意firstItemsecondItem顺序。 上面的代码假设Superview是第一个项目:

截图


另一种方法是定义两个约束:

  • 中心Yalignment约束 (Superview.CenterY == View.CenterY)优先级= 750
  • 垂直空间约束 (SuperView.Top == View.Bottom)priority = 500

截图

并调整优先顺序以确定应该采取哪种限制措施。

 class ViewController: UIViewController { // vertical align contraint @IBOutlet weak var centerYConstraint: NSLayoutConstraint! override func viewDidLoad() { super.viewDidLoad() centerYConstraint.priority = 250 } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) self.view.layoutIfNeeded() UIView.animateWithDuration(0.5) { self.centerYConstraint.priority = 750 self.view.layoutIfNeeded() } } } 

对于任何寻找像请求这样的简单animation的人,请查看我在GitHub上关于在Swift中如何animationUIview的示例。

我希望它可以帮助某人,为原来的请求看第三个animation(向上滑动animation)。

对于向上滑动animation,您需要使用CGAffineTransformMakeTranslation(x,y)

原因是,对于一个向上滑动的animation,你需要首先将视图移出屏幕,然后将其恢复到原来的位置。 所以在你的viewDidLoad中只需使用:

 yourView.transform = CGAffineTransformMakeTranslation(0, 500) 

这将视图从屏幕移出,在这种情况下在底部。 现在在viewDidAppear你可以显示你的观点:

 UIView.animateWithDuration(0.7, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: [], animations: { self.yourView.transform = CGAffineTransformMakeScale(1, 1) }, completion: nil) 

使用这些行,你可以在你的UIView上添加你想要的约束,并把它放在你的ViewController所需要的地方。

对于我来说Swift 3&4的最佳animation

 self.constraint.constant = -150 UIView.animate(withDuration: 0.45) { [weak self] in self?.view.layoutIfNeeded() }