When using Auto Layout my code would look like this:
let safeAreaLayoutGuide = contentView.safeAreaLayoutGuide
let bottomAnchor = userImage.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -16.0)
bottomAnchor.priority = .required - 1
NSLayoutConstraint.activate([
userImage.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 16),
userImage.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor
, constant: 16),
userImage.widthAnchor.constraint(equalToConstant: 90),
userImage.heightAnchor.constraint(equalToConstant: 90),
userName.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 16),
userName.leadingAnchor.constraint(equalTo: userImage.trailingAnchor, constant: 16),
userName.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -16),
userStatus.topAnchor.constraint(equalTo: userName.bottomAnchor, constant: 16),
userStatus.leadingAnchor.constraint(equalTo: userImage.trailingAnchor, constant: 16),
userStatus.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -16),
textField.topAnchor.constraint(equalTo: userName.bottomAnchor, constant: 48),
textField.leadingAnchor.constraint(equalTo: userImage.trailingAnchor, constant: 16),
textField.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -16),
textField.heightAnchor.constraint(equalToConstant: 32),
showStatusButton.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 16),
showStatusButton.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: 16),
showStatusButton.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -16),
bottomAnchor
])
The bottomAnchor
constraint is made to let contentView
adjust to its content size. Now I'm trying to make the same UI but now using SnapKit
. Here are the constraints for all the objects on the contentView
:
userImage.snp.makeConstraints { make in
make.top.equalTo(self.safeAreaInsets.top).offset(16)
make.left.equalTo(self.safeAreaInsets.left).offset(16)
make.height.width.equalTo(userImage.layer.cornerRadius * 2)
}
userName.snp.makeConstraints { make in
make.top.equalTo(self.safeAreaInsets.top).offset(16)
make.left.equalTo(userImage.snp.right).offset(16)
make.right.equalTo(self.safeAreaInsets.right).inset(-16)
}
userStatus.snp.makeConstraints { make in
make.top.equalTo(userName.snp.bottom).offset(16)
make.left.equalTo(userImage.snp.right).offset(16)
make.right.equalTo(self.safeAreaInsets.right).offset(-16)
}
textField.snp.makeConstraints { make in
make.top.equalTo(userStatus.snp.bottom).offset(40)
make.left.equalTo(self.safeAreaInsets.left).offset(16)
make.right.equalTo(self.safeAreaInsets.right).offset(-16)
make.height.equalTo(32)
}
showStatusButton.snp.makeConstraints { make in
make.top.equalTo(textField.snp.bottom).offset(16)
make.left.equalTo(self.safeAreaInsets.left).offset(16)
make.right.equalTo(self.safeAreaInsets.right).offset(-16)
}
I can't figure out what to replace my bottomAnchor
constraint with. How do I make contentView adjust to what I have? (or basically position it relative to bottom anchor of showStatusButton
.
Just in case, the whole project is here and the file I'm changing is ProfileHeadevView.swift
Instead of trying to set constraints to
self.safeAreaInsets
, set them to thecontentView
itself...Here is your original
ProfileHeaderView
- usingNSLayoutConstraints
- with a couple edits since I don't have yourme.login
/textColor
/accentColor
/ etc:Here's that same
ProfileHeaderView
, but using SnapKit for the constraints:and here's a sample view controller that puts one table view using
ContraintsProfileHeaderView
above a second table view that usesSnapsProfileHeaderView
:Looks like this:
Worth noting: you may want to make use of the
contentView.layoutMarginsGuide
- docs - to get the "recommended amount of padding for content inside of a view"Edit
When UIKit lays out the table view elements - header / footer / section header/footers / etc - it is possible, in fact usual, that multiple auto-layout "passes" are made to calculate the framing.
If all the cells use the default cell height, we don't get the constraint warning/error messages for its layout.
If some of the cells are NOT the default height, auto-layout initially sets the section header height to its default of
17.6667-points
(on a @3x device)... which causes constraint conflicts... then re-process the layout and adjusts the header height.We often see this in dynamic tableview cells on their own (particularly when multiline labels are embedded in vertical stack views).
By setting the priority on the bottom constraint to less-than-required, we tell auto-layout to go ahead and break that constraint if necessary, and not complain about it.
That's why the common "fix" is to use:
and we no longer see the messages.
If you want to do that with SnapKit, add the priority modifier: