UICollectionView with an entire item and another exceeding - Swift - ios

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 ?

Related

UICollectionViewCell wrong size

I have a problem with UICollectionViewCell.
My UICollectionViewCell's width = UIScreen.main.bounds.size.width and it works fine before I add UILabel into the cell with constraints for left and right edges. If I add only for left it's ok. but when for both I have an issue.
Bug state :
Normal state:
extension YourViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 50)
}
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
}
}
You can try this code.
In storyboard -> UICollectionView -> Change Estimate size as None in Size Inspector
you can set right constrain with greater than equal to constrain, so it can adjust appropriately.
Dont add a right constrain to the uicollection cell.
Simply provide a top and left (leading) constraint and the drag the uilabel to your desired width and then set a width constraint.
That should be all you need to get your desired outcome.

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.

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

Why strange lines displaying in collection view?

I am currently working in creating a custom calendar where I tried to display Seven cells in a row , But unfortunately some lines occurs randomly can any one guide the error.I have attached the screen shot
I have attached the sample code:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let s = CGSize(width: CGFloat(UIScreen.main.bounds.size.width / 7), height: CGFloat(UIScreen.main.bounds.size.height / 7))
return s
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0,0,0,0)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numDays+weekday
}
You can manage it by UICollectionViewDelegateFlowLayout methods
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0 // OR change as you need
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0 // OR change as you need
}
This behaviour appears when you compute the size of your cell.
Hear, you are doing :
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let s = CGSize(width: CGFloat(UIScreen.main.bounds.size.width / 7), height: CGFloat(UIScreen.main.bounds.size.height / 7))
return s
}
The cell's size may not be rounded, therefor the runtime tries to do its best to fill the collection view with your constraints but end up with these little flaws.

Equidistant collectionViewCells?

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

Resources