How to get UISearchBar baseline position? - ios

I'm subclassing UISearchBar and I want to add label that it's baseline will be aligned with UISearchTextField's baseline. I extract UISearchTextField from the searchbar and try to setup constraints like this:
- (void)addConstraintToBottomLabel {
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:self.bottomLabel attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:self.bottomLabel attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0];
NSLayoutConstraint *baseline = [NSLayoutConstraint constraintWithItem:self.bottomLabel attribute:NSLayoutAttributeBaseline relatedBy:NSLayoutRelationEqual toItem:self.searchTextField attribute:NSLayoutAttributeBaseline multiplier:1.0 constant:0];
[self addConstraints:#[leading, trailing, baseline]];
}
And the result looks like this:
As you see, the labels aren't aligned.
For testing in constraints works well in other situation I align bottomLabel's baseline with textField's bottom and it works great. So where could be the problem?

Related

UIButton constraints programmatically

I have created "first button" using storyboard and set its constraints for it, now I want to create another button programmatically and set it above the first button like this :
and I use this code to try and achieve this:
NSLayoutConstraint *xConstraint = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];
NSLayoutConstraint *Yxonstraints = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.invoiceTextField attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:200];
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:200];
[self.view addConstraints:#[xConstraint,Yxonstraints,width,height]];
However the second button ends up in the middle and on the left and also smaller than its actual size, what am I doing wrong here?
You need
self.secondBu.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
self.secondBu.bottomAnchor.constraint(equalTo: self.firstBu.topAnchor, constant:-15)
self.secondBu.leadingAnchor.constraint(equalTo: self.firstBu.leadingAnchor),
self.secondBu.trailingAnchor.constraint(equalTo: self.firstBu.trailingAnchor),
self.secondBu.heightAnchor.constraint(equalTo: self.firstBu.heightAnchor)
])
but the easiest way is to insert firstBu inside UIStackView in storyboard , and then use 1 line
self.stackView.insertArrangedSubview(secondBu,at:0)
you may set stackView spacing property to 15 also in IB , also avoid using addConstraints as recommended by Apple and use NSLayoutConstraint.activate
NSLayoutConstraint *Yxonstraints = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.invoiceTextField attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
You don't want that. You want secondButton.top be space to firstButton.bottom :
NSLayoutConstraint *Yxonstraints = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.invoiceTextField attribute:NSLayoutAttributeBottom multiplier:1.0 constant:20];

Trailing constraint not applying when programmatically adding UIConstraints

I'm trying to add a subview to a view with constraints through code. I had some success but the trailing constraint seems to be completely ignored for whatever reason.
My code:
leading_const = 16.f;
trailing_const = 16.f;
top_const = 12.f;
bottom_const = 12.f;
insertView.translatesAutoresizingMaskIntoConstraints = NO;
[view addSubview:insertView];
NSLayoutConstraint *leading = [NSLayoutConstraint constraintWithItem:insertView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeLeading
multiplier:1.f
constant:leading_const];
NSLayoutConstraint *trailing = [NSLayoutConstraint constraintWithItem:insertView
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeTrailing
multiplier:1.f
constant:trailing_const];
NSLayoutConstraint *top = [NSLayoutConstraint constraintWithItem:insertView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeTop
multiplier:1.f
constant:top_const];
NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:insertView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeHeight
multiplier:1.f
constant:130.f];
[superView addConstraints:#[leading, trailing, top, height]];
Result:
Appreciate any guidance!
Your constraint is being applied but as you have set it to 16 it is going 16 points past the trailing edge of the view. You therefore should use a negative value for the constant instead.

NSLayoutConstraint inside UITableViewCell crashes app

I'm trying to position an image in the center of a UITableViewCell with NSLayoutConstraints. I'm using the code below for that:
NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:self.image
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:cell.contentView
attribute:NSLayoutAttributeWidth
multiplier:1
constant:200];
[self.image addConstraint: cn];
cn = [NSLayoutConstraint constraintWithItem:self.image
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:cell.contentView
attribute:NSLayoutAttributeHeight
multiplier:1
constant:200];
[self.image addConstraint:cn];
Also, I would like the image to be 80% of the UITableViewCells height and have the same width - so it's square. However, currently my app crashes and throws this error: Impossible to set up layout with view hierarchy unprepared for constraint.
What am I doing wrong?
As it turns out, I had to add the image to the cell.contentView, so that it was actually available as a subview.
This is the completed working code:
NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:self.image
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:cell.contentView
attribute:NSLayoutAttributeHeight
multiplier:0.7
constant:0];
[cell.contentView addConstraint: cn];
cn = [NSLayoutConstraint constraintWithItem:self.image
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:cell.contentView
attribute:NSLayoutAttributeHeight
multiplier:0.7
constant:0];
[cell.contentView addConstraint:cn];
NSLayoutConstraint *constraintX = [NSLayoutConstraint constraintWithItem:self.image attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0];
NSLayoutConstraint *constraintY = [NSLayoutConstraint constraintWithItem:self.image attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:cell.contentView attribute:NSLayoutAttributeCenterY multiplier:1.0f constant:0];
[cell.contentView addConstraint:constraintX];
[cell.contentView addConstraint:constraintY];
Exactly what is "self.image" referring to? Is it a property of your View Controller (this would be definitely wrong)? Seems to me it should be "cell.image" where each of your cells should have it's own reference to an image.

How to center a spinner with autolayout?

I am using this spinner in a project: https://github.com/misterwell/MMMaterialDesignSpinner
How would I add it to the center of the screen with autolayouts so that when the device rotates, it still stays in the center of the screen?
You can add autolayout constraints programmatically. You can use 4 constraints - center x, center y, width and height:
[self.spinner setTranslatesAutoresizingMaskIntoConstraints:NO];
NSLayoutConstraint *centerXConstraint = [NSLayoutConstraint constraintWithItem:self.spinner attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0.0f];
NSLayoutConstraint *centerYConstraint = [NSLayoutConstraint constraintWithItem:self.spinner attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.0f constant:0.0f];
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.spinner attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:kSpinnerWidth];
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self.spinner attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0f constant:kSpinnerHeight];
[self.view addConstraints:#[ centerXConstraint, centerYConstraint, widthConstraint, heightConstraint]];
If you're using storyboards you could add the Horizontal Centre in Container and Vertical Centre in Container. To do this, click on the view in interface builder and look at the bottom right of the IB screen. Click on the first of 4 buttons and check the appropriate boxes.
If you're using code you could write spinner.center = self.view.center in viewDidLayoutSubviews().

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.

Resources