Constraint added programmatically to a xib view not working - ios

I have a view(self.printSettingsView) created from xib. I add this view as a subview to another view(self.view). I programmatically add constraints as follows:
[self.printSettingView setTranslatesAutoresizingMaskIntoConstraints: NO];
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:self.printSettingView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0];
[self.view addConstraint:leftConstraint];
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.printSettingView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.topBar
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0];
[self.view addConstraint:topConstraint];
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self.printSettingView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeHeight
multiplier:1.0
constant:0];
[self.view addConstraint:heightConstraint];
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.printSettingView
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeWidth
multiplier:1.0
constant:0];
[self.view addConstraint:widthConstraint];
All the other constraints take effect except for height.
What could i be doing wrong here???
Thanks

Without knowing the constraints on your xib file or what you expect to happen vs what is happening (a screenshot would be helpful) it's hard to say. However I do have one suggestion where maybe the logic isn't correct.
The second constraint is pinning printViewSettings top to the bottom of the topBar, that part makes sense. The next one however sets the height of printViewSettings to the height of its superview. This may not jive with what you want because your superview contains your topBar as well and so may be larger than you expect. What you might actually want is a constraint that pins the bottom of printViewSettings to the bottom of the superview instead.

Sorry guys about the incomplete information. The problem in a gist was that i was assigning a constraint to the subview in my main view and whatever be the constant of the constraint the size of the subview remained constant. I found that the issue was the subview in turn had components(subviews) with fixed height constraints. I made them proportional to the height of the parent view and it works now.

Related

Adding AutoLayout Constraints To A UITableView When Adding To Parent View

