Equidistant collectionViewCells? - ios

I have a UICollectionView with cells of equal size. I want to make the distances between cells and between the cells and the left and right of the collection view all equal, with 2 cells in each row.
The content of each cell is horizontally centered, so I've tried setting the width of the cells to half the collection view's width:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: eventCollectionView.frame.width/2, height: 111)
}
But this produces the following:
As seen, the two cells are at 1/4 and 3/4th of the width. Instead I want them to be at 1/3 and 2/3 so the space between them and the edges are all equal.
Does anybody know how I'd accomplish this?

use bellow code
fileprivate var defaultspacing: CGFloat = 5
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var size: CGSize = .zero
let width = (SCREEN_WIDTH - (3 * defaultspacing))/2
size = CGSize(width: width, height: width)
return size;
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(self.defaultspacing, self.defaultspacing, 0, self.defaultspacing);
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return self.defaultspacing;
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat
{
return self.defaultspacing;
}

For that, you have to set section Inset property from storyboard whatever you want from left and right side of the collection view, also set the Min Spacing property from storyboard you want
In my case, I want 5 px from both the side and 5 px between 2 cell.
and in delegate method write,
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: (eventCollectionView.frame.width - 15)/2, height: 111)
}

Add following method in your class
You can make changes as per your needs
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: CGFloat(collectionView.frame.size.width / 2 -10), height: CGFloat(111)) // here 10 is the space of cells
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int) -> UIEdgeInsets{
return UIEdgeInsetsMake(2, 2, 2, 2)
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10.0
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10.0
}

Pictures make a lot of sense. My solution will work in every devices in right format.
Why?
Please go through the solution.
Step 1:
My base layout is iphone 7 plus and i have calculated for this devices.Calculation is done because i need to support all devices.So i had make some constants like below:
var SCREEN_WIDTH = UIScreen.main.bounds.size.width
var SCREEN_HEIGHT = UIScreen.main.bounds.size.height
var BASE_SCREEN_HEIGHT:CGFloat = 736.0
var SCREEN_MAX_LENGTH = max(SCREEN_WIDTH, SCREEN_HEIGHT)
var ASPECT_RATIO_RESPECT_OF_7P = SCREEN_MAX_LENGTH / BASE_SCREEN_HEIGHT
let MINIMUM_INTERITEM_SPACING:CGFloat = 46 //My Default Inter Cell Spacing for iphone 7plus as i have designed in it.
var ITEM_WIDTH:CGFloat = 138 //for iPhone 7 plus.initial value
var ITEM_HEIGHT:CGFloat = 138 //for iphone 7 plus.initial value
let NUMBER_OF_CELLS_IN_PORTRAIT:CGFloat = 2
let NUMBER_OF_CELLS_IN_LANDSCAPE:CGFloat = 5
Step 2:
Then i had to calculate cellsize according the exact space between cells.
func calculateCellSize(screenWidth:CGFloat , cellItem:CGFloat) {
ITEM_WIDTH = (screenWidth - MINIMUM_INTERITEM_SPACING * 3 *
ASPECT_RATIO_RESPECT_OF_7P * (cellItem-1)) / cellItem - 1// This 1
has been subtracted from ITEM_WIDTH to remove mantissa
ITEM_HEIGHT = ITEM_WIDTH
}
Step 3:
For between cell spacing you need to call below method.
public func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return MINIMUM_INTERITEM_SPACING * ASPECT_RATIO_RESPECT_OF_7P
}
And for Padding(with left margin and right margin) you have to call this method.
public func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout, insetForSectionAt
section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0,
MINIMUM_INTERITEM_SPACINGASPECT_RATIO_RESPECT_OF_7P, 0,
MINIMUM_INTERITEM_SPACINGASPECT_RATIO_RESPECT_OF_7P)
}
Overall i had to call 4 methods.I didn't explain the other two methods may be you will understand.
So basically whole code is like this.
And my output is

Related

collectionView divided into three lines swift 4

I need to create a collectionView to display a series of images, individually for each photo. I'm trying to reproduce what you see in the picture, view a photo and then scroll left or right for the next. I can not create the layout of the collectionView
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.datasource.count
}
//UICollectionViewDelegateFlowLayout - constraint della collecion view da innestare
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = (UIScreen.main.bounds.size.width - 3) / 3
let height = width
return CGSize(width: width, height: height)
}
swift 4:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
//calculation of cell size
return CGSize(width: self.collectionview.frame.size.width,height: 180)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
// indentation
return UIEdgeInsetsMake(0, 23, 20, 20)
}
If you want to drag to horizontal or vertical, in collectionview there is a "scroll Direction" attribute. You can change it to horizontal or vertical.

