How do I set cell spacing in a section of UICollectionView
? I know there is a property minimumInteritemSpacing
I have set it to 5.0 still the spaci
Well, if you're creating a horizontal collection view then to give space between the cells, you need to set the property minimumLineSpacing
.
Previous versions did not really work with sections > 1. So my solution was found here https://codentrick.com/create-a-tag-flow-layout-with-uicollectionview/. For the lazy ones:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributesForElementsInRect = super.layoutAttributesForElements(in: rect)
var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()
// use a value to keep track of left margin
var leftMargin: CGFloat = 0.0;
for attributes in attributesForElementsInRect! {
let refAttributes = attributes
// assign value if next row
if (refAttributes.frame.origin.x == self.sectionInset.left) {
leftMargin = self.sectionInset.left
} else {
// set x position of attributes to current margin
var newLeftAlignedFrame = refAttributes.frame
newLeftAlignedFrame.origin.x = leftMargin
refAttributes.frame = newLeftAlignedFrame
}
// calculate new value for current margin
leftMargin += refAttributes.frame.size.width + 10
newAttributesForElementsInRect.append(refAttributes)
}
return newAttributesForElementsInRect
}
Swift version of the most popular answer. Space between the cells will be equal to cellSpacing
.
class CustomViewFlowLayout : UICollectionViewFlowLayout {
let cellSpacing:CGFloat = 4
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
if let attributes = super.layoutAttributesForElementsInRect(rect) {
for (index, attribute) in attributes.enumerate() {
if index == 0 { continue }
let prevLayoutAttributes = attributes[index - 1]
let origin = CGRectGetMaxX(prevLayoutAttributes.frame)
if(origin + cellSpacing + attribute.frame.size.width < self.collectionViewContentSize().width) {
attribute.frame.origin.x = origin + cellSpacing
}
}
return attributes
}
return nil
}
}
Answer for Swift 3.0, Xcode 8
1.Make sure you set collection view delegate
class DashboardViewController: UIViewController {
@IBOutlet weak var dashboardCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
dashboardCollectionView.delegate = self
}
}
2.Implement UICollectionViewDelegateFlowLayout protocol, not UICollectionViewDelegate.
extension DashboardViewController: UICollectionViewDelegateFlowLayout {
fileprivate var sectionInsets: UIEdgeInsets {
return .zero
}
fileprivate var itemsPerRow: CGFloat {
return 2
}
fileprivate var interitemSpace: CGFloat {
return 5.0
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let sectionPadding = sectionInsets.left * (itemsPerRow + 1)
let interitemPadding = max(0.0, itemsPerRow - 1) * interitemSpace
let availableWidth = collectionView.bounds.width - sectionPadding - interitemPadding
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: widthPerItem)
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int) -> UIEdgeInsets {
return sectionInsets
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return interitemSpace
}
}
Supporting the initial question. I tried to get the spacing to 5px on the UICollectionView
but this does not work, as well with a UIEdgeInsetsMake(0,0,0,0)
...
On a UITableView I can do this by directly specifying the x,y coordinates in a row...
Heres my UICollectionView code:
#pragma mark collection view cell layout / size
- (CGSize)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return [self getCellSize:indexPath]; // will be w120xh100 or w190x100
// if the width is higher, only one image will be shown in a line
}
#pragma mark collection view cell paddings
- (UIEdgeInsets)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 0, 0, 0); // top, left, bottom, right
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 5.0;
}
#import "ViewController.h"
#import "MagazineCell.h" // created just the default class.
static NSString * const cellID = @"cellID";
@interface ViewController ()
@end
@implementation ViewController
#pragma mark - Collection view
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 30;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
mCell.backgroundColor = [UIColor lightGrayColor];
return mCell;
}
#pragma mark Collection view layout things
// Layout: Set cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"SETTING SIZE FOR ITEM AT INDEX %d", indexPath.row);
CGSize mElementSize = CGSizeMake(104, 104);
return mElementSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 2.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 2.0;
}
// Layout: Set Edges
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
// return UIEdgeInsetsMake(0,8,0,8); // top, left, bottom, right
return UIEdgeInsetsMake(0,0,0,0); // top, left, bottom, right
}
@end
Remember, it is minimum line space, not minimum inter item spacing or cell space. Because your collectionView's scroll direction is HORIZONTAL.
If it is vertical then you need to set cell space or inter item space for horizontal space between cells and line spacing for vertical space between cells.
Objective-C version
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 20;
}
Swift version:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 20
}