I created a custom cell for my CollectionView
, however, I got problems with displaying the cell as I want.
This is the code for the custom cell:
import Foundation
import UIKit
class CardCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupCell()
setupViewsInCell()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupCell()
setupViewsInCell()
}
var postTitle: UILabel = {
let label = UILabel()
label.text = "POST TITLE"
label.font = UIFont.boldSystemFont(ofSize: 14)
label.textColor = UIColor.appColors.mainBlack
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
//postImage need to be the image the user uploaded.
var postImage: UIImageView = {
let image = UIImageView(image: UIImage(named: "placeholder-image"))
image.contentMode = .scaleAspectFit
image.clipsToBounds = true
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
var likeImage: UIImageView = {
let image = UIImageView(image: UIImage(named: "like"))
image.contentMode = .scaleAspectFit
image.clipsToBounds = true
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
var numberOfLikes: UILabel = {
let label = UILabel()
label.text = "20"
label.font = UIFont.systemFont(ofSize: 8)
label.textColor = UIColor.appColors.mainBlack
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
var dislikeImage: UIImageView = {
let image = UIImageView(image: UIImage(named: "dislike"))
image.contentMode = .scaleAspectFit
image.clipsToBounds = true
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
var numberOfDislikes: UILabel = {
let label = UILabel()
label.text = "34"
label.font = UIFont.systemFont(ofSize: 8)
label.textColor = UIColor.appColors.mainBlack
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
func setupCell(){
backgroundColor = UIColor.appColors.mainWhite
layer.cornerRadius = 10
clipsToBounds = true
layer.shadowColor = UIColor(white: 0, alpha: 0.25).cgColor
layer.shadowOffset = CGSize.zero
layer.shadowOpacity = 1
layer.shadowRadius = 2
layer.masksToBounds = false
}
func setupViewsInCell(){
let stackView = UIStackView(arrangedSubviews: [likeImage, numberOfLikes, dislikeImage, numberOfDislikes])
stackView.axis = .horizontal
stackView.distribution = .fillEqually
stackView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(postTitle)
self.addSubview(postImage)
self.addSubview(stackView)
NSLayoutConstraint.activate([
postTitle.topAnchor.constraint(equalTo: self.topAnchor, constant: 0),
postTitle.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 8),
postImage.topAnchor.constraint(equalTo: postTitle.bottomAnchor, constant: 10),
postImage.leftAnchor.constraint(equalTo: self.leftAnchor),
postImage.rightAnchor.constraint(equalTo: self.rightAnchor),
postImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 30),
stackView.topAnchor.constraint(equalTo: postImage.bottomAnchor, constant: 50),
stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0),
stackView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 8),
stackView.heightAnchor.constraint(equalToConstant: 40),
stackView.widthAnchor.constraint(equalToConstant: self.frame.width / 2),
])
}
}
The few problems I have, and couldn't find solution for are this:
Change this constant to negative postImage.topAnchor.constraint(equalTo: postTitle.bottomAnchor, constant: 10)
, when you use bottomAnchor
or rightAnchor
the constant need to be negative. If you want to understand more, see Bottom and Right constraints of view are negative?
The same problem with the constraint constant stackView.topAnchor.constraint(equalTo: postImage.bottomAnchor, constant: 50)
, try to change to -50
If you want to create Collection View with dynamic cell height, you need to calculate the cell size. You can do this by creating your custom view layout, see
https://www.raywenderlich.com/392-uicollectionview-custom-layout-tutorial-pinterest
this is a good tutorial to create a custom UICollectionViewLayout
,
or you can calculate the cell size inside the method func
collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout, sizeForItemAt
indexPath: IndexPath) -> CGSize
using the systemLayoutSizeFitting
, if all constraints are set right, this method will return the size of the cell, but you need to remember that this function will be called every
time a cell appears, a solution to this is save the height and check
if a content was already used to calculate the height of a cell. If
you need to change the height of the cell in another time, you need
to update the saved value as well or delete it to calculate the size
again.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 50)
let dummyCell = Cell(frame: frame)
let targetSize = CGSize(width: view.frame.width, height: 1000)
let dummyData = data[indexPath.row]
dummyCell.data = dummyData
dummyCell.layoutIfNeeded()
let height = max(MINIMUM_CELL_SIZE,
dummyCell.systemLayoutSizeFitting(targetSize).height)
return CGSize(width: view.frame.width, height: height)
}