Reputation: 676
i have to add some constraints programmatically in a customized UITableViewCell, i have a mainView (red) it will be a container (a subView of cell.contentView), an image and 2 other subviews of the mainView.
this is what i want to have (blue and yellow views don't have the same height, but this is an other question):
using the code bellow (i'm not adding the imageView yet), i have this:
as you can see the 2 subviews have the same size, and when i scroll, sometime the blue view is displayed and sometime it's the yellow one.
code :
self.mainView = [[UIView alloc]init];
[self.mainView setBackgroundColor:[UIColor redColor]];
[self.mainView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.contentView addSubview:self.mainView];
UIView *blueView = [[UIView alloc]init];
[blueView setTranslatesAutoresizingMaskIntoConstraints:NO];
[blueView setBackgroundColor:[UIColor blueColor]];
[self.mainView addSubview:blueView];
UIView *yelloView = [[UIView alloc]init];
[yelloView setBackgroundColor:[UIColor yellowColor]];
[yelloView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.mainView addSubview:yelloView];
NSDictionary *views = NSDictionaryOfVariableBindings(blueView,yelloView,mainView);
NSMutableArray *results = [NSMutableArray array];
NSString *mainContentView_CVF_H = @"H:|-[blueView]-|";
NSString *mainContentView_CVF_V = @"V:|-[blueView]";
NSArray *mainContentViewConstaints_H = [NSLayoutConstraint constraintsWithVisualFormat:mainContentView_CVF_H options:0 metrics:nil views:views];
NSArray *mainContentViewConstaints_V = [NSLayoutConstraint constraintsWithVisualFormat:mainContentView_CVF_V options:0 metrics:nil views:views];
[results addObjectsFromArray:mainContentViewConstaints_H];
[results addObjectsFromArray:mainContentViewConstaints_V];
NSString *delivelyView_CVF_H = @"H:|-[yelloView]-|";
NSString *delivelyView_CVF_V = @"V:[blueView][yelloView]-|";
NSArray *delivelyViewConstaints_H = [NSLayoutConstraint constraintsWithVisualFormat:delivelyView_CVF_H options:0 metrics:nil views:views];
NSArray *delivelyViewConstaints_V = [NSLayoutConstraint constraintsWithVisualFormat:delivelyView_CVF_V options:0 metrics:nil views:views];
[results addObjectsFromArray:delivelyViewConstaints_H];
[results addObjectsFromArray:delivelyViewConstaints_V];
[self.mainView addConstraints:results];
NSString *mainView_CVF_H = @"H:|-[mainView]-|";
NSString *mainView_CVF_V = @"V:|-[mainView]-|";
results = [NSMutableArray array];
NSArray *mainViewConstaints_H = [NSLayoutConstraint constraintsWithVisualFormat:mainView_CVF_H options:0 metrics:nil views:views];
NSArray *mainViewConstaints_V = [NSLayoutConstraint constraintsWithVisualFormat:mainView_CVF_V options:0 metrics:nil views:views];
[results addObjectsFromArray:mainViewConstaints_H];
[results addObjectsFromArray:mainViewConstaints_V];
[self.contentView addConstraints:results];
i replace the subviews(blue and yellow) with 2 text filed without any modification, and they are displayed as expected.
2 questions:
can you help :) ?
the order of adding constraints is important ?
Upvotes: 1
Views: 320
Reputation: 437552
A couple of thoughts:
No, the order of constraints is not important.
As an aside, you could combine two of your vertical constraint VLF into one:
@"V:|-[blueView][yellowView]-|"
The reason for the strange heights of blueView
and yellowView
is that your constraints are ambiguous. You define that blue and yellow, together, should span the height of their shared superview, but you leave it to iOS to decide precisely how tall each will will be individually. This ambiguity can be confirmed by running your app in the debugger, pausing the app once the app has finished presenting this particular set of views, and then at the (lldb)
prompt you can enter:
po [[UIWindow keyWindow] _autolayoutTrace]
You'll probably see results that say something like this simplified example:
$0 = 0x075667b0
*<UIWindow:0x718a760>
| *<UIView:0x718d090>
| | *<UIView:0x7562490>
| | | *<UIView:0x75627d0> - AMBIGUOUS LAYOUT
| | | *<UIView:0x7562880> - AMBIGUOUS LAYOUT
Bottom line, you have to resolve this ambiguity. If you wanted them the same height (I know you don't, but just an example), you could do:
@"V:|-[blueView][yellowView(==blueView)]-|"
Or if you wanted to say that blueView
should be 44 px, and it should resize yellowView
to take up the rest, it would be:
@"V:|-[blueView(44)][yellowView]-|"
If you wanted to say that blueView
should be twice the height of yellowView
, you can do that, too, but not with VFL:
[mainView addConstraint:[NSLayoutConstraint constraintWithItem:blueView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:yellowView
attribute:NSLayoutAttributeHeight
multiplier:2.0
constant:0.0]];
But bottom line, unless you're ok with iOS making blue and yellow any old random height (including making one zero height and the other taking up the rest of the space), you need some constraints to indicate some rules about how tall they should each be.
The reason it works when you replace the blue and yellow views with UILabel
controls, is that labels have an intrinsic height constraint which will make them non-zero heights, which means that you will see both views at the same time. But with simple UIView
controls, there is no intrinsic minimum height, so it's free to make either blue or yellow any size it wants to satisfy your constraints, including make one or the other a zero height.
There are tons of different options here. While you tell us you don't want blue and yellow to have the same height, you haven't described to us what will dictate their relative heights. It's hard for us to help you without some information about the rules you want to dictate the relative blue and yellow heights.
Upvotes: 3