Collection View vertical padding issue - ios

I am making a collection view which is horizontally scrolled. The collection view is in a uitableview cell
My height of collection view is 170
I am making a cell of 75x75
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
return UIEdgeInsetsMake(4, 5, 6, 3);
}
This is my inset what I setting. Padding from top is 4 left is 5 right is 3 and bottom is 6. The collection view has 20 items horizontally scrolled. Now my problem is the vertical spacing of items when two rows are made. I want to keep it to minimum. I used this
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 2.5;
}
It provided a 2.5 padding between various items but still my vertical padding is too much as you can see from the image that vertical space between 2 lines of images is around 10. I just want to decrease that to 2.5. I did some change in return UIEdgeInset but if i increase padding from bottom, then the collection view only makes a single row that i dont want. for example if i use this
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(4, 5, 7, 3);
}
I get this output
How to overcome this problem. I just want equal and minimum spacing between all my items. which are a square (75x75). Any help will be appreciated. Thanks

Use the following code to set the height of the collection view cell.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize{
var collectionViewHeight = collectionView.fram.size.height
let cellheight = collectionViewHeight/2 - 5
return CGSize(width: cell height , height: cellheight)
}
now what it will do is that it will calculate the height of the collection view and divide it by 2 if you have fix 2 number of rows and and subtract 5 from each
as collectionViewheight is 170 and divide by 2 is 85 and then - 5 is 80 height for every cell and with width equal for square cell
this will perfectly fit the view
else if you can change the values according to you requirement

Minimum line spacing is just that -- it set the minimum spacing, but doesn't do anything to set the maximum. The collection view will add extra space between the rows if it needs to based on the size of the collection view. Your math doesn't add up. 2 X 75 (cell height) + 4 (top) + 6 (bottom) + 2.5 (interline spacing) = 162.5, but your collection view's height is 170. Change the collection view's height to 162.5, and it should work.

Related

minimumInteritemSpacing is adding some strange content at the end of collection view

I'm trying to achieve horizontally scrolling collection view with only 1 line. As I found out the easiest way to achieve that is to prepare custom flow layout:
class CollectionViewLayoutHorizontal : UICollectionViewFlowLayout {
override init() {
super.init()
//that enables self-sizing cells
self.estimatedItemSize = CGSize(width: 1, height: 1)
self.scrollDirection = .horizontal
//that one should ensure that only one line fits
//using CGFloat.greatestFiniteMagnitude aka CGFLOATMAX breaks collection view completely
self.minimumInteritemSpacing = 1000
self.minimumLineSpacing = 10
}
}
All my cells are properly displayed - they are places next to each other at the middle of collection view even when they are much smaller.
But the problem is there is an extra empty space at the end (after last cell) that is the size of minimumInteritemSpacing which is something unexpected.
Does anyone solve that problem ?
I know this is an old question but it still has no clear answer.
I ran into this exact same problem just recently using Swift 4.2 on iOS 12. After some investigations I found out that if you set the minimumLineSpacing to anything less than its default value (i.e. 10) then flow layout will add this difference multiplied by (number of items - 1) as an extra space to the end of the collection view. (Looks like the total contentSize is calculated with the default value regardless?)
Anyway I was able to solve this by setting the minimumInteritemSpacing to be the same value as minimumLineSpacing, which was 2 for both in my case.
I know it doesn't make any sense, since my collection view is a one-line with horizontally scrolling collection view flow layout, so minimumInteritemSpacing should have no effect in laying out the items, but apparently it does and this does the trick of removing the extra space at the end.
Try to implement this by:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(70, 60);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
And set the flow layout of the collection view:
-(void)setCollectionViewLayout {
UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc] init];
flow.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flow.minimumInteritemSpacing = 5;
flow.minimumLineSpacing = 5;
[yourCollectionview setCollectionViewLayout:flow];
}
Note : my collection view has constant height.
Set minimumInteritemSpacing = 0 (or some smaller value that fits to your collection design at end of scroll), if you do not need to set trailing space inside collection view.
For a vertically scrolling grid, minimumInteritemSpacing value represents the minimum spacing between items in the same row.
For a horizontally scrolling grid, minimumInteritemSpacing value represents the minimum spacing between items in the same column.
minimumInteritemSpacing spacing is used to compute how many items can fit in a single line, but after the number of items is determined, the actual spacing may possibly be adjusted upward.
For more, see Apple Developer Document: minimumInteritemSpacing
Solution for collectionViewLayout
It's caused by the width/height of the group being set as absolute / fractional. Make the scrolling side as estimated.
NSCollectionLayoutSize(widthDimension: .estimated(1.0),
heightDimension: .fractionalHeight(1))

Build up UICollectionView from center

I'm facing a problem where I want to realize a UICollectionView that essentially builds up from the center.
Let's say I have this view which shows a list of people:
When the user keeps adding multiple persons using the +, I want the CollectionView to expand but stay in the center of the view:
How do I realize this behavior?
If you are not using autolayout and size classes then you can set "center" is a collection view like this...
[collectionView setCenter:self.view.center];
And if autolayout is enabled and you are using it then do this...
Set CenterX and CenterY constrains of collection view
Set Height and width constraints of collection view
Instead of a custom flow layout, an alternative approach would be to have a full height collection view as normal and then set a top and bottom inset to visually center the cells:
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
let inset = (collectionView.frame.size.height - ((COUNT_OF_CELLS / CELLS_PER_ROW) * HEIGHT_OF_CELL) / 2)
return UIEdgeInsetsMake(inset, 0, inset, 0);
}
You will need to keep track of the total number of cells, number of cells on a row, and the cells height for the calculation to work right.

