Objective: Apply a constraint based animation so that the UILabel changes height while maintaining its top anchor restraint.
Problem: The constraint and view update appropriately but there seems to be a timing discrepancy -- the height constraint changes first (as if from zero height), and not staying pinned to the top anchor constraint.
Thanks for any feedback or direction.
class ViewController: UIViewController {
private var button : UIButton = {
let button = UIButton()
button.backgroundColor = .red
button.setTitle("Hello", for: .normal)
button.setTitleColor(.white, for: .normal)
button.titleLabel?.textAlignment = .center
button.titleLabel?.font = .systemFont(ofSize: 24, weight: .bold)
button.setTitleColor(.white, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(changeConstraints), for: .touchUpInside)
return button
}()
private var label : UILabel = {
let label = UILabel()
label.backgroundColor = .blue
label.text = "This is my label"
label.font = .systemFont(ofSize: 34, weight: .semibold)
label.textAlignment = .center
label.textColor = .white
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private var animationCount = 0
private var labelHeightConstraint : NSLayoutConstraint = NSLayoutConstraint()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
}
func setupUI() {
view.addSubview(button)
view.addSubview(label)
// setting initial label height constraint
labelHeightConstraint = label.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.6)
labelHeightConstraint.isActive = true
NSLayoutConstraint.activate([
label.topAnchor.constraint(equalTo: view.topAnchor, constant: 10),
label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
button.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 20),
button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20),
button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
button.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
])
}
@objc func changeConstraints() {
print("changeConstraints method CALLED")
//count for animation state
animationCount += 1
UIView.animate(withDuration: 2.0) { [unowned self] in
if animationCount % 2 == 0 {
labelHeightConstraint.isActive = false
labelHeightConstraint = label.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.6)
button.setTitle("GoodBye", for: .normal)
button.backgroundColor = .purple
button.setTitleColor(.white, for: .normal)
} else {
labelHeightConstraint.isActive = false
labelHeightConstraint = label.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.2)
button.setTitle("Welcome Back", for: .normal)
button.backgroundColor = .green
button.setTitleColor(.black, for: .normal)
}
labelHeightConstraint.isActive = true
self.view.layoutIfNeeded()
}
}
}