NSLayoutConstraint setup - ios

I'm trying to setup a panel to display some information. I'm having trouble getting the autolay out to work as i want.
here's what I'm trying to do:
I have a headerView, a UIImageView and 5 labels. I want the labels to line up vertically and i want them 8 spacing from the UIImageView. I can line them up vertically easily enough:
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[headerView]-[acresLabel]-[addedLabel(==acresLabel)]-[typeLabel(==acresLabel)]-[zonesLabel(==acresLabel)]-[sceneLabel(==acresLabel)]-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(headerView, acresLabel, addedLabel, typeLabel, zonesLabel, sceneLabel)]];
But getting them to line up off the image view is proving tedious/verbose:
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[imageView]-[acresLabel]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(imageView, acresLabel)]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[imageView]-[addedLabel]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(imageView, addedLabel)]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[imageView]-[typeLabel]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(imageView, typeLabel)]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[imageView]-[zonesLabel]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(imageView, zonesLabel)]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:[imageView]-[sceneLabel]"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(imageView, sceneLabel)]];
Seems like a better way to do this then set up a constraint for each label to the image view. I tried adding NSLayoutFormatAlignAllCenterX to the first constrain, but it sets them all center to the content view's center X, doesn't line the label's center X up with each other. NSLayoutFormatAlignAllBaseline gives an error and crash when used vertically.
I'll have to do this again for the data (Acres: 'value').

You're on the right track with NSLayoutFormatAlignAllCenterX. All you need to do differently is isolate V:[headerView]-[acresLabel] from the rest of the constraint, since you don't want headerView's CenterX to be aligned with the 5 labels'.
// NSDictionary* views ;
[NSLayoutConstraint constraintsWithVisualFormat:#"V:[headerView]-[acresLabel]" options:0 metrics:nil views:views] ;
// Use any of the horizontal NSLayoutFormats (NSLayoutFormatAlignAllLeft, NSLayoutFormatAlignAllRight, NSLayoutFormatAlignAllLeading, NSLayoutFormatAlignAllTrailing, NSLayoutFormatAlignAllCenterX)
[NSLayoutConstraint constraintsWithVisualFormat:#"V:[acresLabel]-[addedLabel(==acresLabel)]-[typeLabel(==acresLabel)]-[zonesLabel(==acresLabel)]-[sceneLabel(==acresLabel)]-|" options:NSLayoutFormatAlignAllCenterX metrics:0 views:views] ;
[NSLayoutConstraint constraintsWithVisualFormat:#"H:[imageView]-[acresLabel]" options:0 metrics:nil views:views] ;

Related

How to grow UIlabel into scrollable UIlabel?

I'm trying to create a label that fits the text size. But if the text is too long it make scroll
I am trying something like that.
[containerView_ addConstraints:[NSLayoutConstraint constraintWithItem:containerView_
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationLessThanOrEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0f
constant:300]];
[containerView_ addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-bigMargin-[scrollLabel_]-bigMargin-|"
options:0
metrics:metrics
views:views]];
[containerView_ addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-bigMargin-[scrollLabel_]-bigMargin-|"
options:0
metrics:metrics
views:views]];
[scrollLabel_ addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[messageLabel_]-0-|"
options:0
metrics:metrics
views:views]];
[scrollLabel_ addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[messageLabel_]-0-|"
options:0
metrics:metrics
views:views]];
The purpose is to show a popup with text and other stuff.
I expected my container view to grow up to 300 in height and if the message was bigger than scrolling.
But my UIScrollView gets a frame of 0 and the only thing that grows is the contentsize
Any idea how to solve this
I think UILabel are not meant to do that. You may consider using a UITextView. You may need to enable the scroll with:
textView.scrollEnabled = true

NSLayoutConstrain - Will attempt to recover by breaking constraint - Programmatically Creating Constraints [duplicate]

