How to make a simple collection view with Swift How to make a simple collection view with Swift ios ios

How to make a simple collection view with Swift


This project has been tested with Xcode 10 and Swift 4.2.

Create a new project

It can be just a Single View App.

Add the code

Create a new Cocoa Touch Class file (File > New > File... > iOS > Cocoa Touch Class). Name it MyCollectionViewCell. This class will hold the outlets for the views that you add to your cell in the storyboard.

import UIKitclass MyCollectionViewCell: UICollectionViewCell {        @IBOutlet weak var myLabel: UILabel!}

We will connect this outlet later.

Open ViewController.swift and make sure you have the following content:

import UIKitclass ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {        let reuseIdentifier = "cell" // also enter this string as the cell identifier in the storyboard    var items = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"]            // MARK: - UICollectionViewDataSource protocol        // tell the collection view how many cells to make    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {        return self.items.count    }        // make a cell for each cell index path    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {                // get a reference to our storyboard cell        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MyCollectionViewCell                // Use the outlet in our custom class to get a reference to the UILabel in the cell        cell.myLabel.text = self.items[indexPath.row] // The row value is the same as the index of the desired text within the array.        cell.backgroundColor = UIColor.cyan // make cell more visible in our example project                return cell    }        // MARK: - UICollectionViewDelegate protocol        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {        // handle tap events        print("You selected cell #\(indexPath.item)!")    }}

Notes

  • UICollectionViewDataSource and UICollectionViewDelegate are the protocols that the collection view follows. You could also add the UICollectionViewFlowLayout protocol to change the size of the views programmatically, but it isn't necessary.
  • We are just putting simple strings in our grid, but you could certainly do images later.

Set up the storyboard

Drag a Collection View to the View Controller in your storyboard. You can add constraints to make it fill the parent view if you like.

enter image description here

Make sure that your defaults in the Attribute Inspector are also

  • Items: 1
  • Layout: Flow

The little box in the top left of the Collection View is a Collection View Cell. We will use it as our prototype cell. Drag a Label into the cell and center it. You can resize the cell borders and add constraints to center the Label if you like.

enter image description here

Write "cell" (without quotes) in the Identifier box of the Attributes Inspector for the Collection View Cell. Note that this is the same value as let reuseIdentifier = "cell" in ViewController.swift.

enter image description here

And in the Identity Inspector for the cell, set the class name to MyCollectionViewCell, our custom class that we made.

enter image description here

Hook up the outlets

  • Hook the Label in the collection cell to myLabel in the MyCollectionViewCell class. (You can Control-drag.)
  • Hook the Collection View delegate and dataSource to the View Controller. (Right click Collection View in the Document Outline. Then click and drag the plus arrow up to the View Controller.)

enter image description here

Finished

Here is what it looks like after adding constraints to center the Label in the cell and pinning the Collection View to the walls of the parent.

enter image description here

Making Improvements

The example above works but it is rather ugly. Here are a few things you can play with:

Background color

In the Interface Builder, go to your Collection View > Attributes Inspector > View > Background.

Cell spacing

Changing the minimum spacing between cells to a smaller value makes it look better. In the Interface Builder, go to your Collection View > Size Inspector > Min Spacing and make the values smaller. "For cells" is the horizontal distance and "For lines" is the vertical distance.

Cell shape

If you want rounded corners, a border, and the like, you can play around with the cell layer. Here is some sample code. You would put it directly after cell.backgroundColor = UIColor.cyan in code above.

cell.layer.borderColor = UIColor.black.cgColorcell.layer.borderWidth = 1cell.layer.cornerRadius = 8

See this answer for other things you can do with the layer (shadow, for example).

Changing the color when tapped

It makes for a better user experience when the cells respond visually to taps. One way to achieve this is to change the background color while the cell is being touched. To do that, add the following two methods to your ViewController class:

// change background color when user touches cellfunc collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {    let cell = collectionView.cellForItem(at: indexPath)    cell?.backgroundColor = UIColor.red}// change background color back when user releases touchfunc collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {    let cell = collectionView.cellForItem(at: indexPath)    cell?.backgroundColor = UIColor.cyan}

Here is the updated look:

enter image description here

Further study

UITableView version of this Q&A


For swift 4.2 --

//MARK: UICollectionViewDataSourcefunc numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {    return 1     //return number of sections in collection view}func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {    return 10    //return number of rows in section}func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath as IndexPath)    configureCell(cell: cell, forItemAtIndexPath: indexPath)    return cell      //return your cell}func configureCell(cell: UICollectionViewCell, forItemAtIndexPath: NSIndexPath) {    cell.backgroundColor = UIColor.black    //Customise your cell}func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {    let view =  collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "collectionCell", for: indexPath as IndexPath) as UICollectionReusableView    return view}//MARK: UICollectionViewDelegatefunc collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {    // When user selects the cell}func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {    // When user deselects the cell}


Delegates and Datasources of UICollectionView

//MARK: UICollectionViewDataSourceoverride func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {    return 1     //return number of sections in collection view}override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {    return 10    //return number of rows in section}override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionCell", forIndexPath: indexPath)    configureCell(cell, forItemAtIndexPath: indexPath)    return cell      //return your cell}func configureCell(cell: UICollectionViewCell, forItemAtIndexPath: NSIndexPath) {    cell.backgroundColor = UIColor.blackColor()    //Customise your cell}override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {    let view =  collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "collectionCell", forIndexPath: indexPath) as UICollectionReusableView    return view}//MARK: UICollectionViewDelegateoverride func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {      // When user selects the cell}override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {     // When user deselects the cell}