Label with text not showing in custom cell - swift

I have a custom cell set up for UICollectionView. I have a Data model that has an image and title.
I can get the image to show in the cell but cant get the table to show
I tried to set up the label programmatically inside the custom cell (in the same way that the image is set up) yet the image shows but label is invisible...
class CustomCell: UICollectionViewCell {
var data: CustomData? {
didSet {
guard let data = data else {return}
bg.image = data.image
titleLabel.text = data.title
}
}
fileprivate var titleLabel : UILabel = {
let label = UILabel()
label.textAlignment = .left
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 1
label.textColor = .black
label.font = UIFont (name: "Helvetica Neue", size: 30)
label.text = "random text"
return label
}()
fileprivate let bg : UIImageView = {
let iv = UIImageView()
iv.image = #imageLiteral(resourceName: "pic1")
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.layer.cornerRadius = 12
iv.layer.masksToBounds = true
iv.clipsToBounds = true
return iv
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(titleLabel)
contentView.addSubview(bg)
bg.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
this is how the custom cell is set up and below how cellForItemAt is setup
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCell
let color = colorList[indexPath.row]
cell.backgroundColor = color
cell.contentView.layer.masksToBounds = true;
cell.layer.cornerRadius = 12
cell.clipsToBounds = true
return cell
}
any ideas where am I going wrong?

added frame as #rmaddy suggested to titleLable

Try
titleLabel.translatesAutoresizingMaskIntoConstraints = false

Related

TextView text alignment not working within collectionViewCell

I’m having trouble with my TexView here And this method textview.textAlignment = .naturalwon’t work I couldn’t figure out what the problem is here the text only stick to the left side no matter what the language is, now this textview is inside a collectionViewCell, I have tried to work around with the NSSting attributes didn’t work tried also to set the text alignment outside of the Cell didn’t work here is my code you will find messageTextView.textAlignment everywhere and all of this places I set it into didn’t work
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "orderReview", for: indexPath) as! OrderReviewCell
let order = orderreview[indexPath.item]
cell.textBubbleView.backgroundColor = UIColor(white: 0.95, alpha: 1)
cell.messageTextView.textAlignment = .natural
cell.messageTextView.textColor = .black
cell.messageTextView.text = order.order
cell.textBubbleViewRightAnchore?.isActive = false
cell.textBubbleViewLeftAnchore?.isActive = true
if let imgUrl = order.profileImg, imgUrl != "" {
cell.profileImg.loadImageUsingCacheWithUrlStringAndPlaceHolder(urlString: imgUrl)
}
cell.profileImg.isHidden = false
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 8, left: 0, bottom: 2, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var height: CGFloat = 80
let order = orderreview[indexPath.item]
if let text = order.order, text != "" {
height = estmatedFrameForText(text: text).height + 20
}
let width = UIScreen.main.bounds.width
return CGSize(width: width, height: height)
}
private func estmatedFrameForText(text: String) -> CGRect {
let size = CGSize(width: 250, height: 1000)
let options = NSStringDrawingOptions.usesFontLeading.union(.usesDeviceMetrics)
let style = NSMutableParagraphStyle()
style.alignment = NSTextAlignment.natural
return NSAttributedString(string: text, attributes: [ NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16), NSAttributedString.Key.paragraphStyle: style ]).boundingRect(with: size, options: options, context: nil)
}
}
class OrderReviewCell: UICollectionViewCell{
let messageTextView: UITextView = {
let tv = UITextView()
tv.font = UIFont.systemFont(ofSize: 16)
tv.textAlignment = .natural
tv.backgroundColor = .clear
tv.isUserInteractionEnabled = false
tv.translatesAutoresizingMaskIntoConstraints = false
return tv
}()
let textBubbleView: UIView = {
let view = UIView()
view.layer.cornerRadius = 15
view.layer.masksToBounds = true
view.backgroundColor = .red
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let profileImg: UIImageView = {
let img = UIImageView(image: imageLiteral(resourceName: "ProfileHolder"))
img.contentMode = .scaleAspectFill
img.layer.cornerRadius = 16
img.layer.masksToBounds = true
img.translatesAutoresizingMaskIntoConstraints = false
return img
}()
var textBubbleViewWidth: NSLayoutConstraint?
var textBubbleViewRightAnchore: NSLayoutConstraint?
var textBubbleViewLeftAnchore: NSLayoutConstraint?
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(textBubbleView)
addSubview(messageTextView)
addSubview(profileImg)
setupLayout()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupLayout(){
profileImg.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 8).isActive = true
profileImg.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
profileImg.widthAnchor.constraint(equalToConstant: 32).isActive = true
profileImg.heightAnchor.constraint(equalToConstant: 32).isActive = true
textBubbleView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
textBubbleView.heightAnchor.constraint(equalTo: self.heightAnchor).isActive = true
textBubbleViewWidth = textBubbleView.widthAnchor.constraint(equalToConstant: 200)
textBubbleViewWidth?.isActive = true
textBubbleViewRightAnchore = textBubbleView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -8)
textBubbleViewRightAnchore?.isActive = true
textBubbleViewLeftAnchore = textBubbleView.leftAnchor.constraint(equalTo: profileImg.rightAnchor, constant: 8)
textBubbleViewLeftAnchore?.isActive = true
messageTextView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
messageTextView.rightAnchor.constraint(equalTo: self.textBubbleView.rightAnchor).isActive = true
messageTextView.heightAnchor.constraint(equalTo: self.heightAnchor).isActive = true
messageTextView.leftAnchor.constraint(equalTo: self.textBubbleView.leftAnchor, constant: 8).isActive = true
}
}