I am trying to create the following setup with Autolayout to my UITableView before I add it as a subview of its wrapper UIView.
I am using the following so far but haven't had any luck at all. This is as far as I have got and it is throwing an errors.
//Trailing
NSLayoutConstraint *trailing =[NSLayoutConstraint
constraintWithItem:self.tableViewVideoList
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:self.viewContentWrapper
attribute:NSLayoutAttributeTrailing
multiplier:1.0f
constant:0.f];
//Leading
NSLayoutConstraint *leading = [NSLayoutConstraint
constraintWithItem:self.tableViewVideoList
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.viewContentWrapper
attribute:NSLayoutAttributeLeading
multiplier:1.0f
constant:0.f];
//Bottom
NSLayoutConstraint *bottom =[NSLayoutConstraint
constraintWithItem:self.tableViewVideoList
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.viewContentWrapper
attribute:NSLayoutAttributeBottom
multiplier:1.0f
constant:0.f];
[self.viewContentWrapper addConstraint:trailing];
[self.viewContentWrapper addConstraint:bottom];
[self.viewContentWrapper addConstraint:leading];
[self.viewContentWrapper addSubview:self.tableViewVideoList];
Any help would be great thanks, I usually do all the Autolayout work in the Storybaord.
You probably forgot to do this:
self.tableViewVideoList.translatesAutoresizingMaskIntoConstraints = NO;
And you should add `tableViewVideoList' to its superview before setting the constraints.
And you are missing a top layout constraint or height constraint (as 3stud1ant3 pointed out)

Programmatically add constraint to view relative to a sibling

I am using Auto Layout. I have a view with a subview (sb1). I am programmatically adding another subview (sb2) to this view. I am adding constraints to this new subview.
What I want accomplish:
add sb2 below sb1 an add a constraint to the top of sb2 to pin it to sb1.
What I've tried:
[self.containerView insertSubview:sb1
belowSubview:sb2];
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:sb1
attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
toItem:sb2 attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.f];
[self.otherLeftView addConstraint:constraint];
What is happening is my newly added subview is being pinned to the top of the container view, NOT to the sb1 (which is what I want to happen). Visual of what is happening:
Does anyone know how I can add a constraint between SB1 and SB2? Thanks!
Try this:
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:sb1
attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual
toItem:sb2 attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.f];

Autolayout Constraints adding programmatically

I'm having difficulty adding some constraints automatically. Usually when I add a constraint in Storyboard I click on the item and add a constraint to it (be that align to center x or leading edges etc)
However, when I add a constraint programmatically I'm unsure how to achieve the same results. With the following code I'm hoping to make my _spinner view to be half the width and half the height of it's parent _loadingView.
[_loadingView addConstraint:[NSLayoutConstraint constraintWithItem:_spinner
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:_loadingView
attribute:NSLayoutAttributeWidth
multiplier:0.5
constant:0]];
[_loadingView addConstraint:[NSLayoutConstraint constraintWithItem:_spinner
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:_loadingView
attribute:NSLayoutAttributeHeight
multiplier:0.5
constant:0]];
However running this produces some conflicts. The _loadingView has constraints stating that it should be 80% width and height of it's parentview which is the ViewController.view So _loadingView should be 80% of ViewController.view and then _spinner should be 50% of _loadingView. But by adding the constraints on the spinnerview it is causing a conflict.
So I thought it needs an x and a y coordinate so I specified the spinner to be placed in the center of the _loadingView as follows:
[_loadingView addConstraint:[NSLayoutConstraint constraintWithItem:_spinner
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:_loadingView
attribute:NSLayoutAttributeCenterY
multiplier:1
constant:0]];
[_loadingView addConstraint:[NSLayoutConstraint constraintWithItem:_spinner
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:_loadingView
attribute:NSLayoutAttributeCenterX
multiplier:1
constant:0]];
But this still produces conflicts and the spinner constraints are not being added.

Autolayout UICollectionView iOS 8

I have a UICollectionView added to a UIView. I just want the collection view to resize with orientation change, so that it fits the superview (UIView). After I add the layout constraint the collection view is missing. I could not even get the first constraint work properly.(below)
NSLayoutConstraint *leftSideConstraint = [NSLayoutConstraint constraintWithItem:self.collectionView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:10.0];
And then I add the constraint to self.view.
What am I doing wrong? Please, help!
Update:
This is how it works. I am new to autolayouts. I was just trying to satisfy the constraints one by one to be sure that they all work:) Thank you
NSLayoutConstraint *constraint1 = [NSLayoutConstraint constraintWithItem:self.collectionView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:5.0];
NSLayoutConstraint *constraint2 = [NSLayoutConstraint constraintWithItem:self.collectionView
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:-5.0];
NSLayoutConstraint *constraint3 = [NSLayoutConstraint constraintWithItem:self.collectionView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:-5.0];
NSLayoutConstraint *constraint4 = [NSLayoutConstraint constraintWithItem:self.collectionView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:5.0];
[self.view addConstraints:#[constraint1, constraint2, constraint3, constraint4]];
You can't just add one constraint for view to position correctly. It needs to know it's x and y position, width and height. With this one constraint you only gave it x position. You need three more constraints eg. trailing, top and bottom or top, width, height. Basically any set of constraints that will fully describe view position, width and height.

iOS: Autolayout: Lock new position after animating

I tried to write a category function for UIView that will get the constraints that will hold an given frame in place in its superview. I implemented it like so:
-(NSArray *)constraintsForLockingPositionInSuperview
{
NSLayoutConstraint *left=[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.superview
attribute:NSLayoutAttributeLeft multiplier:0 constant:self.frame.origin.x];
NSLayoutConstraint *height=[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:Nil
attribute:NSLayoutAttributeNotAnAttribute multiplier:0 constant:self.frame.size.height];
NSLayoutConstraint *width=[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:Nil
attribute:NSLayoutAttributeNotAnAttribute multiplier:0 constant:self.frame.size.width];
NSLayoutConstraint *top=[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.superview
attribute:NSLayoutAttributeTop multiplier:0 constant:self.frame.origin.y];
return #[left,height,width,top ];
}
And then after animating the view, apply to new constraints by doing the following in the view controller that contains the view in question. I remove the view then re-add it to remove the constraints that were on it, then reapply the new constraints. The hope was that this would hold the view in place if I add another subview or if something like an actionView comes in and the view has to layout itself out. The height and the width seem to be locking properly, but the view is jumping to the middle instead of locking in place:
NSArray *lockingConstraints = [someView constraintsForLockingPositionInSuperview];
[someView removeFromSuperview];
[self.view addSubview:someView;
[self.view addConstraints:lockingConstraints];
[self.view layoutSubviews];
From the documentation for layoutSubviews:
You should not call this method directly.
Call layoutIfNeeded instead.

Resources