UICollectionViewLayout methods never get called - swift

I am working with a UICollectionView and I am trying to use the UICollectionViewLayout methods to adjust the sizing of the cell however they are never being called. The methods are :
sizeForItemAtIndexPath, minimumInterimItemSpacingForSectionAtIndex, and minimumLineSpacingForSectionAtIndex
these 3 methods are never being called and I'm not sure where/ how to call them from. below is my code in Swift 3
import Foundation
import UIKit
class CollectionVC: UICollectionViewController {
var Sections = [SectionService]()
override func viewDidLoad() {
createServiceSections()
}
func createServiceSections(){
ServiceSections.append(ServiceSection(headerTitle: "1", items: 2, headerImage: UIImage(named: "Default"), stats: nil))
ServiceSections.append(ServiceSection(headerTitle: "2", items: 3, headerImage: UIImage(named: "Default"), stats: nil))
ServiceSections.append(ServiceSection(headerTitle: "3", items: 3, headerImage: UIImage(named: "Default"), stats: nil))
ServiceSections.append(ServiceSection(headerTitle: "4", items: 5, headerImage: UIImage(named: "Default"), stats: nil))
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return ServiceSections.count
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return ServiceSections[indexPath.section].items.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell1 = collectionView.dequeueReusableCell(withReuseIdentifier: "servicecell", for: indexPath) as! ServicesCellView
cell1.serviceLabel.text = "test"
cell1.serviceImage.image = ServiceSections[indexPath.section].headerImage
return cell1
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
print("size for item at indexPath")
var cellSize: CGSize
let collectionViewWidth = self.collectionView!.bounds.size.width
cellSize = CGSize(width: (collectionViewWidth * 0.48), height: (collectionViewWidth * 0.48))
return cellSize
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInterItemSpacingForSectionAtIndex section: Int) -> CGFloat {
print("min spacing section")
return 1
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
print("min line spacing section")
return 1
}
}

With help from Xinatanil, I was able to fix the issue. First, I had to change my class line to this
class CollectionVC: UICollectionViewController, UICollectionViewDelegateFlowLayout {
and then I had to change the methods declarations to Swift 3 syntax...
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var cellSize: CGSize
let collectionViewWidth = self.collectionView!.bounds.size.width
cellSize = CGSize(width: (collectionViewWidth * 0.48), height: (collectionViewWidth * 0.48))
return cellSize
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1
}

I think, you haven't set collectionView delegate
Please try:
self.collectionView.delegate = self in viewDidLoad() method
Actually UICollectionViewDelegateFlowLayout inherits from UICollectionViewDelegate. So setting the delegate will be sufficient.
Happy Coding!

Related

using UiCollectionView I don't want too large central space on iPhone 11

the issue:
only on iPhone 11, I have two columns of cells, with very big space in the center, on other devices I have 3 cells on 2 columns, I'd like same result on iPhone 11 too
at this moment my solution is minimumInteritemSpacingForSectionAt from 16 to 5, is there a better solution?
what I am using:
let sectionInsets = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 16.0, right: 16.0)
private func configureCollectionView(){
self.collectionView.collectionViewLayout = UICollectionViewFlowLayout()
self.collectionView.register(UINib(nibName: "AmountCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "cell")
self.collectionView.delegate = self
self.collectionView.dataSource = self
}
extension SavingsSettingViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.viewModel.amountItems.value.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! AmountCollectionViewCell
cell.title = self.viewModel.amountItems.value[indexPath.row].description
return cell
}
}
extension MyController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 16
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 16
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let itemsPerRow = CGFloat(3.0)
let paddingSpace = sectionInsets.left * (itemsPerRow + 1)
let availableWidth = view.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: 59)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return self.sectionInsets
}
}

CollectionView don't update visible cell

