当我们使用 frame 布局控件的时候,如果控件的 frame 发生改变时,我们想让改变产生动画过渡效果,而不是生硬的直接改变。我们可以使用 UIView 的 animate(withDuration:animations:completion:)
函数来实现,如下面的代码:
UIView.animate(withDuration: 0.5) {
// 改变后的frame
self.exampleView.frame = CGRect(x: 10, y: 10, width: 100, height: 100)
}
那当我们使用 AutoLayout 布局的时候,我们想实现上面的效果该如何写呢?
通过下面的两个步骤我们就可以实现:
- 改变目标控件约束
- 调用
animate(withDuration:animations:completion:)
函数- 调用目标控件父视图的
layoutIfNeeded()
函数
- 调用目标控件父视图的
具体例子
声明全局变量
private let exampleView = UIView(frame: .zero)
private var topConstraint = NSLayoutConstraint()
使用 AutoLayout 布局控件
extension ViewController {
private func setupSubviews() {
exampleView.backgroundColor = .green
view.addSubview(exampleView)
exampleView.translatesAutoresizingMaskIntoConstraints = false
topConstraint = exampleView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100)
topConstraint.constant = 100
NSLayoutConstraint.activate([
topConstraint,
exampleView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 100),
exampleView.widthAnchor.constraint(equalToConstant: 100),
exampleView.heightAnchor.constraint(equalToConstant: 100)
])
let button = UIButton(type: .custom)
button.frame = CGRect(x: 100, y: 400, width: 100, height: 50)
button.backgroundColor = .red
button.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside)
view.addSubview(button)
}
}
动画改变约束
extension ViewController {
@objc func buttonAction(_ sender: UIButton) {
// 修改约束
topConstraint.constant = 200
//调用父视图的 layoutIfNeeded()
UIView.animate(withDuration: 0.5) {
self.view.layoutIfNeeded()
}
}
}
注意事项
- 在要调用目标控件的
父视图
的layoutIfNeeded()
函数 - 注意调用的是
layoutIfNeeded()
函数,不是setNeedsLayout()
- 参考