Want a table view to appear 300 pixels down from the top while in portrait and about 175 pixels from the top while in landscape.
i can't seem to figure out the VFL logic i need.
Like many autolayout problems, yes, you can do what you're asking, but it's far from obvious. If I really needed precisely 300pt or 175pt, I might, too, be tempted to adjust the top constraint on rotation.
But if you want to know how to do this without handling rotation events, you could:
Set a required minimum top margin of 175;
Set a lower priority preferred top margin of 300 (which won't be satisfied in landscape); and
Less obviously, you also need a required minimum height too (so that in landscape, it will know not to satisfy the lower priority request to make the top margin 300).
You could, for example, use (obviously replace my bottom margin of 5 with whatever makes sense for you, but adjust the minimum height of the tableview accordingly):
@"V:|-(>=175)-[tableView(>=120)]-5-|"
combined with:
@"V:|-(300@500)-[tableView]"
(Obviously, you would have constraints for the horizontal axis, too, but I omit those for the sake of brevity.)
This is, admittedly, vaguely unappealing, to have to precisely specify the minimum table height, too, but I saw no other way to tell autolayout under what situations it should gracefully not satisfy the optional top space of 300pt.
You can also do this with using the the y = mx + b formula of constraintWithItem
. Yes, I know you asked how to do this with Visual Format Language, but if you use constraintWithItem
, you don't have to specify the minimum table height, but rather you can just set the top margin like so:
constraint = [NSLayoutConstraint constraintWithItem:self.tableView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.tableView.superview
attribute:NSLayoutAttributeBottom
multiplier:multiplier
constant:constant];
Clearly, the trick is how to determine the multiplier
and constant
so that you get 300 pt in portrait and 175 pt in landscape. Doing a little algebra, you will see that you can calculate those values as follows:
CGFloat multiplier = (300.0 - 175.0) / (superviewPortraitHeight - superviewLandscapeHeight);
CGFloat constant = 175.0 - superviewLandscapeHeight * multiplier;
(And, again, I'll assume that you'll specify the other constraints so that the tableview is not ambiguously defined, e.g. set the left, right, and bottom constraints, which can be done in Visual Format Language.)
I don't think there's anyway to set this up to do specific distances without changing it in code in a rotation callback method. If you make an IBOutlet to the constraint in IB (lets call it con1), and have that constraint with the initial value of 300, then in a rotation callback method you can just change that constant.
self.con1.constant = 175;
After Edit:
this works:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
con1.constant = 175;
}else{
con1.constant = 300;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With