26

Auto Layout, as good as it is, driving me crazy with constraints. I have the portrait mode designed in IB but I can't get the desired landscape orientation to work.

layout

Notice that when the orientation changes to landscape, the spacing between the UIImageView blocks decreases and the text alignment of SAMPLE TEXT changes to right aligned.

Currently, I have added a few constraints for it to work. However, I need to keep the space between UIImageView blocks fixed, as a result of which it looks cramped up in portrait and fine in landscape. I need it to be spread out evenly in portrait and compress in landscape (like in image above). Similarly, currently my constraints bring up the text but it doesnot keep it at the center of screen and right aligned.

Is this possible at all with Auto Layout? If so, how? Help greatly appreciated.

Community
  • 1
  • 1
Gaurav Wadhwani
  • 1,312
  • 2
  • 14
  • 30
  • For achieving flexible spacing maybe useful next questions: http://stackoverflow.com/questions/17089427/ios-autolayout-vertically-equal-space-to-fill-parent-view and http://stackoverflow.com/questions/13680303/ios-auto-layout-equal-spaces-to-fit-superviews-width – Mikhail Aug 13 '13 at 16:28
  • To play with views constraint on runtime this will helpful [Runtime Change in Autolayout](http://stackoverflow.com/questions/27414052/moving-views-with-constraints/27420696#27420696) – Kampai Oct 07 '15 at 13:53

3 Answers3

12

There are several ways to approach this. One way is to enclose your 3 image views in a UIView. Give the top and bottom image views constraints to the top and bottom respectively, and give the middle one a centerY constraint. Give this enclosing view a fixed height and width, and a constraint to the top of the controller's view. Make an IBOutlet to the height constraint for this enclosing view, and change it on rotation. In the example below, I gave it a height of 350 in portrait:

-(void)updateViewConstraints {
    [super updateViewConstraints];
    if (self.view.bounds.size.height < self.view.bounds.size.width) {
        self.heightCon.constant = self.view.bounds.size.height;
    }else{
        self.heightCon.constant = 350;
    }
}

As for the label, the easiest way is to remove the constraints you have (bottom and centerX), and add trailing and centerY on rotation.

rdelmar
  • 102,832
  • 11
  • 203
  • 218
  • Sounds good. However, my view isn't responding to -(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration..I tried NSLog-ging the `interfaceOrientation` but nothing comes on output..So I have registered for orientation notification of device but that makes animation sluggish.. do you know why the view isn't responding to the method you mentioned – Gaurav Wadhwani Aug 13 '13 at 17:07
  • @GauravWadhwani, I don't know why that wouldn't be called. I changed my post to put the code in updateConstraints. See if that works. – rdelmar Aug 13 '13 at 17:11
  • That works, thanks a ton!!! Spent entire day on this. Will just add in the blocks and mark your answer in a moment. Thanks again :) – Gaurav Wadhwani Aug 13 '13 at 17:26
  • can't we do this using Xibs by avoiding writing above code? – Naga Mallesh Maddali Sep 10 '14 at 09:19
  • @NagaMalleshMaddali, yes, you could do this with xibs (and code to switch between them), but the question specifically asked whether it could be done with auto layout. – rdelmar Sep 10 '14 at 14:40
6

Yes, it can be done with Auto Layout. If you want the spacing between views to increase and/or decrease depending on orientation, you can use the Less Than or Equal or Greater Than or Equal relation (instead of Equal) for the constraint, which allows a distance to grow or shrink:

enter image description here

Play around with that and you should be able to get what you want.

mluisbrown
  • 12,738
  • 6
  • 50
  • 81
  • Thanks for your reply. I tried altering that constraint. But as soon as I change it to anything other than "Equal to", it gives me ambiguous layout warning for horizontal positioning. – Gaurav Wadhwani Aug 13 '13 at 16:28
  • You'll need to add other constraints to the top and bottom `UIImageView` so that using <= or >= in the constraints between them isn't ambiguous. – mluisbrown Aug 13 '13 at 16:30
  • I need the position of UIImage to be variable in vertical, so whatever constraint i add, it has be in the form of <= or =>. But xcode expects me to add atleast one constraint for vertical that is fixed. How can I add a fixed constraint and keep it flexible? – Gaurav Wadhwani Aug 13 '13 at 16:36
  • 1
    It's tricky. You'll have to experiment, including with the constraint priorities. But it will help if you try and think like Xcode and say "Given the constraints here, can I unambiguously position this view?". It's like solving a logic puzzle, and it's not always easy at first. – mluisbrown Aug 13 '13 at 16:42
2

Yes, it is definitely possible to do this with Auto Layout. Through a series of steps, that I think might be too long to post as an answer, you can retain the spacing between your ImageViews and keep the alignment of the text the same.

Essentially, you will have to pin a corner of each ImageView and remove some constraints so that it doesn't automatically compress the spacing when you change the orientation.

Full explanation on how to do this (pretty much exactly what you are asking for) is explained in this tuorial. You can find it about halfway through the page.

Hope this is what you were looking for.

CaptJak
  • 3,542
  • 1
  • 25
  • 48
  • Hey, currently the compression and text alignment aren't changing. I want the space to Compress and text alignment to change.. – Gaurav Wadhwani Aug 13 '13 at 16:17
  • Have you tried the link that I gave? Which space do you want to compress? It looks like, from your question, that you don't want them compressed in landscape. Do you actually want them compressed? – CaptJak Aug 13 '13 at 16:21
  • Yeah, I want the blocks to be spaced out in Portrait and compressed in landscape so that they fit the way shown in image. I tried the link earlier but couldn't resolve the issue. Will read again though :) – Gaurav Wadhwani Aug 13 '13 at 16:23