Collection Views: Not fitting - swift

I have an images that are 182x150 and I set the collection cell to that and made sure it can contain rows of 2 images. But when I run the simulator, the rows only have 1 image. I don't know if it's my code or that I need to resize my image.
let itemSize = UIScreen.main.bounds.width/2 - 2
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 6, left: 4, bottom: 6, right: 4)
layout.minimumInteritemSpacing = 4
layout.minimumLineSpacing = 4
layout.itemSize = CGSize(width: itemSize , height: itemSize)
myCollectionView.collectionViewLayout = layout

Looks like you just need to include section insets in your itemSize calculation
// 8 for left and right section insets, 4 for item spacing.
let availableWidth = view.bounds.width - 8 - 4
let itemSize = availableWidth / 2

Related

Dynamic collection view cell column from different iPhone device

I try to create a dynamic cell column from different iPhone devices with collectionView.
I already try for iPhone SE to have a 3 column and success, but when I try to make iPhone 11 Pro Max to have a 4 column it have a space between each cell.
iPhone 11 Pro Max
iPhone SE
I calculate my cell like this
enum UIHelper {
static func createCollectionViewFlowLayout() -> UICollectionViewFlowLayout {
let screenWidth = UIScreen.main.bounds.width
let padding: CGFloat = 12
let minimumInterimSpacing: CGFloat = 10
let availableWidth = screenWidth - (padding * 2) - (minimumInterimSpacing * 2)
var numberOfColumn: CGFloat
// 375 is iPhone SE width
if screenWidth > 375 {
numberOfColumn = 4
} else {
numberOfColumn = 3
}
let itemWidth = availableWidth / numberOfColumn
let flowLayout = UICollectionViewFlowLayout()
flowLayout.sectionInset = UIEdgeInsets(top: padding, left: padding, bottom: padding, right: padding)
flowLayout.itemSize = CGSize(width: itemWidth, height: itemWidth)
return flowLayout
}
}
and in my view controller I create it like this
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
collectionView.collectionViewLayout = UIHelper.createCollectionViewFlowLayout()
}
what am I missing?
Your setup seems to be fine, The issue seems to be with the logic / math in this line
let availableWidth = screenWidth - (padding * 2) - (minimumInterimSpacing * 2)
The logic is that if you have 3 cells in a row, there will be 2 gaps between the 3 cells, but if you have 4 cells in a row, you will have 3 gaps.
So if I change the available width also based on the number of cells I intend to have, you will get the desired results. So I have made some small changes to change the available width based on how many cells you want in a row.
I have made some minor edits to your code, I have included some comments to show what I have changed, however, you will need to organize my updates better as I made quick changes to show you the fix in the logic.
static func createCollectionViewFlowLayout() -> UICollectionViewFlowLayout {
let screenWidth = UIScreen.main.bounds.width
let padding: CGFloat = 12
let minimumInterimSpacing: CGFloat = 10
// Updated this to a var
var availableWidth = screenWidth - (padding * 2) - (minimumInterimSpacing * 2)
var numberOfColumn: CGFloat
// 375 is iPhone SE width
if screenWidth > 375 {
numberOfColumn = 4
// Update the width available as well
availableWidth = screenWidth - (padding * 2) - (minimumInterimSpacing * (numberOfColumn - 1))
} else {
numberOfColumn = 3
}
let itemWidth = availableWidth / numberOfColumn
print(numberOfColumn)
let flowLayout = UICollectionViewFlowLayout()
flowLayout.minimumInteritemSpacing = minimumInterimSpacing
flowLayout.sectionInset = UIEdgeInsets(top: padding, left: padding, bottom: padding, right: padding)
flowLayout.itemSize = CGSize(width: itemWidth, height: itemWidth)
return flowLayout
}

How to equally space cells with a fixed size inside a UICollectionView using compositional layout?

