How to Use Auto Layout to Move Other Views When a View Is Hidden

How to use Auto Layout to move other views when a view is hidden?

It is possible, but you'll have to do a little extra work. There are a couple conceptual things to get out of the way first:

  • Hidden views, even though they don't draw, still participate in Auto Layout and usually retain their frames, leaving other related views in their places.
  • When removing a view from its superview, all related constraints are also removed from that view hierarchy.

In your case, this likely means:

  • If you set your left view to be hidden, the labels stay in place, since that left view is still taking up space (even though it's not visible).
  • If you remove your left view, your labels will probably be left ambiguously constrained, since you no longer have constraints for your labels' left edges.

What you need to do is judiciously over-constrain your labels. Leave your existing constraints (10pts space to the other view) alone, but add another constraint: make your labels' left edges 10pts away from their superview's left edge with a non-required priority (the default high priority will probably work well).

Then, when you want them to move left, remove the left view altogether. The mandatory 10pt constraint to the left view will disappear along with the view it relates to, and you'll be left with just a high-priority constraint that the labels be 10pts away from their superview. On the next layout pass, this should cause them to expand left until they fill the width of the superview but for your spacing around the edges.

One important caveat: if you ever want your left view back in the picture, not only do you have to add it back into the view hierarchy, but you also have to reestablish all its constraints at the same time. This means you need a way to put your 10pt spacing constraint between the view and its labels back whenever that view is shown again.

iOS: layout constraint with hidden views

I'm setting this up in storyboard

Basically, you can't. You will have to use code to manage these constraints. When you hide Label2, also swap out the first set of constraints and swap in the second ones. When you show Label2, also swap out the second set of constraints and swap in the first ones. This is perfectly standard procedure.

In fact, I have an example project that effectively shows how to do exactly what you're describing:

https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch01p032constraintSwapping/ConstraintSwapping/ViewController.swift

As you can see, we configure in advance the constraints for when the view v2 is present and for when it is absent, and just swap them when we remove or reinsert v2.

AutoLayout with hidden UIViews?

UIStackView is probably the way to go for iOS 9+. Not only does it handle the hidden view, it will also remove additional spacing and margins if set up correctly.

What happens with constraints when a view is begin to be hidden?

Normally, hiding a view (by setting isHidden) has no effect on layout. Hidden views participate in layout. Any constraints connected to the view are still enforced. The area occupied by the now-hidden view is still reserved for it.

This is useful because it allows you to use hidden views as “spacers” to create layouts (in Interface Builder) that you cannot otherwise create. (In code, you can use UILayoutGuides instead of hidden views, but IB doesn't support creating layout guides.)

UIStackView is different from other views. UIStackView observes the isHidden property of each of its arranged subviews. When an arranged subview's isHidden changes, the UIStackView updates constraints to make or remove the area used by that subview.

No other view does what UIStackView does, so no other view adjusts the layout of its subviews when they become hidden or visible.

Auto layout how to hide 1 view in a view with 3 equal width views

If the deployment target is iOS9 or later, it is recommended to use UIStackView as the enclosing view. Setting isHidden to true on any view arranged in the UIStackView will not only make the view hidden, but also will the stack view re-organize all the non-hidden views to fill up the space that was taken by the hidden views. This behavior could be tuned by adjusting distribution on UIStackView.


Tj3n's answer works, but it has a drawback that you have to use magic numbers in your code and set constraint properties both in code and IB.

IMHO, a better solution would be setting up all the constraints in IB with different priorities and activating/deactivating them in code. Try this:

  1. Set the leading/trailing constraints as you did before.
  2. Set equal width constraints for all three views with priority high.
  3. Set 0 width constraints for all three views with priority required, but leave them deactivated in IB. And connect them to IBOutlets in code just as connecting views.
  4. Activate any of the 0 width constraints to collapse the view you want, and later deactivate them to expand.

Note that just with 1 and 2 in place, you can achieve the equal-width view layout. And with 3 and 4, you can collapse/expand any of the views selectively.

Using Auto layout with hidden views

First get the Top Space to SuperView NSlayoutConstraints Outlets for both subViews and then do the following:-

[self.aView setHidden:YES];
if([self.aView isHidden])
{
self.bViewTopConstraint.constant = self.aViewTopConstraint.constant;
}

using this the second UiView will go to the place of first UIView.

For Scrollview you have to set the constraints value properly. No need to set any contentsize. Once you set the constriants scrollview will work automatically.
Check the attached screenshot.

Sample Image

Hiding a UIView using AutoLayout constraints

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.

Sample Image

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.



Related Topics



Leave a reply



Submit