Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing Auto Layout constant doesn't update its frame

I've created a little info view I'd like to add as a subview to a UIVisualEffectView. On my info view I created a free form xib and used Auto Layout for all the UILabels and one UIButton. The goal here is that Start, Pull and Sled are all optional so if that data doesn't exist I want to collapse those UILabels. I've accomplished this by updating their equal height constraint to 0.

my problem is when some or all of those optional UIlabels collapse I want to update the UIView's frame's height so things are tidy and don't potentially have gaps.

enter image description here

I do the below to update the constraints I've tagged in IB.

    for view in self.view.subviews {
        for constraint in view.constraints {
            if let identity = constraint.identifier {
                if labelTags.contains(identity) {
                    print("Before: \(view.frame)")
                    constraint.constant = labelHeight
                    view.setNeedsUpdateConstraints()
                    print("After: \(view.frame)")
                }
            }
        }
    }

Before: (5.0, 101.0, 50.0, 25.0)
After: (5.0, 101.0, 50.0, 25.0)
Before: (58.0, 101.0, 101.0, 25.0)
After: (58.0, 101.0, 101.0, 25.0)
Before: (5.0, 129.0, 39.0, 25.0)
After: (5.0, 129.0, 39.0, 25.0)
Before: (47.0, 129.0, 23.0, 25.0)
After: (47.0, 129.0, 23.0, 25.0)
Before: (5.0, 157.0, 45.0, 25.0)
After: (5.0, 157.0, 45.0, 25.0)
Before: (53.0, 157.0, 63.0, 25.0)
After: (53.0, 157.0, 63.0, 25.0)

After the constraints are updated I attempt to determine the view's frame by loops the views subview and get the max height like so:

    var height:CGFloat = 0.0
    for v in self.view.subviews {
        if (v.frame.origin.y + v.frame.size.height) > height {
            height = (v.frame.origin.y + v.frame.size.height)
        }
    }

    self.frame.size.height = height

On first load getting the new frame height doesn't work because the UILabels frames don't update after updating their constraints. Here is the kicker, the same code runs on orientation change and it works! When I rotate back to portrait all my UILabels are lined up nicely and the UIView is pulled up snuggly under the UIButton!

Any direction would be greatly appreciated, I've been at this for two days. Thanks!

UPDATE:

self.view.layoutIfNeeded() was indeed the winner! In my case timing was everything.

I have never have paid that close attention but the below appear to be more of a 'suggestion' to the OS where as layoutIfNeeded() is immediate.

self.view.setNeedsUpdateConstraints()
self.view.setNeedsLayout()
self.view.setNeedsDisplay()
like image 413
kev Avatar asked May 12 '16 02:05

kev


1 Answers

Call layoutIfNeeded(), which will force a redraw on the views that have AutoLayout constraint changes. It will also call viewDidLayoutSubviews, so you can do any additional work there.

like image 149
Siriss Avatar answered Nov 16 '22 02:11

Siriss