I am currently trying to convert an NSLayoutDimension to a CGFloat, so that I can get my collection view to conform to a certain layout.
let spacing: CGFloat = 3
let width = CGFloat(myCollectionView.widthAnchor)
let height = CGFloat(myCollectionView.heightAnchor)
let itemWidth = width / 3 - spacing
let itemHeight = height / 3 - spacing
var itemSize: CGFloat = 0
if itemWidth >= itemHeight {
itemSize = itemWidth
}
else if itemHeight > itemWidth {
itemSize = itemHeight
}
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsetsMake(20, 0, 10, 0)
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
layout.minimumInteritemSpacing = spacing
layout.minimumLineSpacing = spacing
myCollectionView.collectionViewLayout = layout
Setting width and height is giving the error of:
Cannot invoke initializer for type 'CGFloat' with an argument list of type '(NSLayoutDimension)'.
I have tried setting as a float and then converting float to cgfloat but that has not worked either.
Does anyone know how to convert NSLayoutDimension to CGFloat?
Any help is much appreciated
Thanks.
if you want width and height of your collection view try the code below:
let width = CGFloat(myCollectionView.frame.width)
let height = CGFloat(myCollectionView.frame.height)
Related
How can I set CellSize, MinSpacing and SectionInset of UICollectionView on "code"?
It is within the red frame of the image.
all this are properties of flow layout which we have to set before collection view start layout cells this can also be set programatically by
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
now you can use above layout variable to set all the parameters that you set through attribute inspector
You should use UICollectionViewFlowLayout
Use the below code for reference.
let cellSide: CGFloat = yourCustomCellSide
let leftOrRightMargin: CGFloat = yourCustomSideMargin
let sizeRect = UIScreen.main.bounds
let deviceWidth = sizeRect.size.width
let availableWidth = deviceWidth - (cellSide * 4)
let customFlowLayout = UICollectionViewFlowLayout()
customFlowLayout.scrollDirection = .horizontal
customFlowLayout.sectionInset = UIEdgeInsets(top: 10, left: leftOrRightMargin, bottom: 10, right: leftOrRightMargin)
customFlowLayout.minimumInteritemSpacing = 0
customFlowLayout.minimumLineSpacing = availableWidth/4
customFlowLayout.itemSize = CGSize(width: cellSide, height: cellSide)
yourCollectionView.collectionViewLayout = customFlowLayout
I'm trying to create equal horizontal spacing between two UICollectionViewCell and between a UICollectionViewCell an the screen border. It should look like this.
I think it is possible to use UICollectionViewFlowLayout to adjust the width of every UICollectionViewCell, so they have equal spacings regardless of the phone's size. There should always only be 3 cells on each row.
First of all you should add constants for all parameters of UICollectionView to the controller:
let itemsPerRow = 3
let spaceBetweenItems: CGFloat = 20.0
let spaceBetweenLines: CGFloat = 40.0
let itemHeight: CGFloat = 50.0
You mentioned that item's width should be adjustable. You can calculate it with this function:
var itemWidth: CGFloat {
return (self.collectionView.frame.width - CGFloat(self.itemsPerRow + 1) * self.spaceBetweenItems) / CGFloat(self.itemsPerRow)
}
Of course you need to customise layout of your UICollectionView instance:
var collectionViewLayout: UICollectionViewFlowLayout {
let result = UICollectionViewFlowLayout()
result.itemSize = CGSize(width: self.itemWidth, height: self.itemHeight)
result.minimumInteritemSpacing = self.spaceBetweenItems
result.minimumLineSpacing = self.spaceBetweenLines
result.sectionInset = UIEdgeInsets(top: 0.0, left: self.spaceBetweenItems, bottom: 0.0, right: self.spaceBetweenItems)
result.scrollDirection = .vertical
return result
}
And in the function viewDidLoad or your controller you should call setupCollectionView(). Here is a code of this function:
func setupCollectionView() {
self.collectionView.frame = self.view.frame
self.collectionView.collectionViewLayout = self.collectionViewLayout
}
You will see something like this:
my UICollectionViewCells are always placing at the edges of the UICollectionView. There is a middle space always like this.
What is the reason for that? And I want to keep 3 items per row always. But in this way it just set 2. How to fix this issue?
Please help me.
Thanks
UPDATE
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //.horizontal
layout.itemSize = cellSize
layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
layout.minimumLineSpacing = 1.0
layout.minimumInteritemSpacing = 1.0
layout.minimumLineSpacing=1.0
btncollectionView.setCollectionViewLayout(layout, animated: true)
btncollectionView.reloadData()
Works for both horizontal and vertical scroll directions, and variable spacing
Declare number of cells you want per row
let numberOfCellsPerRow: CGFloat = 3
Configure flowLayout to render specified numberOfCellsPerRow
if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
let horizontalSpacing = flowLayout.scrollDirection == .vertical ? flowLayout.minimumInteritemSpacing : flowLayout.minimumLineSpacing
let cellWidth = (view.frame.width - max(0, numberOfCellsPerRow - 1)*horizontalSpacing)/numberOfCellsPerRow
flowLayout.itemSize = CGSize(width: cellWidth, height: cellWidth)
}
I'm trying to display some cells in the UICollectionView, But please see the images attached and the code I've provided below, its very weird.
After days of research I didn't find a helpful answer. Please help.
I'm displaying about 200 cells in a view. This is a weird phenomenon happens on the later half when scrolling.
Also, I only need identical size for all cells. Any insights will be appreciated.
![image2][https://i.stack.imgur.com/aEgGy.png]
![image1][https://i.stack.imgur.com/QKei3.png]
var inset = 2
var dividendWidth = 2 // Number of cells in a row
var dividendHeight = 5 // Number of rows in a visible "page"
func configureCellLayout() {
let layout = UICollectionViewFlowLayout()
navHeight = navigationController?.navigationBar.frame.size.height
tabHeight = tabBarController?.tabBar.frame.size.height
statusHeight = UIApplication.shared.statusBarFrame.height
emptyViewWidth = screenSize.width - inset*(dividendWidth+1)
emptyViewHeight = screenSize.height - navHeight - tabHeight - statusHeight - inset*(dividendHeight+1)
layout.sectionInset = UIEdgeInsetsMake(2, 2, 2, 2)
layout.minimumLineSpacing = inset
layout.minimumInteritemSpacing = inset
modifyDividend()
let itemWidth: CGFloat = emptyViewWidth / dividendWidth
let itemHeight: CGFloat = emptyViewHeight / dividendHeight
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
collectionView.collectionViewLayout = layout
}
how can I get the actual interItemSpacing for a horizontal flow layout in the UICollectionView ? the only info I can get (and set) is minimumInteritemSpacing.
I need it for the sake of the following small calculation to always display 3 equally width items in the collection view regardless to screen size (i want to replace minimumInteritemSpacing with the current value of interItemSpacing in the formula):
flowLayout.itemSize = CGSizeMake((_collectionView.frame.size.width/3.0)-(flowLayout.minimumInteritemSpacing/3.0), _collectionView.frame.size.height); I put this calculation in viewDidLayoutSubviews and it's not working precisely for some screens because their current interItemSpacing is different than the minimumInteritemSpacing
thanks in advance.
You could get the actual spacing by comparing two sequential cells
Something like
let firstIndex = IndexPath(item: 0, section: 0)
let secondIndex = IndexPath(item: 1, section: 0)
if let att1 = collectionView.layoutAttributesForItem(at: firstIndex),
let att2 = collectionView.layoutAttributesForItem(at: secondIndex) {
let actualSpace = att2.frame.minX - att1.frame.maxX
print (actualSpace)
}
For creating cells with fixing spacing try this:
private let minItemSpacing: CGFloat = 8
private let itemWidth: CGFloat = 100
private let headerHeight: CGFloat = 32
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Create our custom flow layout that evenly space out the items, and have them in the center
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: itemWidth, height: itemWidth)
layout.minimumInteritemSpacing = minItemSpacing
layout.minimumLineSpacing = minItemSpacing
layout.headerReferenceSize = CGSize(width: 0, height: headerHeight)
// Find n, where n is the number of item that can fit into the collection view
var n: CGFloat = 1
let containerWidth = collectionView.bounds.width
while true {
let nextN = n + 1
let totalWidth = (nextN*itemWidth) + (nextN-1)*minItemSpacing
if totalWidth > containerWidth {
break
} else {
n = nextN
}
}
// Calculate the section inset for left and right.
// Setting this section inset will manipulate the items such that they will all be aligned horizontally center.
let inset = max(minItemSpacing, floor( (containerWidth - (n*itemWidth) - (n-1)*minItemSpacing) / 2 ) )
layout.sectionInset = UIEdgeInsets(top: minItemSpacing, left: inset, bottom: minItemSpacing, right: inset)
collectionView.collectionViewLayout = layout
}
For more information, this excellent article:
http://samwize.com/2015/11/30/understanding-uicollection-flow-layout/