I have a UICollectionView that can either have a single cell or two cells.
Is it possible for me to horizontally center the first cell and on panLeft have the second cell centered likewise - to the UICollectionView whose width sizes itself to the screen/view size and cell's proportionally adjusting as well?
From the references I've seen, I believe I need to use the UICollectionViewDelegateFlowLayout insetForSectionAt method, but I'm not able to get it exactly centered for some reason, and also when it is just one cell, I believe the inset causes the UICollectionView to become scrollable because enough space was created..
To make collection view cell center, your controller must confirm UICollectionViewDelegateFlowLayout protocol. Use below code to make cells center:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width * 0.7, height: 300)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let width = collectionView.frame.width
let margin = width * 0.3
return UIEdgeInsets(top: 10, left: margin / 2, bottom: 10, right: margin / 2)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return collectionView.frame.width * 0.3 / 2
}
If you return 1 or 2 in numberOfItemsInSection method, It works fine.
Related
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.
Im trying to get my collectionView cells to look like the picture bellow but have not been able to do it. I tried using collectionViewLayout but was not able to get the sizing right along with the proper padding. How would I be able to do this?
Here is my code
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let frameSize = collectionView.frame.size
return CGSize(width: frameSize.width, height: frameSize.height / 2)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 27, bottom: 0, right: 27)
}
}
Here is a picture of what I'm trying to achieve. Thanks
Implement the UICollectionViewFlowLayout's following methods
public func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
public func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
and for the 27px inset use
yourcollectionView.sectionInset = UIEdgeInsets(top: 10, left: 27, bottom: 10, right: 27)
To use you class which implements this protocol, you have to set the collection view's delegate property.
yourcollectionView.delegate = /* object which implement flow layout delegate */
UICollctionViewDelegate automatically conform to UICollectionViewFlowLayoutDelegate, setting the delegate is enough.
You are missing another thing while calculating the cell size. Your cell size calculation is wrong. Implement it as follows
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let frameSize = collectionView.frame.size
let size = (frameSize.width - 64.0) / 2.0 // 27 px on both side, and within, there is 10 px gap.
return CGSize(width: size, height: size)
}
If you are using the storyboard to set layout your UI Widget, you can set them in storyboard too.
I have the following basic UICollectionView. Now, I am implementing sizeForItem by returning size in the following way
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.bounds.size.width/3
let size = CGSize(width: width, height: 100.00)
return size
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
The view which I get after this is:
I want the pictures to be equally sized. I dont quite know what am I doing wrong.
How can I solve this?
Size inspector.
Well, I found the solution. As #Dix mentioned in the answer to reduce the spacing to zero. Also, to fit all the cells in the grid following should be the width:
width - 2
This way the grid will be aligned to the view and all centered.
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
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
}