Collection left to right cell not showing correctly - swift

Collection view cells are not showing correctly from left to right. It has the gap in center. How can I correct this issue.
collectionView_.register(UINib.init(nibName: String(describing: GoalSelectionCollectionViewCell.self), bundle: nil), forCellWithReuseIdentifier: reuseIdentifier)
collectionView_.allowsMultipleSelection = true
if let flowLayout = collectionView_?.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let itemSize:CGSize = CGSize(width: 80.0, height: 30.0);
return itemSize;
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 20.0;
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 20.0;
}

You need to conform to UICollectionViewDelegateFlowLayout and you also need to set minimumLineSpacing (min spacing between lines) and minimumInteritemSpacing (min spacing in between items in same row)

Related

How to override the default position of UICollectionViewCells?

I have a vertical UICollectionView which contains 5 different types of cells. The 4 of them take the whole width of the UICollectionView, so the func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize gets the work done.
The other 2 are of the same size but their default position needs to be changed; I want them to be aligned from left to right, instead of the centered default.
Here's how I set up my UICollectionView:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
switch typesOfCellsArray[indexPath.row] {
case .createVoiceRoom:
return CGSize(width: collectionView.frame.width, height: 70)
case .voiceRooms:
let height: CGFloat = content.voiceRooms.count > 3 ? 256 : 128
return CGSize(width: collectionView.frame.width, height: height)
case .seeMoreVoiceRooms:
return CGSize(width: collectionView.frame.width, height: 50)
case .newStatus:
let width = collectionView.frame.width / 4
return CGSize(width: width, height: width + 40)
case .status:
let width = collectionView.frame.width / 4
return CGSize(width: width, height: width + 40)
}
}
Here's how they look:
And here's what I want:
I think I need to subclass UICollectionViewLayout to achieve that, but I've failed... Here's what I did:
class HomeCollectionViewLayout: UICollectionViewLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let collectionView = collectionView else { return nil }
let layoutAttributes = super.layoutAttributesForElements(in: rect)
layoutAttributes?.forEach({ attributes in
if collectionView.cellForItem(at: attributes.indexPath) is NewHomeStatusCollectionViewCell {
let column = attributes.indexPath.row % 3
attributes.frame.origin.x = CGFloat(column-1) * attributes.frame.width
}
})
return layoutAttributes
}
}
Of course, I have set this class as the UICollectionView layout. Any ideas?
You can insert each of you cell into separate section and then control following:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { }

Square CollectionView Cell Swift

I tried to make two square collectionView cells in one row. I implemented all of the necessary delegates. When the view is loaded, cells are not square but when I start scrolling, some cells are being square.
when I start scrolling :
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
collectionView.delegate = self
collectionView.dataSource = self
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
let width = (collectionView.frame.width/2)-0.5
return CGSize(width:width , height: width)
}
Add more margin to width in layout delegate
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
let width = (collectionView.frame.width/2)-10
return CGSize(width:width , height: width)
}

create menu page with collectionView

I'm struggle a lot. I want to make a menu page with collectionView like this.
I set my width collectionView like this
addSubview(menuCollectionView)
menuCollectionView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
menuCollectionView.leadingAnchor.constraint(equalTo: leadingAnchor),
menuCollectionView.bottomAnchor.constraint(equalTo: bottomAnchor),
menuCollectionView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -129),
menuCollectionView.heightAnchor.constraint(equalToConstant: 33)
])
menuCollectionView.register(MenuCell.self, forCellWithReuseIdentifier: cellID)
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath)
cell.backgroundColor = .red
return cell
}
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, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: frame.width / 2, height: frame.height)
}
but it end up like this
the cell not fit with the width I setup, and it scroll to down. I was trying to replicate this tutorial from youtube pageMenuVideo but it behave differently. please help me :(

How do you set inner spacing in a collection view cell with 2 cells per row?

Ive been stuck on this for two weeks now. Searched everywhere and still can't find a solution. I want to bring the cells closer to the middle. Also have another collection view with 3 cells per row I need to do the same thing with. Thanks
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 153, height: 241)
}
//
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(10, 11, 10, 11)
}
//
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
//
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, maximumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
Jusr read comment , don't forget to setup your cell at let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! UICollectionViewCell
extension ViewController :UICollectionViewDelegate , UICollectionViewDelegateFlowLayout,UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100 // data source
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! UICollectionViewCell
cell.backgroundColor = .red
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// 3 cell same size in each row space between them 4
let spaceBetweenCell :CGFloat = 4.0 // if you change this parmters you have to change minimumInteritemSpacingForSectionAt ,
let screenWidth = UIScreen.main.bounds.size.width - CGFloat(2 * spaceBetweenCell)
let totalSpace = spaceBetweenCell * 2.0; // there is 2 between 3 item
return CGSize(width: (screenWidth - totalSpace)/3, height: (screenWidth-totalSpace)/3)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 4.0 // space between sections
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 4.0 // space between items in row
}
}
If you're happy with your cell sizes and just want to move them closer, then adjust your left and right insets (which are the 2nd and 4th inputs to UIEdgeInsetsMake):
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(10, 16, 10, 16)
}

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)
}