iOS - UICollectionView still have spacing between cells after set to 0

Im getting small spaces between cells when setting everything to 0. All I did in the cellForItemAtIndexPath is setting backgroundColor for each cell.
Here's my code:
//collectionView frame
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 150) collectionViewLayout:layout];
...
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
//The cell sizes are divided by the width of the collectionView.
return CGSizeMake(_collectionView.frame.size.width/12, _collectionView.frame.size.width/12);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 0.0f;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 0.0f;
}
My collection view looks like this. You'll see that there are black lines between some cells. What is causing this? How can I remove the lines?
Any help is greatly appreciated. Thanks in advance.
I too faced this problem. Thanks to #tenric for pointing out and yes for me was because the width is not divisible by the number of desired columns. My solution as follow:
var itemWidth: CGFloat {
get {
return floor(view.frame.size.width / 7)
}
}
And because I'm using AutoLayout, I just adjust the gap to the width of the collectionView as follow (refer to widthAnchor):
collectionView?.topAnchor.constraint(equalTo: headerSeparator.bottomAnchor).isActive = true
collectionView?.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
collectionView?.bottomAnchor.constraint(equalTo: footerSeparator.topAnchor).isActive = true
let gap = view.frame.size.width - (itemWidth * 7)
collectionViewWidthConstraint = collectionView?.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -gap)
because both width and height are not divisible by 12,so it would remain some empty pixel point.To avoid this,both width and height of collectionView should be multiples of 12.
I was going crazy over this too. I wanted a generic solution since I had 3 cells per row for iPhones and 4 cells per row for iPads and the UICollectionView was covering the entire width of the screen and the width is different between all devices.
I ended up making the combined width of the cells on a row wider than the device screen by using ceil(frame.width / itemsPerRow). I then calculated the total width of the cells on a row and compared with the screen width (view.frame) to get the width overflow the cells would create. Knowing the overflow I set the trailing constraint of the UICollectionView to be negative the overflow. This means the UICollectionView is actually going to overflow the screen width with a pixel or so, but in my case this was not an issue. Hopefully the code below will help clarify and give you an idea of how this could be solved.
// calculating cell width
let frame = view.frame
let cellWidth = ceil(frame.width / itemsPerRow)
// adjust UICollectionView to avoid space between cells
let totalCellsWidth = cellWidth * itemsPerRow
let overflow = totalCellsWidth - frame.width
let adjustedConstraint = -overflow
collectionViewsTrailingConstraint.constant = adjustedConstraint

Constraints issues with CollectionView

All,
I have a View Controller with a UICollectionView , and the UICollection has a collection of small images (35x35) to make a grid. I am using an inferred size of VC. I have set the top, bottom, left and right constraints..
The problem is that on the iPhone 6 the amount of cells are correct, but obviously on a iPhone 5 and iPhone 4 there is a smaller amount vertically.
How did I get it so that there is an exact amount of cells vertically on all devices ?
I am not familiar with swift, but i hope that this objective-c explanation helps:
In your -(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath method you can specify the width and height of your cell.
for example if you only want 2 cells per row and 3 per column user this:
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGRect screen = [[UIScreen mainScreen]bounds];
return CGSizeMake(screen.size.width/2 - YourHorizontalPadding, screen.size.height/3- YourVerticalPadding);
}
The vertical and horizontal padding is the space you have between your cells, you will have to tweak them to get the desired result.
Hope that helps, let me know if something is not clear.

UICollectionView, simply fit cell to width?

Here's a simple UICollectionView in yellow
The red arrow sets the width of the cell. (TBC: clicking on the pink cell: for 'size' select 'Default', then what you set at the red arrow becomes the size of the cell.)
Example, for an upright iPhone set width to 320.
But this seems crazy ... surely I can set the cell width based on the width of the UICollectionView?
There's no problem autosizing the view itself ..
That works fine.
But it seems crazy that I can't set the width of the CELL to be "same as the view". It seems hard to believe one has to set it manually, in code?
TBC In other words, as Nikita points out,
-(CGSize) collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return self.view.frame.size;
}
(indeed you also typically need this ...)
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0,0,0,0); //t,l,b,r
}
In fact - you have to do that in code?! There's no way to do that in Storyboard, with autolayout, or anything else?!
I think you need to take a look at
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
of UICollectionViewLayout where you can set size based on orientation and current frame.
It would indeed seem that you simply have to do this in code.
There is a simple way to do this. Here is the swift code. Assumes you want one item wide and in the example my cells are 64 pts high, and I want 8 pts for side margins, and finally collectionView is the name of your UICollectionView.
Insert this into viewDidLoad :
let layout = collectionView?.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize.init(width: (UIScreen.main.bounds.width - 16), height: 64.0)
This will set all the cells to default to that size. You can still override individual cells if you subclass UICollectionViewLayout or UICollectionViewFlowLayout, as mentioned in other answers. But if you simply want to have more table view like behavior this should work.
I my case cell inset making extra shapes

Resources