How do I access content of a uicollectionviewcell in a view controller?

I'm trying add a bottom border to a textfield inside a UICollectionViewCell, I registered the cell inside a view controller where my collection view is. But to set the size of the bottom border I need to the it own size, and I don't know how to do it inside the collection view cell, so Im trying to pass It to the view controller where It Is registered, but no success yet.
*Obs: I cut out some parts of the code because is not relevant.
UICollectionViewCell
class NameStepCell: UICollectionViewCell {
let safeAreaHolder: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let title: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.font = UIFont.boldSystemFont(ofSize: 40)
label.text = "What is\nyour\nname?"
return label
}()
let txtFieldStack: UIStackView = {
let stack = UIStackView()
stack.translatesAutoresizingMaskIntoConstraints = false
stack.alignment = .center
stack.axis = .horizontal
stack.distribution = .fillEqually
stack.spacing = 20
return stack
}()
let nameField: UITextField = {
let txtFld = UITextField()
txtFld.keyboardType = UIKeyboardType.default
txtFld.textContentType = UITextContentType.name
txtFld.autocapitalizationType = UITextAutocapitalizationType.words
txtFld.autocorrectionType = .no
txtFld.textColor = UIColor.black
return txtFld
}()
let lastNameField: UITextField = {
let txtFld = UITextField()
txtFld.keyboardType = UIKeyboardType.default
txtFld.textContentType = UITextContentType.familyName
txtFld.autocapitalizationType = UITextAutocapitalizationType.words
txtFld.autocorrectionType = .no
txtFld.textColor = UIColor.black
return txtFld
}()
override init(frame: CGRect) {
super.init(frame: frame)
configuringView()
configuringTitle()
configuringTxtField()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configuringView(){
addSubview(safeAreaHolder)
safeAreaHolder.topAnchor.constraint(equalTo: topAnchor).isActive = true
safeAreaHolder.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16).isActive = true
safeAreaHolder.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
safeAreaHolder.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16).isActive = true
}
func configuringTitle(){
safeAreaHolder.addSubview(title)
title.topAnchor.constraint(equalTo: safeAreaHolder.topAnchor, constant: 50).isActive = true
title.trailingAnchor.constraint(equalTo: safeAreaHolder.trailingAnchor).isActive = true
title.leadingAnchor.constraint(equalTo: safeAreaHolder.leadingAnchor).isActive = true
}
func configuringTxtField(){
safeAreaHolder.addSubview(txtFieldStack)
txtFieldStack.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 50).isActive = true
txtFieldStack.trailingAnchor.constraint(equalTo: safeAreaHolder.trailingAnchor).isActive = true
txtFieldStack.leadingAnchor.constraint(equalTo: safeAreaHolder.leadingAnchor).isActive = true
txtFieldStack.addArrangedSubview(nameField)
txtFieldStack.addArrangedSubview(lastNameField)
nameField.heightAnchor.constraint(equalToConstant: 45).isActive = true
lastNameField.heightAnchor.constraint(equalToConstant: 45).isActive = true
}
}
UIViewController
class SignupViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate, UICollectionViewDataSource{
let stepsCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.backgroundColor = .white
collectionView.contentInsetAdjustmentBehavior = UIScrollView.ContentInsetAdjustmentBehavior.never
collectionView.isPagingEnabled = true
collectionView.showsHorizontalScrollIndicator = false
collectionView.isScrollEnabled = false
return collectionView
}()
override func viewDidLoad() {
super.viewDidLoad()
stepsCollectionView.dataSource = self
stepsCollectionView.delegate = self
stepsCollectionView.register(NameStepCell.self, forCellWithReuseIdentifier: "nameStepId")
stepsCollectionView.register(GenderStepCell.self, forCellWithReuseIdentifier: "genderStepId")
stepsCollectionView.register(BirthdayStepCell.self, forCellWithReuseIdentifier: "birthdayStepId")
stepsCollectionView.register(EmailStepCell.self, forCellWithReuseIdentifier: "emailStepId")
stepsCollectionView.register(PasswordStepCell.self, forCellWithReuseIdentifier: "passwordStepId")
view.backgroundColor = .white
configuringBottomButton()
configuringStepCollectionView()
}
override func viewDidAppear(_ animated: Bool) {
}
Here is where I try to get the nameFied to add the border
override func viewDidLayoutSubviews() {
NameStepCell().self.nameField.addBottomBorder()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 1 {
let genderCell = collectionView.dequeueReusableCell(withReuseIdentifier: "genderStepId", for: indexPath)
return genderCell
}else if indexPath.item == 2{
let birthdayCell = collectionView.dequeueReusableCell(withReuseIdentifier: "birthdayStepId", for: indexPath)
return birthdayCell
}else if indexPath.item == 3{
let emailCell = collectionView.dequeueReusableCell(withReuseIdentifier: "emailStepId", for: indexPath)
return emailCell
}else if indexPath.item == 4{
let passwordCell = collectionView.dequeueReusableCell(withReuseIdentifier: "passwordStepId", for: indexPath)
return passwordCell
}
let nameCell = collectionView.dequeueReusableCell(withReuseIdentifier: "nameStepId", for: indexPath)
return nameCell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: stepsCollectionView.frame.size.width, height: stepsCollectionView.frame.size.height)
}
}
Extension to textfield to add the bottom border
extension UITextField {
func addBottomBorder() {
let border = CALayer()
border.frame = CGRect(x: 0, y: 32, width: self.frame.size.width, height: 1)
border.cornerRadius = 2
border.masksToBounds = true
border.backgroundColor = UIColor.init(red: 112/255, green: 112/255, blue: 112/255, alpha: 1).cgColor
self.layer.masksToBounds = true
self.layer.addSublayer(border)
}
}
Instead of calling addBottomBar() inside viewDidLayoutSubviews, you can try something like this.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 1 {
let genderCell = collectionView.dequeueReusableCell(withReuseIdentifier: "genderStepId", for: indexPath)
return genderCell
}else if indexPath.item == 2{
let birthdayCell = collectionView.dequeueReusableCell(withReuseIdentifier: "birthdayStepId", for: indexPath)
return birthdayCell
}else if indexPath.item == 3{
let emailCell = collectionView.dequeueReusableCell(withReuseIdentifier: "emailStepId", for: indexPath)
return emailCell
}else if indexPath.item == 4{
let passwordCell = collectionView.dequeueReusableCell(withReuseIdentifier: "passwordStepId", for: indexPath)
return passwordCell
}
// Dequeue your NameStepCell from collection view
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "nameStepId", for: indexPath)
if let nameCell = cell as? NameStepCell {
// Add bottom border to it right here and return it
nameCell.nameField.addBottomBorder()
return nameCell
}
return cell
}
Edit:
Now you don't need to change anything in your SignUpViewController. Please replace your NameStepCell class with the below code.
class NameStepCell: UICollectionViewCell {
var safeAreaHolder: UIView!
var title: UILabel!
var txtFieldStack: UIStackView!
var nameField: UITextField!
var lastNameField: UITextField!
override init(frame: CGRect) {
super.init(frame: frame)
configuringView()
configuringTitle()
configuringTxtField()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
private extension NameStepCell {
func configuringView(){
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
self.safeAreaHolder = view
addSubview(safeAreaHolder)
safeAreaHolder.topAnchor.constraint(equalTo: topAnchor).isActive = true
safeAreaHolder.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16).isActive = true
safeAreaHolder.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
safeAreaHolder.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16).isActive = true
self.safeAreaHolder.layoutIfNeeded()
}
func configuringTitle(){
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.font = UIFont.boldSystemFont(ofSize: 40)
label.text = "What is\nyour\nname?"
self.title = label
safeAreaHolder.addSubview(title)
title.topAnchor.constraint(equalTo: safeAreaHolder.topAnchor, constant: 50).isActive = true
title.trailingAnchor.constraint(equalTo: safeAreaHolder.trailingAnchor).isActive = true
title.leadingAnchor.constraint(equalTo: safeAreaHolder.leadingAnchor).isActive = true
self.title.layoutIfNeeded()
}
func configuringTxtField(){
let stack = UIStackView()
stack.backgroundColor = .lightGray
stack.translatesAutoresizingMaskIntoConstraints = false
stack.alignment = .center
stack.axis = .horizontal
stack.distribution = .fillEqually
stack.spacing = 20
self.txtFieldStack = stack
safeAreaHolder.addSubview(txtFieldStack)
txtFieldStack.topAnchor.constraint(equalTo: title.bottomAnchor, constant: 50).isActive = true
txtFieldStack.trailingAnchor.constraint(equalTo: safeAreaHolder.trailingAnchor).isActive = true
txtFieldStack.leadingAnchor.constraint(equalTo: safeAreaHolder.leadingAnchor).isActive = true
self.txtFieldStack.layoutIfNeeded()
self.nameField = getTextField(.name)
self.lastNameField = getTextField(.familyName)
txtFieldStack.addArrangedSubview(nameField)
txtFieldStack.addArrangedSubview(lastNameField)
nameField.heightAnchor.constraint(equalToConstant: 45).isActive = true
lastNameField.heightAnchor.constraint(equalToConstant: 45).isActive = true
// After adding constraints, you should call 'layoutIfNeeded()' which recomputes the size and position based on the constraints you've set
self.nameField.layoutIfNeeded()
self.lastNameField.layoutIfNeeded()
self.nameField.addBottomBorder()
self.lastNameField.addBottomBorder()
}
func getTextField(_ textContentType: UITextContentType) -> UITextField {
let textField = UITextField()
textField.keyboardType = .default
textField.textContentType = textContentType
textField.autocapitalizationType = .words
textField.autocorrectionType = .no
textField.textColor = .black
textField.placeholder = textContentType.rawValue // P.S. Remove placeholder if you don't need.
return textField
}
}

