I'm new in autolayout programmatically, and I have a problem with displaying 2 different cells in UITableView as below:
The first cell I want to show profiles picture and the username, then the menu options. But as screenshot the second section menu option is displaying behind the first section (user profile picture and username).
How to solve this problem?
UserTableViewCell:
class UserTableViewCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
layoutUI()
backgroundColor = .CustomGreen()
selectionStyle = .none
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var containerView: UIView = {
let containerView = UIView()
containerView.backgroundColor = .clear
containerView.translatesAutoresizingMaskIntoConstraints = false
return containerView
}()
lazy var userPhoto: UIImageView = {
let userPhoto = UIImageView()
userPhoto.translatesAutoresizingMaskIntoConstraints = false
userPhoto.layer.cornerRadius = userPhoto.frame.size.width / 2
userPhoto.clipsToBounds = true
return userPhoto
}()
lazy var username: UILabel = {
let username = UILabel()
username.textColor = .white
username.text = "Ahmed Abd Elaziz"
username.translatesAutoresizingMaskIntoConstraints = false
return username
}()
func setupContainerViewConstraints() {
NSLayoutConstraint.activate([
containerView.topAnchor.constraint(equalTo: topAnchor),
containerView.bottomAnchor.constraint(equalTo: bottomAnchor),
containerView.leadingAnchor.constraint(equalTo: leadingAnchor),
containerView.trailingAnchor.constraint(equalTo: trailingAnchor)
])
}
func setupUserPhotoConstraints() {
NSLayoutConstraint.activate([
userPhoto.centerXAnchor.constraint(equalTo: containerView.centerXAnchor),
userPhoto.widthAnchor.constraint(equalToConstant: frame.width / 3),
userPhoto.heightAnchor.constraint(equalToConstant: frame.width / 3)
])
}
func setupUsernameConstraints() {
NSLayoutConstraint.activate([
username.topAnchor.constraint(lessThanOrEqualTo: userPhoto.bottomAnchor, constant: 16),
username.centerXAnchor.constraint(equalTo: containerView.centerXAnchor),
])
}
func addSubviews() {
addSubview(containerView)
containerView.addSubview(userPhoto)
containerView.addSubview(username)
}
func layoutUI() {
addSubviews()
setupContainerViewConstraints()
setupUserPhotoConstraints()
setupUsernameConstraints()
}
}
SideMenuOptionTableViewCell:
class SideMenuOptionTableViewCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
layoutUI()
backgroundColor = .CustomGreen()
selectionStyle = .none
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var containerView: UIView = {
let containerView = UIView()
containerView.backgroundColor = .clear
containerView.translatesAutoresizingMaskIntoConstraints = false
return containerView
}()
lazy var viewTitle: UILabel = {
let viewTitle = UILabel()
viewTitle.font = UIFont(name: "AvenirNext-Regular", size: 20)
viewTitle.textColor = .white
viewTitle.numberOfLines = 0
viewTitle.translatesAutoresizingMaskIntoConstraints = false
return viewTitle
}()
func setupContainerViewConstraints() {
NSLayoutConstraint.activate([
containerView.topAnchor.constraint(equalTo: topAnchor),
containerView.bottomAnchor.constraint(equalTo: bottomAnchor),
containerView.leadingAnchor.constraint(equalTo: leadingAnchor),
containerView.trailingAnchor.constraint(equalTo: trailingAnchor)
])
}
func setupFoodTitle() {
NSLayoutConstraint.activate([
viewTitle.centerYAnchor.constraint(equalTo: containerView.centerYAnchor),
viewTitle.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 16)
])
}
func addSubview() {
addSubview(containerView)
containerView.addSubview(viewTitle)
}
func layoutUI() {
addSubview()
setupContainerViewConstraints()
setupFoodTitle()
}
}
SideMenuTableViewController:
class SideMenuTableViewController: UITableViewController {
let viewControllers = ["Controller One", "Logout"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UserTableViewCell.self, forCellReuseIdentifier: "UserTableViewCell")
tableView.register(SideMenuOptionTableViewCell.self, forCellReuseIdentifier: "SideMenuOptionTableViewCell")
tableView.reloadData()
tableView.backgroundColor = .CustomGreen()
tableView.separatorStyle = .none
tableView.rowHeight = UITableView.automaticDimension
// tableView.estimatedRowHeight = 100
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return section == 0 ? 1 : viewControllers.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "UserTableViewCell", for: indexPath) as! UserTableViewCell
cell.userPhoto.image = UIImage(named: "ahmed")
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "SideMenuOptionTableViewCell", for: indexPath) as! SideMenuOptionTableViewCell
cell.viewTitle.text = viewControllers[indexPath.row]
return cell
}
}
}
The problem here is you are adding constraints according to the cells height and all the views are being adjusted in the cell. As the space for the views is too small they are overlapping the views of the next cell. You can fix this problem by increasing the size of the content view of the cell.
Add this line in init of your UserTableViewCell
let minHeight = 70
let minHeightConstraint = contentView.heightAnchor.constraint(greaterThanOrEqualToConstant: minHeight)
minHeightConstraint.priority = UILayoutPriority(rawValue: 999)
minHeightConstraint.isActive = true