如何在Swift中用约束animationUIView?
在我devise的例子中,我有以下一个观点:
正如你所看到的,它包含一些简单的约束:
- alignment水平和垂直中心,
- 高度(设置为常量)
- 前后空格(设置为常量)
我想要达到的是从顶部看这个微红/粉红色的视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() } } }
在约束中要注意firstItem
和secondItem
顺序。 上面的代码假设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() }