How can I match Custom View's frame with TableViewCell frame properly?

I have a TableView which contains image stretched into cell and I added a view for darkening the image. Since I want to draw this view only in the beginning and not every time I scroll in table I added my codes into awakeFromNib in TableViewCell.
TableViewCell.swift
#IBOutlet weak var equipmentImageView: UIImageView!
let darkFilter = UIView()
override func awakeFromNib() {
super.awakeFromNib()
darkFilter.backgroundColor = .black
darkFilter.layer.opacity = 0.6
darkFilter.frame = self.equipmentImageView.frame
equipmentImageView.addSubview(darkFilter)
}
My problem is that this view will not have the same width with the ImageView, so the effect I'm trying to implement takes half of the screen.
I followed this solution but the problem is that this solution will only apply after the cells recreate themselves by scrolling down and up again.
TableViewCell.swift
override func layoutSubviews() {
super.layoutSubviews()
darkFilter.backgroundColor = .black
darkFilter.layer.opacity = 0.6
darkFilter.frame = self.equipmentImageView.frame
equipmentImageView.addSubview(darkFilter)
}
How can I apply this solution before the cells are created and will not redraw when scrolling through it?
You could set the cell's .background color to .black, and then lower the alpha of the equipmentImageView and you'd achieve the same darkened effect without having to add a new UIView.
EDIT
To illustrate my point: here's a really sloppy and quick example I drew up in Playground with an image titled "Untitled.jpg" to prove fading the image with a black cell background works the same as adding a faded black layer on top of a cell with an image:
Picture of result:
code:
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
class CustomTableViewCell: UITableViewCell {
let myImageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
if let sample = Bundle.main.path(forResource: "Untitled", ofType: "jpg") {
let image = UIImage(contentsOfFile: sample)
imageView.image = image
}
imageView.clipsToBounds = true
return imageView
}()
let blackView: UIView = {
let myView = UIView()
myView.translatesAutoresizingMaskIntoConstraints = false
myView.backgroundColor = .black
return myView
}()
let title: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = .white
label.font = UIFont.systemFont(ofSize: 12)
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
backgroundColor = .black
let views = [myImageView,
blackView,
title]
views.forEach {
contentView.addSubview($0)
NSLayoutConstraint.activate([
$0.heightAnchor.constraint(equalTo: contentView.heightAnchor),
$0.widthAnchor.constraint(equalTo: contentView.widthAnchor),
$0.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
$0.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
])
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setCellViews(indexPath: IndexPath) {
blackView.alpha = 0
if indexPath.row % 2 == 0 {
if indexPath.row % 4 == 0 {
blackView.alpha = 0.4
title.text = "blackLayer added and faded"
} else {
backgroundColor = .black
myImageView.alpha = 0.6
title.text = "backView faded"
}
} else {
title.text = "not faded at all"
}
}
}
private let reuseId = "cellId"
class MyViewController : UIViewController {
let tableView: UITableView = {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.separatorStyle = .none
return tableView
}()
let data = ["one", "two", "three", "four", "five"]
override func viewDidLoad() {
super.viewDidLoad()
setTableView()
}
func setTableView() {
tableView.dataSource = self
tableView.delegate = self
tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: reuseId)
view.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.heightAnchor.constraint(equalTo: view.heightAnchor),
tableView.widthAnchor.constraint(equalTo: view.widthAnchor),
tableView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
tableView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
])
}
}
extension MyViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseId, for: indexPath) as! CustomTableViewCell
cell.setCellViews(indexPath: indexPath)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
2 suggestions:
1) Since you are dealing with IBOutlets for the cell, you could also add the view on the IB on top of the image view, and then adding constrains to it to match up the image view size.
2) If you are aiming to adding it programmatically, you might need to setup its constraints based on the cell content view. For example:
darkFilter.backgroundColor = .black
darkFilter.layer.opacity = 0.6
contentView.addSubview(darkFilter)
darkFilter.translatesAutoresizingMaskIntoConstraints = false
darkFilter.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
darkFilter.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
darkFilter.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
darkFilter.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true

