ios UICollectionView separation on top / bottom between cells - ios

I have a collection view, is working fine, and I have adjusted the separation for the X padding,
and it works fine,
but for the Y padding between cells, doesn't seem to adjust to NO separation
This is my code for the layout
UICollectionViewFlowLayout *layoutItem=[[UICollectionViewFlowLayout alloc] init];
layoutItem.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
So how can I set the separation on top / bottom to 0px? Between cells?,
thanks!

you will see only top y padding at first time.
And For showing bottom y padding you need more data that CollectionView frame height. When you scroll up collection view you will see bottom y padding.
I used collectionView like this
https://stackoverflow.com/a/17856406/1305001
When I set
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(60, 10, 50, 10);
}
The output will come as First time..
When you scrolled up collectionView you will see bottom padding..
Use this for verticle line spacing between cells
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 5;
}
Will look like

You can also do it a much simpler way using the collection view flow layout.
Set up the flow layout (remember to add the delegate in your header):
UICollectionViewFlowLayout * stickerFlowLayout = [[UICollectionViewFlowLayout alloc] init];
stickerFlowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
**stickerFlowLayout.minimumLineSpacing = 10;**
stickerFlowLayout.minimumInteritemSpacing = 5;
stickerFlowLayout.sectionInset = UIEdgeInsetsMake(10, 25, 20, 25);
// Set up the collection view
collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:stickerFlowLayout];
collectionView.delegate = self;
collectionView.dataSource = self;
etc
As you can see we can easily set the line spacing using:
**stickerFlowLayout.minimumLineSpacing = 10;**
We can also alter the other attributes
stickerFlowLayout.minimumInteritemSpacing = 5;
With the interitem spacing affecting the spaces between items (similar but different to the line spacing)
Using the flow layout you can save on a huge amount of code and set your collection view up programatically all in one place (just setting the inset and line spacing has immediately saved me two extra unneeded functions)

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

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

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.

Cell spacing in UICollectionView minimumInteritemSpacing

How to do set cell spacing in a section of UICollectionView? UICollectionView there is a property minimumInteritemSpacing, I need to set 1.0 still it not work. And I implemented the delegate method.
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 1.0;
}
To check about how your collection Cells would look, you can try this in your Storyboard with the help of storyboard. First just for the sake of checking, put some static cells in your CollectionViewController like this so that your screen appears like this :
No you can see those cells and the spacing between them. In your case, the cells will appear with improper spacing as you have shown above. So now open with this screen open, open up the Size Inspector fron your Interface Builder. It would look something like this :
Now you can see some options in the size inspector window. You can adjust the size of each cell and also the spacing between them using the Min. Spacing option. And finally for equal spacing from left and right sides, use the Section Insets Option. As you change the values there, the change will be reflected in your Controller View. So you can get an idea if you want to increase/decrease some values.
Hope this helps.
you can set programmatically like this
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
[layout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
layout.minimumLineSpacing = 0.0;
layout.minimumInteritemSpacing = 0.0;
contestsCollectionView=[[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:layout];
This method set up spaces between cells, footer and header:
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(20, 20, 20, 20);
}

Grouped UITableView 35 point / pixel top inset / padding

Please note, I'm going to refer to points as pixels in this question.
I have a grouped UITableView with 3 sections, each with a 40 pixel tall header view. The first header in the table view seems to be given a y position of 35 pixels by the system.
I've tried messing around with automaticallyAdjustsScrollViewInsets and a few other iOS 7 automatic pieces, but to no avail.
Why is my UITableView content being inset by 35 pixels?
EDIT: I've seen this answer and many other threads on this. I have valid headers and header heights. Also, setting the default to FLT_MIN, 0.01f, 1.0f or 100.0f doesn't fix the problem.
Here is my header implementation:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
UIView *header = (self.headerViews.count > section ? self.headerViews[section] : nil);
return (header.viewHeight ? : FLT_MIN);
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *header = (self.headerViews.count > section ? self.headerViews[section] : nil);
return (header.viewHeight ? header : nil);
}
I'm also setting:
- (BOOL)automaticallyAdjustsScrollViewInsets{return NO;}
and
[self setSectionHeaderHeight:FLT_MIN];
It seems that this:
[self setTableHeaderView:[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, width, FLT_MIN)]];
In init, where self is a UITableView, will get rid of the top 35 points.
Yep,i get this problem when i set tableview.tableFooterView and custom set section header height, then first section height has over 35 points.
Then i add a
tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))
worked for me.
There are multiple ways of getting the same issue you are getting and therefore, multiple solutions. I will try to list the ones I know with their corresponding solutions. Most of them are copied from this question.
UITableView inside a UIViewController
This is a common one that trips people off because they think the problem is related to their UITableView and most of the time is actually the parent UIViewController.
If your VC is embedded on a NavigationController. You will get a 35 points y offset as mentioned here.
Solutions
In Xcode Version > 5 on VC untick Extended Edges "Under Top Bars under the Attributes Inspector to remove the top UITableView content inset.
Constraints: Your VC has a main view where all the other subviews are laid including your UITableView. You need to make sure that all constraints from your UITableView are explicitily set and satisfied/non-ambiguous.
Set self.navigationController.navigationBar.translucent = YES;
Set self.automaticallyAdjustsScrollViewInsets = NO;. This one can also be set on the storyboard by unchecking the Adjust Scroll View Insets checkbox for the view controller layout.
Set self.edgesForExtendedLayout = UIRectEdgeNone;
General UITableView/UITableViewController
Set the tableView.separatorInset = UIEdgeInsetsZero;
Set the tableView.contentInset = UIEdgeInsetsMake(-35, 0, 0, 0); Pay attention to the -35. The negative number offsets the view.
Declare this method (Can also be used for FooterSection):
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return CGFLOAT_MIN;
}

Resources