使用 storyboard, xib 创建的视图, 视图的约束是用的 Autolayout , 所以实现动画效果也要通过改变约束的值,而不是直接改变 frame
示例: 在控制器上添加一个 blueView, blueView 上添加一个 greenView, 现改变 blueView 的宽度实现动画效果
将 blueView 的宽度拉成属性 BlueView_Width, 改变 BlueView_Width 的 constant 值, 然后在UIView.animate 中添加 strongSelf.view.layoutIfNeeded(), 更新controller View 的子视图布局, 不添加的 strongSelf.view.layoutIfNeeded() 没有动画效果
blueView 是 View 的子视图, blueView 的宽度改变时, view 的 viewWillLayoutSubviews 会执行
@IBOutlet weak var blueView: UIView!
@IBOutlet weak var greenView: UIView!
@IBOutlet weak var BlueView_Width: NSLayoutConstraint!
let blueWidth = BlueView_Width.constant + 10
BlueView_Width.constant = blueWidth
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.8, options: .curveEaseIn, animations: { [weak self] in
if let strongSelf = self {
strongSelf.view.layoutIfNeeded()
}
}, completion: nil)
view 的 viewWillLayoutSubviews 不会执行
错误:
blueView 的宽度改变了, 但是 greenView 的宽度没有随着改变
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.8, options: .curveEaseIn, animations: { [weak self] in
if let strongSelf = self {
let blueWidth = strongSelf.blueView.frame.width + 10
strongSelf.blueView.frame.size.width = blueWidth
strongSelf.view.layoutIfNeeded()
}
}, completion: nil)
因为 blueView 和 greenView 的约束是通过 Autolayout 创建的, 所以改变 blueView frame 时, 它的子视图并不会随之改变, view 的 viewWillLayoutSubviews 不会执行, 要让 greenView 宽度改变, 需要改变 greenView 的 frame
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.8, options: .curveEaseIn, animations: { [weak self] in
if let strongSelf = self {
let blueWidth = strongSelf.blueView.frame.width + 10
strongSelf.blueView.frame.size.width = blueWidth
strongSelf.greenView.frame.size.width = 70
strongSelf.view.layoutIfNeeded()
}
}, completion: nil)
如果使用 blueView 的 layoutIfNeeded() 方法, 需要写在改变 greenView 宽度之前, 写在之后没有效果
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.8, options: .curveEaseIn, animations: { [weak self] in
if let strongSelf = self {
let blueWidth = strongSelf.blueView.frame.width + 10
strongSelf.blueView.frame.size.width = blueWidth
strongSelf.blueView.layoutSubviews()
strongSelf.greenView.frame.size.width = 70
}
}, completion: nil)