I have a situation where viewControllerA
pushes viewControllerB
onto the navigation stack. When the user rotates the screen and the orientation of
Constraints can be made in such a way that the position and size of views can change automatically (no checking on the orientation) when the bounds of the superview change. If you make the constraints this way, then the view will have the proper arrangement on rotation regardless of whether the view was on screen at the time of the rotation or not.
Constraints have the form y = m*x + b
where y and x are two views, m is the multiplier, and b is the constant. It requires doing a bit of math to figure out what values of m and b will give you the constraints you want. I've made a category on NSLayoutConstraint that allows you to directly specify what values you want for portrait and landscape. You can use it like this,
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addConstraint:[NSLayoutConstraint widthConstraintForView:self.rectangle superview:self.view portraitValue:100 landscapeValue:200]];
[self.view addConstraint:[NSLayoutConstraint heightConstraintForView:self.rectangle superview:self.view portraitValue:150 landscapeValue:80]];
[self.view addConstraint:[NSLayoutConstraint topConstraintForView:self.rectangle viewAttribute:NSLayoutAttributeTop superview:self.view portraitValue:200 landscapeValue:10]];
[self.view addConstraint:[NSLayoutConstraint leftConstraintForView:self.rectangle viewAttribute:NSLayoutAttributeLeft superview:self.view portraitValue:100 landscapeValue:100]];
}
If you have any constraints setup in IB that would be replaced by these, you can mark them as placeholders that will be removed at runtime. The category looks like this,
+(NSLayoutConstraint *)heightConstraintForView:(UIView *)subview 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:NSLayoutAttributeHeight relatedBy:0 toItem:superview attribute:NSLayoutAttributeHeight multiplier:multiplier constant:constant];
NSLog(@"height coeffs: %f %f",multiplier,constant);
return con;
}
+(NSLayoutConstraint *)widthConstraintForView:(UIView *)subview superview:(UIView *)superview portraitValue:(CGFloat)pValue landscapeValue:(CGFloat)lValue {
CGFloat multiplier = (pValue - lValue)/(superview.bounds.size.width - superview.bounds.size.height);
CGFloat constant = pValue - (superview.bounds.size.width * multiplier);
NSLayoutConstraint *con = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeWidth relatedBy:0 toItem:superview attribute:NSLayoutAttributeWidth multiplier:multiplier constant:constant];
NSLog(@"width coeffs: %f %f",multiplier,constant);
return con;
}
+(NSLayoutConstraint *)leftConstraintForView:(UIView *)subview viewAttribute:(NSLayoutAttribute) att superview:(UIView *)superview portraitValue:(CGFloat)pValue landscapeValue:(CGFloat)lValue {
CGFloat multiplier = (pValue - lValue)/(superview.bounds.size.width - superview.bounds.size.height);
CGFloat constant = pValue - (superview.bounds.size.width * multiplier);
NSLayoutConstraint *con = [NSLayoutConstraint constraintWithItem:subview attribute:att relatedBy:0 toItem:superview attribute:NSLayoutAttributeRight multiplier:multiplier constant:constant];
NSLog(@"left coeffs: %f %f",multiplier,constant);
return con;
}
+(NSLayoutConstraint *)rightConstraintForView:(UIView *)subview viewAttribute:(NSLayoutAttribute) att superview:(UIView *)superview portraitValue:(CGFloat)pValue landscapeValue:(CGFloat)lValue {
CGFloat multiplier = (superview.bounds.size.width - pValue - superview.bounds.size.height + lValue)/(superview.bounds.size.width - superview.bounds.size.height);
CGFloat constant = superview.bounds.size.width - pValue - (superview.bounds.size.width * multiplier);
NSLayoutConstraint *con = [NSLayoutConstraint constraintWithItem:subview attribute:att relatedBy:0 toItem:superview attribute:NSLayoutAttributeRight multiplier:multiplier constant:constant];
NSLog(@"right coeffs: %f %f",multiplier,constant);
return con;
}
+(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;
}
+(NSLayoutConstraint *)bottomConstraintForView:(UIView *)subview viewAttribute:(NSLayoutAttribute) att superview:(UIView *)superview portraitValue:(CGFloat)pValue landscapeValue:(CGFloat)lValue {
CGFloat multiplier = (superview.bounds.size.height - pValue - superview.bounds.size.width + lValue)/(superview.bounds.size.height - superview.bounds.size.width);
CGFloat constant = superview.bounds.size.height - pValue - (superview.bounds.size.height * multiplier);
NSLayoutConstraint *con = [NSLayoutConstraint constraintWithItem:subview attribute:att relatedBy:0 toItem:superview attribute:NSLayoutAttributeBottom multiplier:multiplier constant:constant];
NSLog(@"bottom coeffs: %f %f",multiplier,constant);
return con;
}
I have this example project posted here, http://jmp.sh/SYgejs6