In my uicollectionview cells are loaded in sections. but the number of sections in the collectionview is 1. when sections are breaking there is a space between cells which i need to avoid.
func cellSize() -> CGSize {
let collectionViewSize: CGSize = self.colorScrollCollectionView.frame.size
return CGSize(width: collectionViewSize.width, height: collectionViewSize.width * 0.35)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.colorArray.count * 5
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cellSize = CGSize(width: self.cellSize().width, height: self.cellSize().height)
return cellSize
}
Related
I am getting the space between the cells (marked with blue color):
extension ProfileVC: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if collectionView == self.humanCollectionView {
let screenWidth = humanCollectionView.bounds.width
return CGSize(width: screenWidth/3-0, height: screenWidth/3-0)
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 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
Why are you declaring the delegate functions inside collectionView(_ collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) delegate method?
Try to do like this:
import UIKit
class ProfileVC: UICollectionViewController {
override func viewDidLoad() {
super.viewDidLoad()
//remember to set the delegates
self.collectionView.delegate = self
self.collectionView.dataSource = self
//this is optional just to test that it is working
collectionView.backgroundColor = .red
// Do any additional setup after loading the view.
}
}
extension ProfileVC: UICollectionViewDelegateFlowLayout {
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//this is just a test number, here you should return the number of your items
return 20
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//you should set reuseIndetifier in storyboard or in code if you create your collectionView programmatically
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "reuseIdentifier", for: indexPath)
//again this is just a placeholder color to see that it's working
cell.backgroundColor = .green
return cell
}
func collectionView(_ collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) -> CGSize {
let screenWidth = collectionView.bounds.width
//be sure to use floor or to use a number of items that perfectly fits the width of collectionView
return CGSize(width: floor(screenWidth/3), height: floor(screenWidth/3))
}
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 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
I want to add that if the width of your collectionView is not perfectly divisible by 3, you will always have some gap between the cells. You should do the math by yourself for each device width and choose a proper number of cells for the width. For example for a screen with aspect ratio like iPhone X, I would use 3 cells when in portrait and 4 cells when in landscape.
You can do like this:
func collectionView(_ collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) -> CGSize {
let screenWidth = collectionView.bounds.width
let screenHeight = collectionView.bounds.height
let numberOfCells : CGFloat = screenWidth > screenHeight ? 4 : 3
return CGSize(width: floor(screenWidth/numberOfCells), height: floor(screenWidth/numberOfCells))
}
I set sections for my horizontal UICollectionView. I want my cell item in second rows in each section to be double width of items in first row. This is what i set:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return 2
}
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { //1.7, 2.7
if indexPath.row == 0 {
return CGSize(width: collectionView.frame.size.width/2,
height: collectionView.frame.size.height/2)
}
return CGSize(width: collectionView.frame.size.width,
height: collectionView.frame.size.height/2)
}
But this is the end result:
How i can get rid of spaces in smaller size items and layout them nicely?
Note: Numbers on pictures represent section and row (0 1 -> Section 0, Row 1)
This is what i want to achieve:
First: if you use a storyboard, make sure you add collection view's constraints properly to its super view.
Second: Add collection view cell's constraints.
Third: From storyboard's size inspector, change collection view's estimate size to none.
Fourth: Add UICollectionViewDelegateFlowLayout in your viewcontroller
Fifth: Add those following code:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.section == 0 {
return CGSize(width: (collectionView.frame.size.width - 10)/2,
height: (collectionView.frame.size.height - 10)/2) // your desired height
}
return CGSize(width: (collectionView.frame.size.width - 10),
height: (collectionView.frame.size.height - 10)/2)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
}
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 5
}
Replace indexPath.row with indexPath.section.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { //1.7, 2.7
if indexPath.section == 0 {
return CGSize(width: collectionView.frame.size.width/2,
height: collectionView.frame.size.height/2)
}
return CGSize(width: collectionView.frame.size.width,
height: collectionView.frame.size.height/2)
}
I am trying to create 2x2 grid layout using collection view.
I have used below code. It's kind of working fine for iPhone 5 but with tweaks. I am trying to write code that can be used on all screen sizes. This is not working on iPhone 6.
public func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if let cell1 = cell as? CollectionViewCell {
return cell1
}
return cell
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let padding: CGFloat = 20
let collectionViewSize = collectionView.frame.size.width - padding
return CGSize(width: collectionViewSize/2, height: collectionViewSize/2+15)
}
public func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int
) -> UIEdgeInsets {
return UIEdgeInsets(
top: 5, left: 5, bottom: 5, right: 5
)
}
public func collectionView(
_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 5
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 5
}
I am trying to achieve following layout:
In future this grid can be like 2 columns only and N rows. Each row will always have 2 items.
First of all, get three variables together depending on your needs. Those are the minimum spacing (Both InteritemSpacing and Line spacing - Should be same UXwise but you can change that in delegate methods if you like. The interitem space however must always be equal to minimumSpacing), edgeInsetPadding and the number of items you want in a row.
private var numberOfItemsInRow = 2
private var minimumSpacing = 5
private var edgeInsetPadding = 10
In your code, you have already defined your Edge Insets as:
UIEdgeInsets(
top: 5, left: 5, bottom: 5, right: 5
)
The left and right insets are important for correctly determining the size of the item. left+right gives us a grand sum of 10. This should be assigned to edgeInsetPadding like this:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let inset = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
edgeInsetPadding = inset.left+inset.right
return inset
}
Now lets get to your UICollectionViewDelegateFlowLayout. Update the following methods.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return minimumSpacing
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return minimumSpacing
}
Now lets get to the main part. Modify your sizeForItemAt in UICollectionViewDelegateFlowLayout as:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = (Int(UIScreen.main.bounds.size.width) - (numberOfItemsInRow - 1) * minimumSpacing - edgeInsetPadding) / numberOfItemsInRow
return CGSize(width: width, height: width)
}
And this is it. You now get two equal size tiles in 2x2 grid. If you want to change this in future, just change the numberOfItemsInRow variable to something else. Like 3 for 3x3.
This will be done using the item size of the collectionViewCell
collectionView.delegate = self
extension ViewController : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let padding = 5
let width = (collectionView.frame.size.width - CGFloat(padding) * 2) / CGFloat(2)
let height = width / 200 * 110 // or what height you want to do
return CGSize(width: width, height: height)
}
}
Use:
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let padding: CGFloat = 20
let size = self.view.frame.width - padding
return CGSize(width: size/2, height: size/2+15)
}
I have these views
UICollectionView(1) [that contains]-> a Cell -> UICollectionView(2) -> a Cell -> UICollectionView(3)
when calling reloadData on 3rd UICollectionView ( with most depth ) it will freezes the app.
NOTE: I'm not using auto layout
EDIT:
for 3rd ui collection view :
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.data.count
}
//endregion
//region cellForItemAt
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let item = self.data[indexPath.item]
return (self.cv.dequeueReusableCell(
withReuseIdentifier: reuseIdentifierItem,
for: indexPath) as! AboutCellItem)
.setImage(URL(string: item.images?.first?.thumbImageUrl ?? "")!)
.setTitle(item.aboutTitle ?? "-")
}
//endregion
//region size
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if self.data.count == 1 {
return CGSize(width: self.bounds.width, height: 70)
} else if self.data.count == 2 {
return CGSize(width: self.bounds.width / 2, height: 70)
} else {
return CGSize(width: ( self.bounds.width / 2.5 ) - Theme.Paddings.mainHorizontal * 1.5 , height: 70)
}
}
//endregion
//region space
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return Theme.Paddings.mainHorizontal
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return Theme.Paddings.mainHorizontal
}
EDIT:
CPU on device goes up to 97% when calling realodData
EDIT
updating data source and not calling reloadData
and updating views by scrolling out the 3rd cv using 2rd cv and then scrolling it in again will works okay
NOTE: calling reloadData with delay doesn't work either
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if collectionView == self.collectionViewVideo {
var collectionViewSize = collectionViewVideo.frame.size
collectionViewSize.width = collectionViewSize.width/3.0 //Display Three elements in a row.
return collectionViewSize
} else {
return CGSize(width: 60, height: 60)
}
}
You also need to take space in account.
Space is your collection view item space
Following is the code has two cells and 20 spaces.
(I am not writing exactly code you need You should do it by your self)
extension YourViewController : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 20
}
//--------------------------------------------------------------------------------
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 20;
}
//--------------------------------------------------------------------------------
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: ( self.collectionView.frame.size.width - 60 ) / 2,height:( self.collectionView.frame.size.width - 60 ) / 2)
}
//--------------------------------------------------------------------------------
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0, 20, 20, 20)
}
}
Here 60 means SPACE 20 CELL SPACE 20 CELL SPACE 20