I have a collection view created with compositional layout. Each item has a fixed width and height, and the section occupies the full width of the table (which itself occupies the full width of the screen). I'm trying to create an algorithm to calculate the content and section insets in a way that each item has an equal space between them, and also an equal space between the screen's border. In other words, the space between everything should be the same.
Here's the methods to calculate the content and section insets:
// width is 414
private func getContentInsets(width: CGFloat) -> NSDirectionalEdgeInsets {
let totalItemsInRow = Int(width / 120) // 3
let totalCellWidth = 120 * totalItemsInRow // 360
let remainingSpace = width - CGFloat(totalCellWidth) // 54
let marginPerItem = remainingSpace / CGFloat(totalItemsInRow) // 18
return NSDirectionalEdgeInsets(top: 8, leading: marginPerItem / 2, bottom: 8, trailing: marginPerItem / 2)
}
// width is 414
private func getSectionContentInsets(width: CGFloat) -> NSDirectionalEdgeInsets {
let totalItemsInRow = CGFloat(Int(width / 120)) // 3
return NSDirectionalEdgeInsets(top: 0,
leading: getContentInsets(width: width).leading * totalItemsInRow, // 9 * 3 = 27
bottom: 0,
trailing: getContentInsets(width: width).trailing * totalItemsInRow) // 9 * 3 = 27
}
Using these methods I was able to have an equal space between the items. But they have a different space to the border of the screen, as we can see on the image bellow:
So, how can I change these algorithms to achieve an equal space between the items, and also between the screen borders (everything should have the same spacing).
Thanks to Felipe's idea of assign just the leading value, I was able to fix the algorithm. Unfortunately that formula didn't solved the problem, because a small space was still left at the trailing border of the collection view. And I also noticed that the correct property to use to add space between the cells of the collection view is the edgeSpacing, not the contentInsets.
So I removed the section inset, and just assigned the edgeSpacing like this:
private func getEdgeSpacing(width: CGFloat) -> NSCollectionLayoutEdgeSpacing {
let totalItemsInRow = Int(width / 120)
let totalCellWidth = 120 * totalItemsInRow
let remainingSpace = width - CGFloat(totalCellWidth)
let totalMargins = totalItemsInRow
let marginPerItem = remainingSpace / CGFloat(totalMargins)
return NSCollectionLayoutEdgeSpacing(leading: NSCollectionLayoutSpacing.fixed(marginPerItem / 2),
top: nil,
trailing: NSCollectionLayoutSpacing.fixed(marginPerItem / 2),
bottom: nil)
}
The only fixed value there is 120, which is the fixed width of each cell.
Well.. I think you can accomplish it changing the end of your calculation by.
54 / (numberOfCells + 1) and assign just the leading with this value
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
group.contentInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0)
group.edgeSpacing = .init(leading: .fixed(135), top: nil, trailing: .fixed(135), bottom: nil)
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0)
// 135(leading)+135(trailing)-108(Space) = -162
section.interGroupSpacing = -162
https://github.com/MilanSavaliya321/Compositional-Collection-View-Layouts

Custom UICollectionViewCell size in Swift 4.2

I am working on a crossword app but I keep missing something when I calculate each itemSize of the UICollectionView. I get the right size for iPhone SE but the wrong size for iPhone XR. What am I doing wrong?
func setLayout() -> UICollectionViewFlowLayout {
let layout = UICollectionViewFlowLayout()
layout.itemSize = getCellSize()
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
return layout
}
func getCellSize() -> CGSize {
let width:CGFloat = self.view.frame.width/CGFloat(crossWordData[0].count)
let height:CGFloat = (self.view.frame.height - TitleView.frame.height)/CGFloat(crossWordData.count) - cellsBorderWidth
//cellsBorderWidth = 1.2
let cellSize = CGSize(width:width , height:height)
return cellSize
}
This is because self.view ends where is bottom of the display. New iPhones (X, Xs, Xs Max, Xr) have on the bottom this place for "home gesture". So for your calculation, content of your CollectionView is bigger than CollectionView because your CollectionView has bottom constraint equal to safe area bottom constraint which is for new iPhones higher than where bottom of the display is. So when you need width and height instead of this
let width:CGFloat = self.view.frame.width/CGFloat(crossWordData[0].count)
let height:CGFloat = (self.view.frame.height - TitleView.frame.height)/CGFloat(crossWordData.count) - cellsBorderWidth
call this
let width:CGFloat = self.yourCollectionView.frame.width/CGFloat(crossWordData[0].count)
let height:CGFloat = self.yourCollectionView.frame.height/CGFloat(crossWordData.count) - cellsBorderWidth
Eventually this is how I changed my code -
let width:CGFloat = self.view.frame.width/CGFloat(crossWordData[0].count)
let height:CGFloat = self.view.frame.height*0.85/CGFloat(crossWordData.count)
The collections view height is 85% in the screen layout

How to set spacing between collectionview cells in Swift 3?

currently i am using swift 3 and storyboard, googled everything and looked over all stackoverflow similar questions, got nothing so far.
On my example Porject,
my Collection view looks like this
Simulator Screenshot
which is not what i want, i want a grid layout with no spacing at all, i edited the storyboard values ddin't got anything there, so for that i used this code
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let width = UIScreen.main.bounds.width
layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
layout.itemSize = CGSize(width: width / 2, height: width / 2)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
collectionView!.collectionViewLayout = layout
didn't work either :(
'if let layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout{
let width = UIScreen.main.bounds.width
layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
layout.itemSize = CGSize(width: width / 2, height: width / 2)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
}'

swift collection view resizing problems

So the problem which I have is, the collection view, depending on what simulator I am using it displays either 3(iPhone 5) columns in one setting or 4 columns(iPhone 6) in another. I want the collection view to always displays 4 columns no matter how big or small the screen is. Here is some code I am using so far:
override func viewDidLoad() {
super.viewDidLoad()
let screenWidth = UIScreen.mainScreen().bounds.size.width
let screenHeight = UIScreen.mainScreen().bounds.size.height
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 100, height: 80)
collview1 = UICollectionView(frame: CGRectMake(0, 0, screenWidth, screenHeight), collectionViewLayout: layout)
[collview1.reloadData];
}
You'll want to change your layout.itemSize to a calculated value.
Something like:
layout.itemSize = CGSize(width: (screenWidth - spacing) / numberOfColumns, height: desiredHeight)
Spacing would be the total inter item spacing in a row plus the left and right insets.
DesiredHeight should probably be a calculated value to maintain the aspect ratio of your cells between devices.
Hopefully that's helpful.