Reputation: 8144
I've got a layout which I want to look like this:
Location: "blabla"
Website: "blabla"
LongerLabel: "blabla"
I want all the labels to be the same width. Hardcoded this can look like this:
@"H:|[locationLabel(80)]-5-[location]|"
@"H:|[websiteLabel(80)]-5-[website]|"
@"H:|[remarksLabel(80)]-5-[remarks]|"
I've already tried this using circular reference which doesn't work ;)
@"H:|[locationLabel(websiteLabel)]-5-[location]|"
@"H:|[websiteLabel(remarksLabel)]-5-[website]|"
@"H:|[remarksLabel(locationLabel)]-5-[remarks]|"
I do not want my labels to be hardcoded to 80, but I want them all the same width according to the max intrinsic content size.
Upvotes: 0
Views: 541
Reputation: 1453
Not sure if I am missing something, but simple 'equal width' constraints should have sufficed (no need for >=). They did for me.
The default compression resistance priority (750) is greater than the default content hugging priority (250). So it all works out in the end.
Upvotes: 0
Reputation: 7764
You can do it using circular greater-than-or-equal-width constraints:
@"H:|[locationLabel(>=websiteLabel)]-5-[location]|"
@"H:|[websiteLabel(>=remarksLabel)]-5-[website]|"
@"H:|[remarksLabel(>=locationLabel)]-5-[remarks]|"
(sorry for weird colors :) )
UPDATE: I've just checked simple "equal" circular constraints, and they work in my case as well. However, I think, "equal" constraints don't specify the "main" label in any way, they just state, that labels should be equal. And if they are all equal to the smallest label, it is also fine. So in the "equal" case it probably depends on the order of constraints.
Now let's take a look at two hypothetical labels ("Label" and "Label label" (LL for shortness)), which are connected using ">=" constraints.
Warning: the following text is just an assumption, I've never seen an actual autolayout implementation. I just know that it uses a complicated linear equations solving system to find a solution which satisfies all constraints as close as possible.
The autolayout engine (AE) takes the first label and makes it as small as possible because of the content hugging. The LL is ignored for now. Then the AE takes the second label. In case of equal constraints it would have to make it short, like the first labels, because the first label has already been processed. But in case of ">=" constraint the AE can make the second label longer. However, now it affects the "L >= LL" constraint and AE has to switch back to L and process it one more time using the new data (in case of "==" constraint it would stop already, because no conflicts emerged). The only solution now is to make the first label longer, which AE does, because it doesn't introduce any conflicts.
So, this way in several iterations the AE ends up with all labels being the same width (the width of the longest label).
Upvotes: 2
Reputation: 23053
Yes, you can specify fix-same width constraints using Visual Formatting language.
Constraints will be like below:
@"H:|[locationLabel]-5-[location]|"
@"H:|[websiteLabel]-5-[website]|"
@"H:|[remarksLabel]-5-[remarks]|"
Below additional constraints are required:
// Width constraints for Left side labels
NSLayoutConstraint *locationLabelConstraint = [NSLayoutConstraint constraintWithItem:locationLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.6 constant:0];
[self.view addConstraint:locationLabelConstraint];
NSLayoutConstraint *websiteLabelConstraint = [NSLayoutConstraint constraintWithItem:locationLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.6 constant:0];
[self.view addConstraint:locationLabelConstraint];
NSLayoutConstraint *remarksLabelConstraint = [NSLayoutConstraint constraintWithItem:locationLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.6 constant:0];
[self.view addConstraint:remarksLabelConstraint];
// Width constraints for right side labels
NSLayoutConstraint *locationConstraint = [NSLayoutConstraint constraintWithItem:locationLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.3 constant:0];
[self.view addConstraint:locationConstraint];
NSLayoutConstraint *websiteConstraint = [NSLayoutConstraint constraintWithItem:locationLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.3 constant:0];
[self.view addConstraint:websiteConstraint];
NSLayoutConstraint *remarksLabelConstraint = [NSLayoutConstraint constraintWithItem:locationLabel attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.3 constant:0];
[self.view addConstraint:remarksConstraint];
Explanation:
Above all constraints are width constraints equally related to its parent view width, these means labels will take all full width of its parent view. Here you can change multiplier to fix labels width.
Multiplier = 1 => Full view width
Multiplier = 0.5 => Half view width
Observe left side label width constraint where multiplier = 0.6
which means that it will take 0.6
% space of self.view
width.
Same way right side label width multiplier = 0.3
which takes 0.3
% space of self.view
. Change these values as your convenience.
Note: Also please check Xcode console sometimes there constraints gives warnings about constraint conflict. If there is any warning please resolve by changing constraints properties.
Upvotes: 0