Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure different layouts for Portrait and Landscape Orientations using Auto Layout?

I have a view like in attached image

enter image description here

Now I am adding constraints such that the UITextview in the view has to be on the right hand side of the screen when orientation is changed to landscape. On UItextview, I have added below constraints,

  1. Trailing Space to : Superview
  2. Bottom Space to : Superview

These constraints though displayed some warnings on ambugity, did the job for me. Below is the screenshot of landscape mode.

enter image description here

My problem is though the UItextview is moved to right side, I want some additional width from top of superview when it is in landscape mode. In other words, I want the UITextview to be moved a little downward from where it is now in landscape mode. I am pondering how to do that using auto layout in IB and I am not able to figure that how.

Any suggestions please.

like image 417
slysid Avatar asked Dec 19 '13 14:12

slysid


1 Answers

You can do this with constraints in several ways, but there's no way to do this automatically with just constraints you make in IB. By using both the multiplier and constant values in the method, constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:, you can have one constraint that evaluates to different distances in portrait and landscape. It's a pain to do the calculations to figure out what to use for those values, so I've written a category on NSLayoutConstraint to do that. An example of one of those methods, is this:

+(NSLayoutConstraint *)topConstraintForView:(UIView *)subview viewAttribute:(NSLayoutAttribute) att superview:(UIView *)superview portraitValue:(CGFloat)pValue landscapeValue:(CGFloat)lValue {
    CGFloat multiplier = (pValue - lValue)/(superview.bounds.size.height - superview.bounds.size.width);
    CGFloat constant = pValue - (superview.bounds.size.height * multiplier);
    NSLayoutConstraint *con = [NSLayoutConstraint constraintWithItem:subview attribute:att relatedBy:0 toItem:superview attribute:NSLayoutAttributeBottom multiplier:multiplier constant:constant];
     NSLog(@"top coeffs: %f   %f",multiplier,constant);
    return con;
}

The way you use these, is to add the starting portrait constraint in the storyboard, but check the box, "Placeholder - Remove at build time" in the attributes inspector for the constraint, and then replace it in viewDidLoad, like this:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addConstraint:[NSLayoutConstraint topConstraintForView:self.textView viewAttribute:NSLayoutAttributeTop superview:self.view portraitValue:225 landscapeValue:50]];
}

This will automatically adjust the position of the text view based on the rotation of the device without any further code. You might have to change the width of the text fields to get everything to fit properly -- I enclosed them and the "Get" labels in a view to more easily position them as a group. That view and the text view had height and width constraints, as well as top and left for the view, and top and right for the text view. The category has methods to adjust the other constraints as well, and can be found at http://jmp.sh/b/S4exMJBWftlCeO5GybNO.

The other way to do this, is to make IBOutlets to the constraints you make in IB, and adjust them (the constant value), or delete some and remake other ones, in one of the rotation callback methods.

like image 52
rdelmar Avatar answered Oct 19 '22 23:10

rdelmar