Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hiding a UIView using AutoLayout constraints

From time to time I have a subview that I would like to remove from a layout. Not only should it be hidden, but it should not be considered part of the view's 'flow', so to speak. An example:

enter image description here

I am looking for a strategy to hide the orange view programmatically. The layout of the boxes, and their content, is via autolayout. Two things to note:

  • the orange box is defining its vertical height based on the content, plus some top/bottom offsets for margins. So, setting the labels' text to nil will only 'shrink' the view down to it's internal margins, it won't have a height of 0.
  • Similarly, the vertical spacing between the three boxes mean that even if the orange box's height is 0, the gap between red and yellow will be twice as large as required.

A possible solution

My best suggestion is to add a constraint to the orange box, setting it's height to 0. For this to work, I need to use non-required priorities for all of the vertical constraints inside the orange box. At the same time, the container should update the constant for the constraint that separates the boxes. I don't like this approach so much since the orange box class is defining it's internal constraints with it's superview's behavior in mind. Perhaps I could live with it if the orange box view instead exposes a 'collapse' method that adds the 0 height constraint itself.

Is there a better approach?

like image 948
Ben Packard Avatar asked Feb 03 '15 14:02

Ben Packard


People also ask

How do I use Autolayout constraints?

Auto Layout dynamically calculates the size and position of all the views in your view hierarchy, based on constraints placed on those views. For example, you can constrain a button so that it is horizontally centered with an Image view and so that the button's top edge always remains 8 points below the image's bottom.

How do I use Autolayout in Xcode?

To create constraints select the button and click the Align icon in the auto layout menu. A popover menu will appear, check both “Horizontal in container” and “Vertically in container” options to center the button on the screen. Then click the “Add 2 Constraints” button. Run the application.


2 Answers

You can do this by adding an extra constraint between the yellow and red views of a lower priority, and adjusting the priorities in code.

enter image description here

The short dashed constraint (orangeToRedCon is the outlet) has a priority of 999 (you can't change a required priority to a non-required, so that's why it's not 1000). The long dashed constraint (yellowToRedCon) has a priority of 500 and a constant of 20. In code, you can hide the orange view, and swap those priority levels, and that will cause the yellow view to move up to whatever value you've set for the constant value of yellowToRedCon.

-(void)changePriorities {     self.yellowToRedCon.priority = 999;     self.orangeToRedCon.priority = 500;     [UIView animateWithDuration:.5 animations:^{         self.orangeView.alpha = 0;         [self.view layoutIfNeeded];     }]; } 

This method doesn't require any changes in the orange view's height.

like image 164
rdelmar Avatar answered Sep 26 '22 12:09

rdelmar


In iOS 9 you can use UIStackView for this. There also are polyfills for older versions: TZStackView and OAStackView

like image 28
fabb Avatar answered Sep 22 '22 12:09

fabb