Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autolayout causing UI Elements to "snap" into place at runtime?

I have a UIView with a UIImageView at the very top, a UILabel below it, a UIButton below that, and a UISegmentedControl that determines what determines what embedded UIview to display at the bottom (which also a choice to not show any at all).

I've run into the problem where I've set up all of my constraints in the interface builder, and everything seems to be fine when I switch between screen sizes in the storyboard. However when I actually run the project on a device or emulated, the UIimage at the top is briefly stretched before "snapping" into a size the fits the constraints. Also, it seems as if the label disappears for a brief second and reappears after the image has snapped into a size. After the "snap" has occurred, everything is in place and there are no problems.

This snapping occurs both when testing on a 4 and 3.5 inch display. I find this odd because I've designed the UI for the 4inch screen perfectly.

Does anyone know why this is happening?

Edit Here's whats the constraints look like in IB.

Constraints

like image 357
p0ny Avatar asked Aug 10 '14 18:08

p0ny


1 Answers

This is potentially due to adjustments that you might be making to your UI elements (or constraints) from the view controller in code. For example, if you are programmatically setting a different UIImage into your UIImageView, and this code is happening too late in the view lifecycle (for example, in viewDidAppear) after a layout pass has already calculated view positions and sizes, then you will see a visible snap as views take on new positions based on the new intrinsic content size of the image view.

This could be caused by other adjustments such as injecting a localized string into a UILabel in code, which causes the label to have a smaller or larger intrinsic content size, which in turn affects the layout based on your constraints.

If you are making adjustments to your UI in code, make sure they are happening in viewDidLoad or viewWillAppear: so that they occur before the view's initial layout pass (and the view's animation onscreen).

If you're still seeing issues, you can try explicitly forcing an immediate layout pass to occur on the view controller's view at the end of viewWillAppear: by doing the following:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [self.view setNeedsLayout];
    [self.view layoutIfNeeded]; // forces an immediate layout pass
}
like image 143
smileyborg Avatar answered Sep 20 '22 11:09

smileyborg