UICollectionView with an entire item and another exceeding - Swift

I'm making an app which contains a UITableView, and inside this UITableView, there is a cell containing a horizontal UICollectionView.
Into this UICollectionView, I'm trying to display only one item, and a part of an other, to indicate to the user that he can scroll to the right.
Here is the result I would like to get :
But actually, here is what I get :
Here is my code :
extension CollectionViewCell: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var width = self.frame.width - 32.0
return CGSize(width: width, height: 275.0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets.zero
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
As you can see, the sizeForItem width is self.frame.width - 32.0 and not self.frame.width - 48.0. I did this because my collectionView cell contains a container, which has a right spacing of 16.0pt with its superview.
Anyone has the solution to get the right behavior ?

Swift: Change the width of cell Layout in UICollectionView when add items

I'm new to swift , i want to make a UICollectionViewCell layout to be dynamic example: if we have an item added to look like this:
1.if we have one item it look like this
2.If we have two items added to look like this:
3. if we have item 3 again to look like this :
This process proceeds this way, as long as there are items
Thanks!
This is method of UICollectionViewDelegateFlowLayout for the size of items.
Just check for total item count odd/even and based on that decide you cell width.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if arrList.count % 2 == 0 {
let width = (collectionView.frame.width-20)/2
let height : CGFloat = 100.0
return CGSize(width: width, height: height)
}else {
if arrList.count-1 == indexPath.row {
let width = collectionView.frame.width-10
let height : CGFloat = 100.0
return CGSize(width: width, height: height)
}else{
let width = (collectionView.frame.width-20)/2
let height : CGFloat = 100.0
return CGSize(width: width, height: height)
}
}
}
This is interspacing methods.
//these methods are to configure the spacing between items
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0,5,5,5)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10
}

issues with gridLayout in swift

So I have these delegate methods that help me layout my collectionView. I am trying to create somewhat of a grid layout where there are X numberOfSections and X numberOfItemsInSection. Based off of what I have now it lays out all of the rights next to each other and spaces them out a little too far as to where cells go to the next line. How do I go about fitting all the cells for a section on one line.
//Asks the delegate for the size of the header view in the specified section.
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return .zero
}
//Asks the delegate for the size of the footer view in the specified section.
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return .zero
}
//Asks the delegate for the size of the specified item’s cell.
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: (collectionView.bounds.size.width - CGFloat(numberOfItemsInSection))/2.2, height: collectionView.bounds.size.height - 50)
}
//Asks the delegate for the margins to apply to content in the specified section.
//in short in controls the amount of space between the items above,left,right, and below
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
}
//Asks the delegate for the spacing between successive rows or columns of a section.
//controls the space in between rows and columns
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
//Asks the delegate for the spacing between successive items of a single row or column.
//controls the space between each cell
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
I feel like it has to do with the sizeForItemAt but I can't exactly figure out how to change it.
This is what it currently looks like.
You're right, it has to do with sizeForItemAt method, you should use the indexPath parameter so you can use its property section to define the size for each item in each section.
Just remember that there is a space between items so you need to take that into account when calculating the width and height, so you can adjust the spacing using minimumLineSpacingForSectionAt and minimumInteritemSpacingForSectionAt methods.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.section == 0 {
return CGSize(width: 200, height: 100)
}
return CGSize(width: (collectionView.bounds.size.width - CGFloat(numberOfItemsInSection))/2.2, height: collectionView.bounds.size.height - 50)
}

How to automatically resize cells to fit 4 per line [duplicate]

This question already has answers here:
How to display 3 cell per row UICollectionView
(3 answers)
Closed 5 years ago.
I have a collection view were I'm looking for a method to find out how big the cells can be to fit 4 cells per line (on that specific screen size) and use that size on all of the cells. I have a reusable cell that I use on the rest of the cells.
extension LevelSelectController: UICollectionViewDelegateFlowLayout {
// Collection view flow layout setup
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// Compute the dimension of a cell for an NxN layout with space S between
// cells. Take the collection view's width, subtract (N-1)*S points for
// the spaces between the cells, and then divide by N to find the final
// dimension for the cell's width and height.
let cellsAcross: CGFloat = 4
let spaceBetweenCells: CGFloat = 0
let dim = (collectionView.bounds.width - (cellsAcross - 1) * spaceBetweenCells) / cellsAcross
return CGSize(width: dim, height: dim)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0, 0, 0.0, 0.0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}

Resources