Good afternoon!
Faced with this problem, there is a collection in which cells in the whole screen
the cell is configured with data,
and there are events inside the cell that make the collection reload,
it is not possible to make a check, if the cell is now visible, it is not necessary to update it completely, but only part of the data, I do not yet understand how to do it, can someone be able to prompt?!))
Test project))
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var collectionViwe: UICollectionView!
let dataSource = [1,2,3,4,5,6,7,8,9]
override func viewDidLoad() {
super.viewDidLoad()
collectionViwe.isPagingEnabled = true
collectionViwe.register(Cell.self, forCellWithReuseIdentifier: "Cell")
// Do any additional setup after loading the view.
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dataSource.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
let text = String(dataSource[indexPath.row])
if cell.label.text != text {
cell.label.text = text
cell.label.backgroundColor = .random()
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return view.frame.size
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return .zero
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.reloadData()
}
}
class Cell: UICollectionViewCell {
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
label.backgroundColor = .red
addSubview(label)
label.frame = CGRect(x: 36, y: 36, width: 200, height: 100)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension CGFloat {
static func random() -> CGFloat {
return CGFloat(arc4random()) / CGFloat(UInt32.max)
}
}
extension UIColor {
static func random() -> UIColor {
return UIColor(red: .random(),
green: .random(),
blue: .random(),
alpha: 1.0)
}
}

Change vertical cell size space created with a XIB file

How can I change the space between the cells? It currently looks like this:
Nothing that I've tried works, this is my current setup:
and this is where I'm defining the cell:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// return products.count
return 3
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// This determines the size of the cell on the featured slider
return CGSize(width: UIScreen.main.bounds.width, height: 350)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FeaturedPostsCollectionViewCell", for: indexPath) as! FeaturedPostsCollectionViewCell
let product = products[indexPath.row]
cell.featuredImage.image = UIImage(named: "4")
cell.lbName.text = product.Name!
cell.lbDesc.text = product.desc!
return cell
}
I've looked around but can't find what is it that is giving it so much space...
I just found the solution, it happened that I had to fix the width to my preferred value:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 310, height: 350)
}

How to trigger an function of an UICollectionViewCell inside an UICollectionViewController?

I would like to trigger the animation3() function (which is a function inside PageCell() which is a UICollectionViewCell) inside the BreathingSwpipingController which is a UICollectionViewController.
class BreathingSwipingController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var pageCell: PageCell?
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .white
collectionView.register(PageCell.self, forCellWithReuseIdentifier: "cellId")
collectionView.isPagingEnabled = true
setupStartStopButton()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
pageCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as? PageCell)!
return pageCell!
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: collectionView.frame.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
#objc func startStopTapped() {
pageCell!.animation3()
}
}
Make PageCell a delegate of BreathingSwipingController by making a protocol
protocol BreathingSwipingDelegate: class {
func doSth()
}
now inside UICollectionViewController define a weak var delegate: BreathingSwipingDelegate?
then head to PageCell file and conform to that protocol
class PageCell: BreathingSwipingDelegate .... {
func doSth() {
animation3()
}
var mController = BreathingSwipingController()
override init(style: .....) {
mController.delegate = self
.
.
.
.
}
}
now in BreathingSwipingController make the following
#objc func startStopTapped() {
delegate?.doSth()
}

UICollectionView cell size - swift 3/4

I am working on Collection view.I want to display 3 rows in collection view . Each row having two cells.The problems is i can't able to fit the cells in a row.Please kindly refer my code which i tried.
import UIKit
class ProductsTableViewCell: UITableViewCell {
#IBOutlet weak var productsCollections: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
productsCollections.isScrollEnabled = false
productsCollections.dataSource = self as? UICollectionViewDataSource
productsCollections.delegate = self as? UICollectionViewDelegate
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension ProductsTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 6
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Product", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 10, left: 10, bottom: 0, right: 10)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return collectionView.frame.width/9
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return collectionView.frame.width
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let collectionViewWidth = collectionView.bounds.width
let collectionViewHeight = collectionView.bounds.height
return CGSize(width: collectionViewWidth/2.0 , height: collectionViewHeight/2.5)
}
[This is the output i got.][1]}
I want like this.totally 6 rows.Per row 2 cells i want to display
First of all, calculate a row height that you need. So it is depends on screen resolution.
for example :
1- Declare a variable
fileprivate var cellHeight: CGFloat
2- calculate it once in viewDidLoad()
self.cellHeight = yourContainerFrameHeight / 3
3- Remove minimumLineSpacingForSectionAt
4- Calculate cell size.
I'm not sure, but you should not use the size of the CollectionView here (in sizeForItemAt). Instead you can use a fixed UIView or screen sizes. Because we already identify it.
This example has self.contentView you must change with yours or screen size
And try this:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
flowLayout.invalidateLayout()
let vMiddle = self.contentView.frame.size.width / 2.0
//this calculation for prevent next row shifts and fit rows
let cellWidth =
indexPath.row % 2 == 0 ? floor(vMiddle) : self.contentView.frame.size.width - floor(vMiddle)
//print("---------- cell width : \(cellWidth)")
return CGSize(width: cellWidth, height: self.cellHeight)
}