This question already has answers here:
Unable to simultaneously satisfy constraints, will attempt to recover by breaking constraint
(17 answers)
Closed 6 years ago.
It runs fine and nothing is wrong except that I receive this error.
Below is my code.
NSDictionary *views = #{#"container":self.containerView,
#"head":self.headImageView,
#"userName":self.userNameLabel,
#"userTitle":self.userTitleLabel,
#"line":self.infoSeparatorLine,
#"articleTitle":self.articleTitleLabel
};
float headWidthAndHeight = 50;
NSDictionary *metrics = #{#"headWH":#(headWidthAndHeight),
#"userLabelWH":#(headWidthAndHeight/2),
};
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[container]|" options:0 metrics:nil views:views]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-10-[container]|" options:0 metrics:nil views:views]];
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-15-[head(headWH)]-5-[userName]-15-|" options:0 metrics:metrics views:views]];
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-15-[head(headWH)]-5-[userTitle]-15-|" options:0 metrics:metrics views:views]];
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[line]|" options:0 metrics:metrics views:views]];
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-15-[articleTitle]-15-|" options:0 metrics:metrics views:views]];
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[head(headWH)]-0-[line(1)]-8-[articleTitle]|" options:0 metrics:metrics views:views]];
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[userName(userLabelWH)]-0-[userTitle(userLabelWH)]" options:0 metrics:metrics views:views]];
Below is the error message I receive in the debug area.
How do I fix it?
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[head(headWH)]-0-[line(1)]-8#999-[articleTitle]|" options:0 metrics:metrics views:views]];
Change priority below 1000 for broken constraint.

App crashing while adding constraints programatically

I am using visual format to define constraints. The goal is to place a UIView at the bottom of the super view say self.view with height fixed as 40, and width automatically. I have done this using Storyboard but I am unable to do it programatically. Here is the code what I have written. The app is crashing if i am not giving a fixed width. It is crashing with the following constraint: "H:[redView]|". If I change this to "H:[redView(100)]", it works. I don't want to use self.bounds and get width from there. It should stick from left side of super view, bottom and right side of the view.
Please help!
NSDictionary *viewsDictionary = #{#"redView":self.redView};
NSArray *constraint_H = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[redView(40)]"
options:0
metrics:nil
views:viewsDictionary];
NSArray *constraint_V = [NSLayoutConstraint constraintsWithVisualFormat:#"H:[redView]|"
options:0
metrics:nil
views:viewsDictionary];
// 3. Define the redView Position
NSArray *constraint_POS_V = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[redView]|"
options:0
metrics:nil
views:viewsDictionary];
NSArray *constraint_POS_H = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[redView]"
options:0
metrics:nil
views:viewsDictionary];
[self.redView addConstraints:constraint_H];
[self.redView addConstraints:constraint_V];
[self.view addConstraints:constraint_POS_H];
[self.view addConstraints:constraint_POS_V];
You need to add redView to its super view first.
Also, the constraints are to be added to the superview, not redView.
[self.view addSubview:self.redView];
// create your constraints here
[self.view addConstraints:#[constraint_H, constraint_V, constraint_POS_V, constraint_POS_H]];
[self.view updateConstraintsIfNeeded];
In the visual constraints syntax the | refers to the parent view. The way you had that horizontal constraint before, adding it to the redview, it was interpreted as redview had a child, called the same, which obviously did not exist, so it crashed.
The vertical constraint works the way it is because it does not reference the parent view.
You could change your code a bit so that the constraints are more clear:
NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[redView(40)]|" options:0 metrics:nil
views:viewsDictionary];
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[redView]|" options:0 metrics:nil
views:viewsDictionary];
[self.view addConstraints:horizontalConstraints];
[self.view addConstraints:verticalConstraints];
Just remember you should always add the constraints for an UIView to it's superview.
Changing this line
[self.redView addConstraints:constraint_V];
with
[self.view addConstraints:constraint_V];
Solved myself. Thanks to me..:)
If you want to take the width of the view and apply it to red view, you only need to add a constraint like that:
NSArray *constraint_POS_H = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[redView]-|"
options:0
metrics:nil
views:viewsDictionary];

NSLayoutConstraint, sub-viewing a UIView in a table view cell not working

