你想要的其实很简单,我将详细说明应该如何完成它,而不会弄乱优先级或时髦的常量。这样我们就可以获得适用于任何屏幕尺寸的动画。
TL;DR 是您需要配置约束,然后在动画块内调用 layoutIfNeeded 以动画化更改。更多see this SO post.
所以我们需要两组约束来隐藏和显示视图。在viewDidLoad 中,视图将被隐藏,然后在viewDidAppear 或我们希望该视图滑入的任何位置。
故事板/XIB 设置
所以第一件事是配置在 IB 中不会改变的约束(或代码,无论你喜欢哪个)。即;红色视图的高度,以及它到容器的前导和尾随空间。所以你的约束可能看起来像这样(注意:我没有设置宽度约束,但让前导和尾随空格定义宽度):
现在您将看到 IB 会警告您没有为视图的 Y 位置配置约束(因此是红色虚线)
您现在可以将顶部空间添加到容器约束并将其设置为占位符约束(显示“在构建时删除”的复选框)。我们这样做是因为我们想以编程方式控制视图的位置。
这意味着一旦加载视图,此约束将不存在,但用于删除所有警告,因为您告诉 IB 您知道如何在加载视图时处理此约束。
编码时间
现在我们需要一个隐藏视图的方法,一个显示视图的方法。为此,我们将在视图上存储 Y 定位约束,然后对其进行动画处理。我们的 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)
}
显示
同样,我们的显示约束将视图的中心 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
}
}
您还可以使用一些 CGRect 数学检查红色视图是否可见:
func isRedViewVisible() -> Bool {
return CGRectContainsPoint(self.view.bounds, self.redView.frame.origin)
}