I need to fix a small issue with my UICollectionView, when on the 6s device size I get a layout like this:
However, I want to know what is the best way to either center them so that its two lines, or should i shrink them down a bit so I can put three of them? I think I would prefer to center the two columns instead so I'm not cramming too much onto the same screen. I looked but wasn't sure what to do with the Layout formatting.
Thank you!
I believe one or both of these are what you are looking for. Play with the values you return and see what happens. Also, your constraint inside each cell will have some effect that I can not predict without seeing them.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionView, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0, 0, 0, 0)
}
Related
I'm developing an app with xcode/swift and the constraints that i put are only working for one screen size.
I looked for solutions, i saw things involving auto-layout but nothing has worked for me.
What i Want
What i have when i change the screen format
Can someone please help me, what is the best solution to have the layout adapt itself to the different screen resolutions ?
Thank you
The best solution in your case is to use UICollectionView, create one UICollectionViewCell with label and change background according to your data. Then, set your UIViewController as delegateFlowLayout, which has method:
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
Here you can calculate size for your according to screen size. UIScreen.main.bounds.size returns CGSize which is size of the screen.
Delegate methods can be used to set inter item and line spacing between cells.
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat
Guide from Apple about collection view.
Normally I just use this function:
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat
to set some spacing between the items in a collectionView, but the spacing is the same for all items. I would like to set the spacing to be different between some items, depending on some logic that I need to check, the logic will depend on which cell is before and after, so I would need something like IndexPath to check that.
When we want to set size of a cell, we conveniently get IndexPath from the function below, but not from the function above.
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
What can I do to achieve this?
There's no good way to do it without creating your own layout. There's too much to it to go into it here, but there's tons of good tutorials on the matter. Here's a good place to start.
I'm trying to implement UICollectionView (flowLayout) with self sizing items.
Implementation is very simple - I have just set estimatedItemSize and set UICollectionViewCell constraints to manage it's size.
Everything works fine at first data reload after collectionView was created, but on another or some other reload few items at the top becomes same size as estimatedItemSize is. If scroll down and up - items size looks good again.
I have spend 2 days with this issue experimenting different cell constraints, trying to setNeedsLayout in various places and other stuff around collectionView. Is it bug?
In this post I had an interesting problem that I found my own answer to. There are two important functions to be using properly for the sizing purposes which are:
minimumInteritemSpacingForSectionAtIndex
insetForSectionAtIndex
sizeForItemAtIndexPath
Example of me using them in Swift
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionView, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0, 0, 0, 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
let screenRect: CGRect = collectionView.bounds
let screenWidth: CGFloat = screenRect.size.width
let cellWidth: CGFloat = screenWidth / 24
//Replace the divisor with the column count requirement. Make sure to have it in float.
let size: CGSize = CGSize(width: cellWidth, height: cellWidth)
return size
}
The biggest secret is to be careful about attaching your views to the trailing edge and the bottom layout. If you only attach them to leading and the top, then you can set the width and height programmatically through frame or constraints. I think that doing it through constraints is a little more straight forward, though in my personal project I have chose to do it the other way because it makes the functionality slightly cleaner in my opinion.
Try to accomplish as much of a cells layout as possible inside of cellForItemAt.
I want to have equal amount of spacing between all the cells as well as between the screen border and the closest cell. Basically something like this. Equal spacing in and all around.
I managed to test this in the interface builder by setting values like this. I set the cell size to 110, Min spacing to 0 and all Section Insets to 10.
And it looks perfect in the IB.
However when I run it (in an iPad Air 2), it looks like this.
Notice the spacing in between the cells is bigger. I also tried to do this solely from the code by implementing the following methods from the UICollectionViewDelegateFlowLayout.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: 110, height: 110)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 0
}
That yielded the same results. Can anybody please tell me how to correct this? I'd prefer to do this by code. But I'm open to anything.
Unluckily, this is how UICollectionViewFlowLayout works by default. That's because you specify exact section insets but minimum interitem space.
To do what you're asking, you mainly have two ways to do it depending on the end result you wish for. Both have to be done manually by code.
• Enlarge the cells to leave the exact space (same space, bigger cells)
• Compute the space and change the insets to match it (same cells, bigger space)
Both can be done by either setting the values on the layout object (and invalidating it) or by returning the values through the delegate.
By default, a collection view will attempt to space out the cells in the collection by spacing them evenly so that there will be one cell touching either side of the collection view. Example:
But, when the cell is too wide to fit multiple cells in one row on the collection view, it will centre the cell in the collection view.
Is there a way to make the behaviour of centring cells, like in the 3rd picture, the default for the collection view so that there is 0 space between the individual cells and space on either side to the edges of the collection view?
Not that I'm aware of. You should implement something like this:
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
CGFloat width = UIScreen.mainScreen().bounds.size.width
return CGSize(width, anyHeight)
}
and then implement the delegate method below as well:
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsetsZero
}
Make sure to implement rotation handling too if it's applicable.
My answer would be to use a carefully set up something like
let insets = UIEdgeInsets(top: yourvalues, left: yourvalues, bottom: yourvalues, right: yourvalues),
and feed it to either YourCollectionView.contentInset, or
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return sectionInsets
}
This should work! Lemme know if you have any troubles with it!