If I set:
stackView.distributon = .fillProportionally
Then on iOS 11 I get a very weird animation when loading a view that contains this stack view (all subviews - not just stack view - are flying from the top or bottom of the screen). On lower iOS version everything works fine. If I set the stack view's distribution to anything else, everything works fine as well.
Does anyone have any idea what could be a cause of this problem?
Thank you.
I think I've found a fix - call self.view.layoutIfNeeded()
in the animations
block.
Here's my reproduction:
import UIKit
class ViewController: UIViewController {
var showB = true
weak var viewB: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let viewA = UIView()
viewA.backgroundColor = UIColor.green
let toggleViewBButtonAnimated = UIButton(frame: CGRect(x: 50, y: 150, width: 200, height: 40))
toggleViewBButtonAnimated.backgroundColor = UIColor.cyan
toggleViewBButtonAnimated.setTitle("Toggle B (animated)", for: .normal)
viewA.addSubview(toggleViewBButtonAnimated)
toggleViewBButtonAnimated.addTarget(self, action: #selector(toggleBButtonTappedAnimated), for: .touchUpInside)
let viewB = UIView()
viewB.backgroundColor = UIColor.orange
let viewBHeightConstraint = viewB.heightAnchor.constraint(equalToConstant: 200)
viewBHeightConstraint.priority = 999
viewBHeightConstraint.isActive = true
self.viewB = viewB
let stackView = UIStackView(arrangedSubviews: [viewA, viewB])
stackView.axis = .vertical
stackView.alignment = .fill
stackView.distribution = .fill
stackView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(stackView)
stackView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
}
@IBAction func toggleBButtonTappedAnimated() {
self.showB = !self.showB
UIView.animate(withDuration: 0.3,
animations: { self.viewB.isHidden = !self.showB; self.view.layoutIfNeeded() }
)
}
}
This controller sets up a UIStackView
that has two vertical views, a green one (A) and an orange one (B). Tapping the button hides/unhides view B.
If I do not have self.view.layoutIfNeeded()
in the animations
block, then, when view B is being shown, it flies in from the top of the screen. (When view B is being hidden, it hides normally - moving down off the bottom of the screen.)
When I added self.view.layoutIfNeeded()
to the animations
block, view B shows as expected - it comes up from the bottom of the screen.
Thanks to an answer from @g3rv4 for pointing me in this direction!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With