So I am using a project that I found on Github — https://github.com/kmonaghan/CBPWordPress — and am trying to get a handle on it.
Essentially, what I want to do is create the floating "Cards" illusion that an app like Facebook has. The way that I have accomplished this in the past is by creating a subview UIView, rounding the corners, etc. before putting the title label, author name inside of that view. The issue is that I have typically done that with storyboards, while this example programmatically lays things out.
After toying around with it, I thought I had figured it out. This is how I set up the -(void)updateConstraints method:
(void)updateConstraints
{
if (!self.constraintsUpdated) {
self.contentView.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(self.frame), CBPLargePostPreviewTableViewCellHeight);
NSDictionary *views = #{#"postCommentLabel": self.postCommentLabel,
#"postDateLabel": self.postDateLabel,
#"postImageView": self.postImageView,
#"postTitleLabel": self.postTitleLabel,
#"roundedBackground": self.roundedBackground};
NSDictionary *metrics = #{#"padding": #(CBPPadding)};
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(4)-[roundedBackground]-(4)-|"
options:0
metrics:metrics
views:views]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(4)-[roundedBackground]-(4)-|"
options:0
metrics:metrics
views:views]];
[self.roundedBackground addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(5)-[postTitleLabel]-(5)-[postImageView(150)]-(5)-[postDateLabel]-(5)-|"
options:0
metrics:nil
views:views]];
[self.roundedBackground addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(padding)-[postTitleLabel]-(padding)-|"
options:0
metrics:metrics
views:views]];
[self.roundedBackground addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(padding)-[postImageView]-(padding)-|"
options:0
metrics:metrics
views:views]];
[self.roundedBackground addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(padding)-[postDateLabel]-(>=0)-[postCommentLabel]-(padding)-|"
options:0
metrics:metrics
views:views]];
[self.roundedBackground addConstraint:[NSLayoutConstraint constraintWithItem:self.postCommentLabel
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.postDateLabel
attribute:NSLayoutAttributeCenterY
multiplier:1.0f
constant:0]];
self.constraintsUpdated = YES;
}
[super updateConstraints];
}
But upon running I get this error: [__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[4]'
I have tried creating bounds for the view, but to no avail. Does anybody have any suggestions? If there is a better approach to creating the effect I am looking for, I am also open to that.
It seems that you use roundedBackground in visual format strings, but have background
key in your views dict.

constraintsWithVisualFormat set same Y position for all the views

I am just playing with constraintsWithVisualFormat but not able to figure out how to do.
I have two Views placed together with 10 pix margin in horizontal. and Y position will be the same for the both of the views.
I have tried the following things.
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-10-[view1(==100)]-10-[view2(==100)]" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-10-[view1(==100)]-[view2(==100)]" options:0 metrics:nil views:views]];
Horizontal Constraint : 10 pix left margin from superview - 100 width
of view1- 10 pix margin - 100 width of view2
Vertical Constraint : 10 pix top from superview - 100 height of view1-
100 height of view2
Problem
The second view Y position start after the view1 i want the same Y position for the both of the view.
Please if possible explain the answer
Mark '-' is margin 8px in VisualFormatLanguage.
Try this.
`[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-10-[view1(==100)]-10-[view2(==100)]" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-10-[view1(==100)]" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-10-[view2(==100)]" options:0 metrics:nil views:views]];`
Horizontal layout with all bottom alignment:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-10-[view1(==100)]-10-[view2(==100)]"
options:NSLayoutFormatAlignAllBottom
metrics:nil
views:views]
Vertical layout untouched:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-10-[view1]"
options:0
metrics:nil
views:views]
Please also note that two approaches -- constrain each view at top of superview vs. align all views around common top/bottom/baseline/centery differ in obvious way. And that other answer cannot address the case of center-alignment, btw.
UPD: Here is a complete working example of using alignment options in layout:
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
NSTextField *view1 = [[NSTextField alloc] initWithFrame:NSZeroRect];
NSTextField *view2 = [[NSTextField alloc] initWithFrame:NSZeroRect];
NSView *contentView = [self.window contentView];
NSDictionary *views = NSDictionaryOfVariableBindings(view1, view2);
[view1 setTranslatesAutoresizingMaskIntoConstraints:NO];
[view2 setTranslatesAutoresizingMaskIntoConstraints:NO];
[contentView addSubview:view1];
[contentView addSubview:view2];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[view1(==100)]-[view2(==100)]"
options:NSLayoutFormatAlignAllBottom
metrics:nil
views:views]];
[contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[view1]"
options:0
metrics:nil
views:views]];
}

Resources