Reduce Spacing Between CollectionView Cell

Introduction

When we open an iPhone's gallery we see that images are structured as a grid that has rows and columns. CollectionView in iOS development is similar to that structure. It provides us a functionality that we can show items in a grid manner, it is similar to TableView but we have more functionality in CollectionView to show the items, we can display the items in a number of rows and columns and can scroll it horizontally or vertically.

We can see in this example where we have a CollectionView that has cat images, these images are structured as grid, we can scroll it down. According to Apple Developer's Documentation, CollectionView is an object that manages an ordered collection of data items and presents them using customizable layouts. Every item in CollectionView is called a cell, as in this example each image of a cat is presented in a cell.

CollectionView gets data from an object called DataSource that are stored in CollectionView's DataSource property. We can create a custom DataSource object by using UICollectionViewDataSource protocol.

Let's Start with the Xcode

Open Xcode and create single view application, name the project and click next and we are ready to go.

Go to main.storyboard file search for collectionView and simply drag and drop CollectionView to our storyboard and set all constraints to zero. Here you can see a CollectionView added to our storyboard and on the left side you can see added CollectionView. Here by default, a CollectionViewCell type of UICollectionView is added to CollectionView. In this CollectionViewCell there is added a content view, it is a place where we keep our items or content.

Now on right side go to attribute inspector name, I use indentifier as "cell", you can give any name but I gave "cell" here, When we will have to display something or place some content in CollectionViewCell we will be using this identifier name "cell".

Search for UIimage and place that image in CollectionViewCell and set all constraints to zero.

We cannot simply create an outlet for this UIImage in ViewController file, we will have to create a new file. For creating a new file just press key Command  + N click cocoa touch class select subclass as UICollectionViewCell, name the file as CollectionViewImageCell and click next and create file, new file is created.

Now click cell in our left side and got to identity inspector and give class name as new file we created "ImageCollectionViewCell".

Press control on CollectionView and drag it to our ViewController and select DataSource again press control to it and drag to ViewController and select Delegate, Now we are ready to implement our CollectionView.

Now we will go to ViewController file and write code there.

import UIKit

class ViewController: UIViewController {
    var cats = [#imageLiteral(resourceName: "kate-stone-matheson-uy5t-CJuIK4-unsplash"),#imageLiteral(resourceName: "kate-stone-matheson-uy5t-CJuIK4-unsplash"),#imageLiteral(resourceName: "yoo-ho-E3LcqpQxtTU-unsplash"),#imageLiteral(resourceName: "borna-bevanda-VwqecUsYKvs-unsplash"),#imageLiteral(resourceName: "zhang-kaiyv-SlZq1f2tmaM-unsplash"),#imageLiteral(resourceName: "mikhail-vasilyev-MEb2jandkbc-unsplash"),#imageLiteral(resourceName: "mikhail-vasilyev-MEb2jandkbc-unsplash"),#imageLiteral(resourceName: "sajad-nori-s1puI2BWQzQ-unsplash"),#imageLiteral(resourceName: "tugba-fKC47FgTsVY-unsplash"),#imageLiteral(resourceName: "sajad-nori-s1puI2BWQzQ-unsplash"),#imageLiteral(resourceName: "juli-kosolapova-nAvhy44SbkA-unsplash"),#imageLiteral(resourceName: "long-ma-hxEAE88Onv0-unsplash"),#imageLiteral(resourceName: "giovanna-gomes-0cyXsESU9yw-unsplash"),#imageLiteral(resourceName: "esteban-chinchilla-9m1OFDFAuss-unsplash"),#imageLiteral(resourceName: "tugba-fKC47FgTsVY-unsplash"),#imageLiteral(resourceName: "yoo-ho-E3LcqpQxtTU-unsplash")]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) - > Int {
        return cats.count
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) - > UICollectionViewCell {
        let cell: ImageCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell",
            for: indexPath) as!ImageCollectionViewCell
        cell.img.image = cats[indexPath.row]
        return cell
    }
}

We will create an array of images that we want to display, for this you can place all the images in Assets.xcassets file, here we are creating array of ImageLiterals and name it cat. You remember we select their DataSource and Delegate we will use those protocols here, for this we will use extension here.

Extension 

As swift documentation says Extension adds new functionality to an existing class, structure, or protocol type. This includes the ability to extend types for which you don't have access to the original source code. Extension is similar to Categories in swift. We extend UICollectionViewDelegate Protocol and UICollectionViewDataSource Protocol to our ViewController.

UICollectionViewDelegate Protocol

It is used to manage user interactions in CollectionView, highlighting, selecting, and performing actions on items. We may implement or may not implement the methods of this class.

UICollectionViewDataSource Protocol

This protocol uses DataSource object to provide data to cells to display CollectionView, by adopting this protocol we give our data to cell for display items in a CollectionView like how many rows will be there in CollectionView. By using this protocol we have to implement two methods of this protocol. The methods of this protocol are not optional we have to implement two necessary methods of this otherwise it will give error to us.

  1. NumberOfItemsInSection
    This method returns integer value, that is the number of rows in CollectionView. We provided here number of items available in cat array.
     
  2. CellForItemAt
    This method returns a cell of CollectionView, here we created a variable called "cell" that inherits ImageCollectionViewCell, we are taking that cell by that identifier name that we provided at beginning, then we are taking that image outlet that we created and giving images to each and every cell of CollectionView. here we are using indexPath.row which means in a first cell we are providing an image that we have in our first index in cat array and we are returning that cell to CollectionView.

Now run the app and see the result on simulator,

So in the result you can see there are only two columns available and some white space is there between the images of cats, don't worry this article is written to help you.

Reducing spaces between images 

extension ViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) - > CGSize {
        let collectionWidth = collectionView.bounds.width
        return CGSize(width: collectionWidth / 3 - 2, height: collectionWidth / 3 - 2)
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) - > CGFloat {
        return 2
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) - > CGFloat {
        return 2
    }
}

We will use UICollectionViewDelegateFlowLayout to reduce white spaces and set number of columns here,

UICollectionViewDelegateFlowLayout

It has several methods to work on but we will use three important methods here. 

SizeForItemAt

This method we use to define how many number of rows and columns will be in CollectionView, this returns a frame CGSize that has width and height. Here we created a collectionWidth variable that will contain the whole width of CollectionView then we will return how CGSize and pass parameters width and height divided by three you can divide any number depending upon how many columns you want in your CollectionView.

MinimumInteritemSpacingForSectionAt

This method returns CGFloat value, we are giving here two you can adjust as you want, But remember one thing what we are returning here we have minus that from the width and height parameter in SizeforItemAt method this will give us perfect look.

MinimumLineSpacingForSectionAt

This method also returns CGFloat, this method is for reducing spaces between rows in CollectionView.

Now run the app again and see the results,

This is how we reduce extra spaces in CollectionView.

Conclusion

We reduce the spaces between CollectionView cells. In this article, we used vertical scrolling CollectionView but we can also use horizontal scrolling in CollectionView. CollectionView is an important topic in iOS development and is also used in several e-commerce applications like Amazon, Flipkart etc. So open your Xcode and use this concept in your application. 

Thanks for reading this article  -- keep learning.