UICollectionViewFlowLayout minimumInteritemSpacing doesn't work - ios

I've got two problems with my UICollectionView:
minimumInteritemSpacing doesn't work
it overflows horizontally on iOS 6
I set up the layout like this:
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(70.0f, 70.0f);
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
layout.minimumLineSpacing = 0.0f;
layout.minimumInteritemSpacing = 0.0f;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
// I set the size of _collectionView in layoutSubviews:
// _collectionView.frame = self.bounds;
_collectionView.contentInset = UIEdgeInsetsMake(8.0f, 8.0f, 8.0f, 8.0f);
The image shows the result on iOS 6 (on iOS 7 there is no overflow, but the spacing between columns is still not zero)
I tried this solution https://gist.github.com/OliverLetterer/5583087, but it doesn't fix anything in my case.

From the documentation for the minimumInterItemSpacing property:
For a horizontally scrolling grid, this value represents the minimum spacing between items in the same column. This 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.
The flow layout will evenly space cells across its width, with a spacing of no smaller than the minimum you set. If you don't want the spacing, you'll need to implement your own layout.
The iOS 6 overflow issue I'm not sure about. Try dropping support for iOS 6 ;)

"line spacing" can mean the space between vertical lines.
Say you have a ordinary single line horizontal collection view.
(Eg, the whole view is simply 50 high, and the items are simply 50x50.)
As user #matt has explained
a horizontal collection view has columns of cells
the "lines" as Apple means it are the vertical "lines" (!) of cells
Thus:
in the case of a simple horizontal collection view with one row,
what Apple names the "line" spacing is - indeed - the spacing between items
Thus surprisingly in a simple horizontal collection view with one row, to set the gap between items, it's just:
l.minimumLineSpacing = 6 // Apple means "vertical scan lines" by "lines"
(minimumInteritemSpacing is completely meaningless in a normal simple horizontal collection view with one row.)
This finally explains why there are 100 pages on the internet asking why minimumInteritemSpacing just doesn't work. Fantastic tip by user #matt

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))

Create a horizontal UICollectionView with Cell's height larger than view's height

I've create a UICollectionView with UICollectionViewFlowLayout and UICollectionViewScrollDirectionHorizontal. I need to set the view's frame in fixed height.
However, some cells' height may be larger than the view's height. And when this cells shown, the console complains:
the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less than the height of the UICollectionView minus the section insets top and bottom values.
Please check the values return by the delegate.
My layout setting is as follow:
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.minimumLineSpacing = 0.f;
layout.minimumInteritemSpacing = 0.f;
Section inset is set as UIEdgeInsetsMake(0, 0, 0, 0).
UICollectionView is set as fixed frame like CGRectMake(0,0,SCREEN_WIDTH, 100).
Cell's item size is changed dynamically based on the content. So sometimes it can be larger than the collection view's height(100).
How can I fix that?
Add a fixed UIView (height < 100) to collectionCell. Then add actual view (what you want to display) (changed dynamically based on the content) to this fixed UIView.
P/s: OP found the lib GMCPagingScrollView for this kind of control also.

Paging by cells in a vertically scrolling UICollectionView when using custom sectionInset values

I have a vertically scrolling UICollectionView with paging enabled that uses a subclass of UICollectionViewFlowLayout.
My UICollectionView is 320x504 and my UICollectionViewCells are 287x490.
I add a UIImageView as a subview to my UICollectionView and to keep it from covering part of the very first cell, I use the following sectionInset values which I set on the UICollectionViewFlowLayout:
self.sectionInset = UIEdgeInsetsMake(130, 0, 100, 0);
Here are all the custom settings I'm using for the layout:
self.minimumInteritemSpacing = 10;
self.minimumLineSpacing = 30;
self.itemSize = CGSizeMake(287, 490);
self.scrollDirection = UICollectionViewScrollDirectionVertical;
self.sectionInset = UIEdgeInsetsMake(130, 0, 100, 0);
My problem is that when I try to use paging, it works, but it shows 2 cells at a time. It basically shows almost half of the previous cell, and then 80% of the next cell.
This is because of top inset value of 130 that I'm using. If I change that to 0 instead, the paging works much better when scrolling/paging.
How can I still use paging in a vertically scrolling UICollectionView and have perfect cell by cell paging when using these custom sectionInset values?
There are a ton of questions on here about this but they all focus on horizontal scrolling, not vertical scrolling.

Can't make autolayout

