Reputation: 21726
I got stuck with resolving constraints, perhaps someone can help:
Here is the case:
I need myView
to have flexible width according to superview
width.
If superview
has more width than 500 -> myView
should have 500.
If superview
has less width then 500 -> myView
should take all superView
width.
[NSLayoutConstraint constraintsWithVisualFormat:@"[myView(==500)]" options:0 metrics:nil views:@{
@"myView" : self.myView,
@"superview" : superview
}];
// If I write myView(<=500), obviously width will be zero.
// I can not add something like this:
// @[tableView(<=superview)]", as width can be less, can be more
So I got stuck here, any thoughts?
Thanks in advance!
Upvotes: 2
Views: 2269
Reputation: 1536
You need more than one constraint and the use of priorities. One constraint for myView to equal the superview width as you already have and another for the myView to be NSLessThanOrEqual to 500 as suggested above. Then set the priority of the latter to be greater than the equal width constraint. I think that should be enough for the width. Maybe you'll need a 3rd constraint with lower priority to set the width of myView to 500 if it still shrinks to 0 to avoid ambiguity.
Here's an edit to my answer with some code to illustrate better:
Using visual layout as below allows for the more readable layout (once you're used to the syntax)
NSDictionary *views = @{@"myView" : _myView, @"superView": self.view};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-100-[myView(40)]" options:0
metrics:nil
views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(3@999,>=3)-[myView(<=500)]-(3@999,>=3)-|" options:0
metrics:nil
views:views]];
If put a padding of 3 just to illustrate the shrinking to the edges.
If you wanting to center myView in the superview visual layout will be lacking and you'll need to add a long form constraint like this:
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.myView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]];
But all of this could done in Storyboards without any code based on the same logic. If not using Storyboards I try to use the visual layout as much as possible and usually only the long form for centering views or when dynamically laying views where the structure is only known at runtime.
Upvotes: 1
Reputation: 2770
Visual Format Language can be kind wonky even by Auto Layout standards, especially when setting priority. The problem is actually conceptual and can be done in IB or with VFL or by the class methods. Anyway, the issue:
When you want some behavior to change in a set way when some condition is met or not met, try switching to priority instead of inequality. In this case, think of the margins: You want to the horizontal margin to be 0 when the total width is under 500, but adding space when more than 500. Constraints you will need:
If the space is less than 500, both conditions can be met. If the space is more than 500, than it will start breaking constraints, starting with the lowest priority.
Note that after breaking the margin constraints it won't know where to set the horizontal x placement of myView, so you will need another constraint. Centering in superview will conflict the least, since it can place it horizontally with or without margin constraints broken. There is a way to get it to add space on one side only, but it's a complicated dance-of-the-breaking-constriants leading to messy required programmatic intervention; I think centered-horizontally gets your intended behavior.
Upvotes: 2
Reputation: 2928
As per your question you need to set constraint to myView.
Here's what you need to do:
UIView *myView = [UIView new];
myView.translatesAutoresizingMaskIntoConstraints = NO;
myView.backgroundColor = [UIColor blueColor];
[self.view addSubview:myView];
NSDictionary *viewDictionary = @{@"myView":myView};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-50-[myView(200)]" options:0 metrics:0 views:viewDictionary]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[myView(<=500)]" options:0 metrics:0 views:viewDictionary]];
NSLayoutConstraint *tailing = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:myView attribute:NSLayoutAttributeTrailingMargin multiplier:1 constant:75];
tailing.priority = 999;
[self.view addConstraint:tailing];
Result:
Hope this might help in solving your problem.
You can visit this link for setting auto layout constraints programmatically for advance help.
ref: http://technet.weblineindia.com/mobile/ui-design-of-ios-apps-with-autolayout-using-constraints-programmatically/
ref: https://codehappily.wordpress.com/2013/10/09/ios-how-to-programmatically-add-auto-layout-constraints-for-a-view-that-will-fit-its-superview/
Upvotes: -1