Reputation: 154
Numerous tutorials on animating AutoLayout constraints suggest to update constant property of a constraint and then call layoutIfNeeded()
in animation block.
My situation is a bit tricky. I have a view that houses 3 subviews. The height of this superview is not fixed - it is calculated as a sum of heights of its subviews. On some event, I ask one of those 3 subviews to toggle its height (it changes between 0 and 30, i.e. I want to smoothly hide and show it). The code is similar to this:
// In superview
subview1.isVisibleInContext = !subview1.isVisibleInContext
// In subview
class MySubview: UIView {
@IBOutlet var heightConstraint: NSLayoutConstraint!
var isVisibleInContext = false {
didSet {
updateHeight()
}
}
func toggleHeight() {
let newHeight = isVisibleInContext ? 30 : 0
layoutIfNeeded()
heightConstraint.constant = newHeight
UIView.animate(withDuration: 0.8) {
self.layoutIfNeeded()
}
}
}
Unfortunately, this does not work as I expect. I can see the smooth change of the height of my subview, but the height of my superview is recalculated immediately after I set the new value for my subview height constraint.
I want to see the height of the superview gradually increasing/decreasing as on of its subviews grows or decreases.
Please someone point me in the right direction. Any help is appreciated.
Thanks a lot!
Upvotes: 1
Views: 2813
Reputation: 154
The first thing, that was incorrect in my approach was executing self.layoutIfNeeded()
. Having investigated the issue I learned out that I had to execute it on the superivew, like this:
self.superview?.layoutIfNeeded()
That also didn't work out for a reason. The main issue in this case was that the view, which had 3 subviews inside was itself a subview of view. So to make it work I had to use the following code:
self.superview?.superview?.layoutIfNeeded()
Definitely not good that subview has to know the hierarchy of views, however it works.
Upvotes: 1
Reputation: 27620
The animation block should be in the UIView
that contains the 3 MySubviews
. Inside the MySubview
class you only update the height constraint's constant:
In Subview
func toggleHeight() {
let newHeight = isVisibleInContext ? 30 : 0
heightConstraint.constant = newHeight
}
Then in the UIView
that contains the 3 MySubviews
you animate the change:
In Superview
func toggleHeight(with subview: MySubview) {
subview.toggleHeight()
UIView.animate(withDuration: 0.8) {
self.view.layoutIfNeeded()
}
}
Upvotes: 6