I'm trying to lay out six UIViews onto a UIViewController, but I can't make them appear correctly in the simulator. Could someone please explain what constraints to use here to make it appear the same on the simulator?
My desired result, as seen in interface builder:
My currently result:
I'm using storyboards, Xcode 6, iOS 8 and autolayout.
Thanks!
You don't need collectionViews, nor any trickery in code. This is easily achievable in AutoLayout in interface builder.
Btw, the number and type of constraints matters. You should keep it as common sense as possible so that you can maintain it, and keep their number to minimum for the compositing part of UI rendering to stay fast. My solution is thus less complex than #k6sandeep s.
1) Lay them all out evenly, select all 6 tiles by CMD+mouseclick and add these constraints.
2) select each tile individually and add a particular constraint as shown below.
They have the same size and "kiss" each other on all sides and main view.
Once done, interface builder will stop complaining about missing constraints and you will just recalculate frames to make it perfect.
If you are only ever going to display 6 views a CollectionView might would not be necessary. You could place a 6 views with a constraints to pin the corner views to the respective corners. Then add constraints for the horizontal spacing between each neighbouring row/column. And finally set equal width and height constraints from the first (or any view) to the others. This does mean there are more views and constraints with dragging and dropping but you wont need to worry about populating a collectionView datasource and (perhaps the best bit) you won't need to write any code.
Here is a simple gif image of what I tried. It is actually fun to do this. You have to make sure that all have equal width and equal height, the views in rows have aligning top and bottom edges, while the views in columns have aligning leading and trailing edges. Then, if you set the distance between adjacent views and the edges to zero, it will all be done.
The image below shows what I actually mean in a pictorial representation.
I had a similar problem and couldn't make it work with autolayout. Turns out a UICollectionView was perfect for this though.
For a 2 x 6 grid:
CGFloat screenWidth = [[UIScreen mainScreen]bounds].size.width;
CGFloat screenHeight = [[UIScreen mainScreen]bounds].size.height;
CGSize collectionSize = CGSizeMake(screenWidth, screenHeight);
CGFloat cellWidth = screenWidth / 2;
CGFloat cellHeight = (screenHeight - 44) / 3; // deduct title bar
CGSize cellSize = CGSizeMake(cellWidth, cellHeight);
CGPoint collectionPoint = CGPointMake(0, 0);
CGRect collectionFrame = {collectionPoint, collectionSize};
// set up collection view flow layout
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
flowLayout.minimumLineSpacing = 0;
flowLayout.minimumInteritemSpacing = 0;
flowLayout.itemSize = cellSize;
flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
// instantiate
self.categoryCollectionView = [[UICollectionView alloc] initWithFrame:collectionFrame collectionViewLayout:flowLayout];
Then you can return the cell contents in
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
Make sure you implement other necessary delegate methods of UICollectionView like numberOfItemsInSection.

UICollectionView using sections leaves a gap between cells

I'm using a UICollectionView to show several sections of data. These sections have a fixed number of items. I want all the items to show in a continuous grid.
Right now I accomplish this in horizontal orientation:
But in vertical this leaves a big gap:
I want to solve this gap between sections because it's ugly and it doesn't belong there.
I'd be happy to use a custom FlowLayout, but I can't find a tutorial that points me in the right direction (I've found several, but none of them really touch this problem specifically.)
Can anybody help me solve this problem, or at least point me in the right direction?
P.S: I've implemented sections because I'm loading the data on the fly. Using 1 section isn't an option for me at this moment.
UPDATE
On request I'm adding the values used for my current FlowLayout. I'm using the standard Horizontal Flow Layout on a fullscreen (minus UINavigationBar) UICollectionView with 21 items per section.
Scroll direction: Horizontal
Cell size: 248, 196
Header / footer size: none
Min spacing for cells: 10
Min spacing for lines: 10
Section Insets: 20, 20, 10, 10
Use like this
It will solve Gap problem
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
layout.minimumInteritemSpacing = 0;
layout.minimumLineSpacing = 2;
To remove those gaps you need to create custom layout which will act as layout for your collection view. This class will child class for UICollectionViewFlowLayout.
Then you can override below two methods and can create your own custom layout as you want.
- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path
UICollectionViewLayoutAttributes is class which will deal with cell position, frame, Zindex etc
You can also use below properties.
collectionView:layout:minimumInteritemSpacingForSectionAtIndex:
collectionView:layout:minimumLineSpacingForSectionAtIndex:

Resources