How to create UICollectionViewCell programmatically

I'm trying to create UICollectionView programatically.
I need to add labels inside the cells, so I Created CollectionViewCell class.
This is the class:
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
And this is the collectionView implementation class:
import UIKit
class TwoViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {
let leftAndRightPaddings: CGFloat = 80.0
let numberOfItemsPerRow: CGFloat = 7.0
let screenSize: CGRect = UIScreen.main.bounds
private let cellReuseIdentifier = "collectionCell"
var items = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"]
override func viewDidLoad() {
super.viewDidLoad()
let flowLayout = UICollectionViewFlowLayout()
let collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: flowLayout)
collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "collectionCell")
collectionView.delegate = self
collectionView.dataSource = self
collectionView.backgroundColor = UIColor.cyan
self.view.addSubview(collectionView)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return self.items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as! MyCollectionViewCell
cell.backgroundColor = UIColor.green
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let width = (screenSize.width-leftAndRightPaddings)/numberOfItemsPerRow
return CGSize(width: width, height: width)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
{
return UIEdgeInsets(top: 20, left: 8, bottom: 5, right: 8)
}
}
The error happens when the cell produced:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellReuseIdentifier, forIndexPath: indexPath) as! MyCollectionViewCell
The error is:
Could not cast value of type 'UICollectionViewCell' (0x1033cc820) to 'CollectionViewProgramatically.MyCollectionViewCell' (0x1015a4f88).
Try to copy and paste this code into your xcode, it should work
//
// HomeVIewController.swift
// Photolancer
//
// Created by Lee SangJoon on 9/8/16.
// Copyright © 2016 Givnite. All rights reserved.
//
import UIKit
class HomeViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var collectionview: UICollectionView!
var cellId = "Cell"
override func viewDidLoad() {
super.viewDidLoad()
// Create an instance of UICollectionViewFlowLayout since you cant
// Initialize UICollectionView without a layout
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: view.frame.width, height: 700)
collectionview = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionview.dataSource = self
collectionview.delegate = self
collectionview.registerClass(FreelancerCell.self, forCellWithReuseIdentifier: cellId)
collectionview.showsVerticalScrollIndicator = false
collectionview.backgroundColor = UIColor.whiteColor()
self.view.addSubview(collectionview)
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionview.dequeueReusableCellWithReuseIdentifier(cellId, forIndexPath: indexPath) as! FreelancerCell
return cell
}
}
class FreelancerCell: UICollectionViewCell {
let profileImageButton: UIButton = {
let button = UIButton()
button.backgroundColor = UIColor.whiteColor()
button.layer.cornerRadius = 18
button.clipsToBounds = true
button.setImage(UIImage(named: "Profile"), forState: .Normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let nameLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFontOfSize(14)
label.textColor = UIColor.darkGrayColor()
label.text = "Bob Lee"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let distanceLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.lightGrayColor()
label.font = UIFont.systemFontOfSize(14)
label.text = "30000 miles"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let pricePerHourLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.darkGrayColor()
label.font = UIFont.systemFontOfSize(14)
label.text = "$40/hour"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let ratingLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.lightGrayColor()
label.font = UIFont.systemFontOfSize(14)
label.text = "4.9+"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let showCaseImageView: UIImageView = {
let imageView = UIImageView()
imageView.backgroundColor = UIColor.whiteColor()
imageView.image = UIImage(named: "Profile")
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let likesLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.lightGrayColor()
label.font = UIFont.systemFontOfSize(14)
label.text = "424 likes"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let topSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.darkGrayColor()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let bottomSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.darkGrayColor()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let likeButton: UIButton = {
let button = UIButton()
button.setTitle("Like", forState: .Normal)
button.titleLabel?.font = UIFont.systemFontOfSize(18)
button.setTitleColor(UIColor.darkGrayColor(), forState: .Normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let hireButton: UIButton = {
let button = UIButton()
button.setTitle("Hire", forState: .Normal)
button.titleLabel?.font = UIFont.systemFontOfSize(18)
button.setTitleColor(UIColor.darkGrayColor(), forState: .Normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let messageButton: UIButton = {
let button = UIButton()
button.setTitle("Message", forState: .Normal)
button.titleLabel?.font = UIFont.systemFontOfSize(18)
button.setTitleColor(UIColor.darkGrayColor(), forState: .Normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let stackView: UIStackView = {
let sv = UIStackView()
sv.axis = UILayoutConstraintAxis.Horizontal
sv.alignment = UIStackViewAlignment.Center
sv.distribution = UIStackViewDistribution.FillEqually
sv.translatesAutoresizingMaskIntoConstraints = false;
return sv
}()
override init(frame: CGRect) {
super.init(frame: frame)
addViews()
}
func addViews(){
backgroundColor = UIColor.blackColor()
addSubview(profileImageButton)
addSubview(nameLabel)
addSubview(distanceLabel)
addSubview(pricePerHourLabel)
addSubview(ratingLabel)
addSubview(showCaseImageView)
addSubview(likesLabel)
addSubview(topSeparatorView)
addSubview(bottomSeparatorView)
// Stack View
addSubview(likeButton)
addSubview(messageButton)
addSubview(hireButton)
addSubview(stackView)
profileImageButton.leftAnchor.constraintEqualToAnchor(leftAnchor, constant: 5).active = true
profileImageButton.topAnchor.constraintEqualToAnchor(topAnchor, constant: 10).active = true
profileImageButton.heightAnchor.constraintEqualToConstant(36).active = true
profileImageButton.widthAnchor.constraintEqualToConstant(36).active = true
nameLabel.leftAnchor.constraintEqualToAnchor(profileImageButton.rightAnchor, constant: 5).active = true
nameLabel.centerYAnchor.constraintEqualToAnchor(profileImageButton.centerYAnchor, constant: -8).active = true
nameLabel.rightAnchor.constraintEqualToAnchor(pricePerHourLabel.leftAnchor).active = true
distanceLabel.leftAnchor.constraintEqualToAnchor(nameLabel.leftAnchor).active = true
distanceLabel.centerYAnchor.constraintEqualToAnchor(profileImageButton.centerYAnchor, constant: 8).active = true
distanceLabel.widthAnchor.constraintEqualToConstant(300)
pricePerHourLabel.rightAnchor.constraintEqualToAnchor(rightAnchor, constant: -10).active = true
pricePerHourLabel.centerYAnchor.constraintEqualToAnchor(nameLabel.centerYAnchor).active = true
// Distance depeneded on the priceLabel and distance Label
ratingLabel.rightAnchor.constraintEqualToAnchor(pricePerHourLabel.rightAnchor).active = true
ratingLabel.centerYAnchor.constraintEqualToAnchor(distanceLabel.centerYAnchor).active = true
showCaseImageView.topAnchor.constraintEqualToAnchor(profileImageButton.bottomAnchor, constant: 10).active = true
showCaseImageView.widthAnchor.constraintEqualToAnchor(widthAnchor).active = true
showCaseImageView.heightAnchor.constraintEqualToConstant(UIScreen.mainScreen().bounds.width - 20).active = true
likesLabel.topAnchor.constraintEqualToAnchor(showCaseImageView.bottomAnchor, constant: 10).active = true
likesLabel.leftAnchor.constraintEqualToAnchor(profileImageButton.leftAnchor).active = true
topSeparatorView.topAnchor.constraintEqualToAnchor(likesLabel.bottomAnchor, constant: 10).active = true
topSeparatorView.widthAnchor.constraintEqualToAnchor(widthAnchor).active = true
topSeparatorView.heightAnchor.constraintEqualToConstant(0.5).active = true
stackView.addArrangedSubview(likeButton)
stackView.addArrangedSubview(hireButton)
stackView.addArrangedSubview(messageButton)
stackView.topAnchor.constraintEqualToAnchor(topSeparatorView.bottomAnchor, constant: 4).active = true
stackView.widthAnchor.constraintEqualToAnchor(widthAnchor).active = true
stackView.centerXAnchor.constraintEqualToAnchor(centerXAnchor).active = true
bottomSeparatorView.topAnchor.constraintEqualToAnchor(stackView.bottomAnchor, constant: 4).active = true
bottomSeparatorView.widthAnchor.constraintEqualToAnchor(widthAnchor).active = true
bottomSeparatorView.heightAnchor.constraintEqualToConstant(0.5).active = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Your problem lies here. In your viewDidLoad(), you're registering your collectionView cell twice. You are registering the collectionview's cell to your custom cell class in the first line and then in the second line you are registering it to the class UICollectionViewCell.
collectionView.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)
collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "collectionCell")
Just remove the second line and your code should work.
I changed Bob Lee answer for swift 4
import UIKit
class noNibCollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var collectionview: UICollectionView!
var cellId = "Cell"
override func viewDidLoad() {
super.viewDidLoad()
// Create an instance of UICollectionViewFlowLayout since you cant
// Initialize UICollectionView without a layout
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: view.frame.width, height: 700)
collectionview = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionview.dataSource = self
collectionview.delegate = self
collectionview.register(FreelancerCell.self, forCellWithReuseIdentifier: cellId)
collectionview.showsVerticalScrollIndicator = false
collectionview.backgroundColor = UIColor.white
self.view.addSubview(collectionview)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionview.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FreelancerCell
return cell
}
}
class FreelancerCell: UICollectionViewCell {
let profileImageButton: UIButton = {
let button = UIButton()
button.backgroundColor = UIColor.white
button.layer.cornerRadius = 18
button.clipsToBounds = true
button.setImage(UIImage(named: "Profile"), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let nameLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 14)
label.textColor = UIColor.darkGray
label.text = "Bob Lee"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let distanceLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.lightGray
label.font = UIFont.systemFont(ofSize: 14)
label.text = "30000 miles"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let pricePerHourLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.darkGray
label.font = UIFont.systemFont(ofSize: 14)
label.text = "$40/hour"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let ratingLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.lightGray
label.font = UIFont.systemFont(ofSize: 14)
label.text = "4.9+"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let showCaseImageView: UIImageView = {
let imageView = UIImageView()
imageView.backgroundColor = UIColor.white
imageView.image = UIImage(named: "Profile")
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let likesLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.lightGray
label.font = UIFont.systemFont(ofSize: 14)
label.text = "424 likes"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let topSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.darkGray
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let bottomSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.darkGray
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let likeButton: UIButton = {
let button = UIButton()
button.setTitle("Like", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
button.setTitleColor(UIColor.darkGray, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let hireButton: UIButton = {
let button = UIButton()
button.setTitle("Hire", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
button.setTitleColor(UIColor.darkGray, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let messageButton: UIButton = {
let button = UIButton()
button.setTitle("Message", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
button.setTitleColor(UIColor.darkGray, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let stackView: UIStackView = {
let sv = UIStackView()
sv.axis = UILayoutConstraintAxis.horizontal
sv.alignment = UIStackViewAlignment.center
sv.distribution = UIStackViewDistribution.fillEqually
sv.translatesAutoresizingMaskIntoConstraints = false;
return sv
}()
override init(frame: CGRect) {
super.init(frame: frame)
addViews()
}
func addViews(){
backgroundColor = UIColor.black
addSubview(profileImageButton)
addSubview(nameLabel)
addSubview(distanceLabel)
addSubview(pricePerHourLabel)
addSubview(ratingLabel)
addSubview(showCaseImageView)
addSubview(likesLabel)
addSubview(topSeparatorView)
addSubview(bottomSeparatorView)
// Stack View
addSubview(likeButton)
addSubview(messageButton)
addSubview(hireButton)
addSubview(stackView)
profileImageButton.leftAnchor.constraint(equalTo: leftAnchor, constant: 5).isActive = true
profileImageButton.topAnchor.constraint(equalTo: topAnchor, constant: 10).isActive = true
profileImageButton.heightAnchor.constraint(equalToConstant: 36).isActive = true
profileImageButton.widthAnchor.constraint(equalToConstant: 36).isActive = true
nameLabel.leftAnchor.constraint(equalTo: profileImageButton.rightAnchor, constant: 5).isActive = true
nameLabel.centerYAnchor.constraint(equalTo: profileImageButton.centerYAnchor, constant: -8).isActive = true
nameLabel.rightAnchor.constraint(equalTo: pricePerHourLabel.leftAnchor).isActive = true
distanceLabel.leftAnchor.constraint(equalTo: nameLabel.leftAnchor).isActive = true
distanceLabel.centerYAnchor.constraint(equalTo: profileImageButton.centerYAnchor, constant: 8).isActive = true
distanceLabel.widthAnchor.constraint(equalToConstant: 300)
pricePerHourLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -10).isActive = true
pricePerHourLabel.centerYAnchor.constraint(equalTo: nameLabel.centerYAnchor).isActive = true
// Distance depeneded on the priceLabel and distance Label
ratingLabel.rightAnchor.constraint(equalTo: pricePerHourLabel.rightAnchor).isActive = true
ratingLabel.centerYAnchor.constraint(equalTo: distanceLabel.centerYAnchor).isActive = true
showCaseImageView.topAnchor.constraint(equalTo: profileImageButton.bottomAnchor, constant: 10).isActive = true
showCaseImageView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
showCaseImageView.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.width - 20).isActive = true
likesLabel.topAnchor.constraint(equalTo: showCaseImageView.bottomAnchor, constant: 10).isActive = true
likesLabel.leftAnchor.constraint(equalTo: profileImageButton.leftAnchor).isActive = true
topSeparatorView.topAnchor.constraint(equalTo: likesLabel.bottomAnchor, constant: 10).isActive = true
topSeparatorView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
topSeparatorView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
stackView.addArrangedSubview(likeButton)
stackView.addArrangedSubview(hireButton)
stackView.addArrangedSubview(messageButton)
stackView.topAnchor.constraint(equalTo: topSeparatorView.bottomAnchor, constant: 4).isActive = true
stackView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
stackView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
bottomSeparatorView.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 4).isActive = true
bottomSeparatorView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
bottomSeparatorView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Response of Bob Lee updated to Swift 5.1
class HomeViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var collectionview: UICollectionView!
var cellId = "Cell"
override func viewDidLoad() {
super.viewDidLoad()
// Create an instance of UICollectionViewFlowLayout since you cant
// Initialize UICollectionView without a layout
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: view.frame.width, height: 700)
collectionview = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionview.dataSource = self
collectionview.delegate = self
collectionview.register(FreelancerCell.self, forCellWithReuseIdentifier: cellId)
collectionview.showsVerticalScrollIndicator = false
collectionview.backgroundColor = UIColor.white
self.view.addSubview(collectionview)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionview.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath as IndexPath) as! FreelancerCell
return cell
}
}
class FreelancerCell: UICollectionViewCell {
let profileImageButton: UIButton = {
let button = UIButton()
button.backgroundColor = UIColor.white
button.layer.cornerRadius = 18
button.clipsToBounds = true
button.setImage(UIImage(named: "Profile"), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let nameLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 14)
label.textColor = UIColor.darkGray
label.text = "Bob Lee"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let distanceLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.lightGray
label.font = UIFont.systemFont(ofSize: 14)
label.text = "30000 miles"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let pricePerHourLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.darkGray
label.font = UIFont.systemFont(ofSize: 14)
label.text = "$40/hour"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let ratingLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.lightGray
label.font = UIFont.systemFont(ofSize: 14)
label.text = "4.9+"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let showCaseImageView: UIImageView = {
let imageView = UIImageView()
imageView.backgroundColor = UIColor.white
imageView.image = UIImage(named: "Profile")
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
let likesLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.lightGray
label.font = UIFont.systemFont(ofSize: 14)
label.text = "424 likes"
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let topSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.darkGray
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let bottomSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.darkGray
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let likeButton: UIButton = {
let button = UIButton()
button.setTitle("Like", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
button.setTitleColor(UIColor.darkGray, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let hireButton: UIButton = {
let button = UIButton()
button.setTitle("Hire", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
button.setTitleColor(UIColor.darkGray, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let messageButton: UIButton = {
let button = UIButton()
button.setTitle("Message", for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
button.setTitleColor(UIColor.darkGray, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let stackView: UIStackView = {
let sv = UIStackView()
sv.axis = NSLayoutConstraint.Axis.horizontal
sv.alignment = UIStackView.Alignment.center
sv.distribution = UIStackView.Distribution.fillEqually
sv.translatesAutoresizingMaskIntoConstraints = false;
return sv
}()
override init(frame: CGRect) {
super.init(frame: frame)
addViews()
}
func addViews(){
backgroundColor = UIColor.black
addSubview(profileImageButton)
addSubview(nameLabel)
addSubview(distanceLabel)
addSubview(pricePerHourLabel)
addSubview(ratingLabel)
addSubview(showCaseImageView)
addSubview(likesLabel)
addSubview(topSeparatorView)
addSubview(bottomSeparatorView)
// Stack View
addSubview(likeButton)
addSubview(messageButton)
addSubview(hireButton)
addSubview(stackView)
profileImageButton.leftAnchor.constraint(equalTo: leftAnchor, constant: 5).isActive = true
profileImageButton.topAnchor.constraint(equalTo: topAnchor, constant: 10).isActive = true
profileImageButton.heightAnchor.constraint(equalToConstant: 36).isActive = true
profileImageButton.widthAnchor.constraint(equalToConstant: 36).isActive = true
nameLabel.leftAnchor.constraint(equalTo: profileImageButton.rightAnchor, constant: 5).isActive = true
nameLabel.centerYAnchor.constraint(equalTo: profileImageButton.centerYAnchor, constant: -8).isActive = true
nameLabel.rightAnchor.constraint(equalTo: pricePerHourLabel.leftAnchor).isActive = true
distanceLabel.leftAnchor.constraint(equalTo: nameLabel.leftAnchor).isActive = true
distanceLabel.centerYAnchor.constraint(equalTo: profileImageButton.centerYAnchor, constant: 8).isActive = true
distanceLabel.widthAnchor.constraint(equalToConstant: 300)
pricePerHourLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -10).isActive = true
pricePerHourLabel.centerYAnchor.constraint(equalTo: nameLabel.centerYAnchor).isActive = true
// Distance depeneded on the priceLabel and distance Label
ratingLabel.rightAnchor.constraint(equalTo: pricePerHourLabel.rightAnchor).isActive = true
ratingLabel.centerYAnchor.constraint(equalTo: distanceLabel.centerYAnchor).isActive = true
showCaseImageView.topAnchor.constraint(equalTo: profileImageButton.bottomAnchor, constant: 10).isActive = true
showCaseImageView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
showCaseImageView.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.width - 20).isActive = true
likesLabel.topAnchor.constraint(equalTo: showCaseImageView.bottomAnchor, constant: 10).isActive = true
likesLabel.leftAnchor.constraint(equalTo: profileImageButton.leftAnchor).isActive = true
topSeparatorView.topAnchor.constraint(equalTo: likesLabel.bottomAnchor, constant: 10).isActive = true
topSeparatorView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
topSeparatorView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
stackView.addArrangedSubview(likeButton)
stackView.addArrangedSubview(hireButton)
stackView.addArrangedSubview(messageButton)
stackView.topAnchor.constraint(equalTo: topSeparatorView.bottomAnchor, constant: 4).isActive = true
stackView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
stackView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
bottomSeparatorView.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 4).isActive = true
bottomSeparatorView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
bottomSeparatorView.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
let collection :UICollectionView = {
let layout = UICollectionViewFlowLayout()
let collection = UICollectionView(frame: CGRect(x: 0, y: 0, width: 0, height: 0), collectionViewLayout: layout)
layout.scrollDirection = .horizontal
collection.translatesAutoresizingMaskIntoConstraints = false
collection.backgroundColor = .clear
return collection
}()

UICollectionView Section headers & footers show wrong way - iOS

The problem is:
SupplementaryView has a textLabel on it, but the text appears at a wrong location while header and footer and textLabel just show right.
As you can see in the picture, only the first section header has a title, other header or footers text is out of sight(they are on the screen but you have to scroll down to see it).
I don't know how to solve it...
I setup my collectionview like following in viewDidLoad function:
func setupCollectionsView(){
let width:CGFloat = self.view.frame.size.width/4
let flowLayout = UICollectionViewFlowLayout()
flowLayout.minimumInteritemSpacing = 5
flowLayout.minimumLineSpacing = 5
flowLayout.estimatedItemSize = CGSizeMake(width, width)
flowLayout.headerReferenceSize = CGSizeMake(self.view.frame.size.width, 30)
flowLayout.footerReferenceSize = CGSizeMake(self.view.frame.size.width, 30)
flowLayout.scrollDirection = UICollectionViewScrollDirection.Vertical
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: flowLayout)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.registerClass(FuncViewCell.self, forCellWithReuseIdentifier: "collectionView")
collectionView.backgroundColor = UIColor.clearColor()
collectionView.registerClass(SupplementaryView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerView")
collectionView.registerClass(SupplementaryView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "footerView")
self.view.addSubview(collectionView)
}
For each supplementaryview I write this:
func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
var view:SupplementaryView?
var title:String = ""
switch kind {
case UICollectionElementKindSectionFooter:
view = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "footerView", forIndexPath: indexPath) as? SupplementaryView
view?.backgroundColor = UIColor ( red: 0.9879, green: 0.3225, blue: 0.4925, alpha: 1.0 )
title = "Footer"
default:
view = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "headerView", forIndexPath: indexPath) as? SupplementaryView
view?.backgroundColor = UIColor ( red: 0.6571, green: 1.0, blue: 0.8628, alpha: 1.0 )
title = "Header"
}
switch indexPath.section {
case 0:
title = "First \(title)"
default:
title = "Second \(title)"
}
view?.setTitle(title)
return view!
}
And my supplementary view implemented this way:
class SupplementaryView: UICollectionReusableView{
var titleLabel:UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
titleLabel = UILabel(frame: frame)
self.addSubview(titleLabel)
let gesture = UITapGestureRecognizer(target: self, action: #selector(SupplementaryView.tap))
self.addGestureRecognizer(gesture)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setTitle(title:String){
print("Label's frame is\(titleLabel.frame)")
titleLabel.text = title
}
func tap(){
print("\(titleLabel.text!) tapped")
}}
PS:I print the frame of each textlabel, they are just in right postion.
.
Change you code as below, and to see if it works
override init(frame: CGRect) {
super.init(frame: frame)
// There should be self.bounds
titleLabel = UILabel(frame: self.bounds)
self.addSubview(titleLabel)
let gesture = UITapGestureRecognizer(target: self, action: #selector(SupplementaryView.tap))
self.addGestureRecognizer(gesture)
}