I'm using Xcode 9 and swift 3 to developing a pet project. It requires showing a list of images horizontally at the bottom of the screen as shown in the image below.
1. Add UICollectionView in Interface Builder
- Drag UICollectionView from the Object Library and drop it on the View Controller and set appropriate constraints (related to its superview).
- Drag UIImageView from the Object Library and drop it on the UICollectionViewCell come with the UICollectionView object and set appropriate constraints related to the UICollectionViewCel.
(Don't set constraints for the UICollectionViewCell)
2. Create a custom UICollectionViewCell class
- Select File menu > New > File...
- Select Cocoa Touch Class and click Next
- Set "Class" to
ImageCollectionViewCell then "Subclass of" to
UICollectionViewCell and make sure the "Also create XIB file" checkbox is unchecked cause we don't need it.
- Open
ImageCollectionViewCell.swift file and create an outlet connected to the
UIImageView control added in the step above.
import UIKit
class ImageCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var imageView: UIImageView!
}
- Within the storyboard, select the UICollectionViewCell control then open Identity Inspector and set Class under Custom Class section to
ImageCollectionViewCell. After that, open Attributes Inspector and set Identifier under Collection Reusable View section to
ImageCollectionViewCell.
3. Make the ViewController class conform to UICollectionViewDelegate and UICollectionViewDataSource
Create an outlet connected the UICollectionView control in the Interface Builder to the ViewController class and update it as following:
import Foundation
import UIKit
public class ViewController : UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
@IBOutlet weak var collectionView: UICollectionView!
private var images = [
UIImage(named:"theme_1"),
UIImage(named:"theme_2"),
UIImage(named:"theme_3"),
UIImage(named:"theme_4")
]
public override func viewDidLoad() {
collectionView.delegate = self
collectionView.dataSource = self
}
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCollectionViewCell", for: indexPath) as! ImageCollectionViewCell
cell.imageView.image = images[indexPath.row]
return cell
}
}
Note that any operations related to the sizes of cell's
subviews should not be done in those methods of
UICollectionViewCellDelegate because the
frame and
bounds properties are not finalized yet. Do it in
layoutSubviews() method of the cell instead.
Setting the size of the cell in the method below does not have any effects.
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
}
Setting the size of each cell and space between them
The ViewController must conform to
UICollectionViewDelegateFlowLayout protocol and implement its methods.
The code snippets below is an example of how to set the size of a cell:
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// The height and width of the container view (stackview)
// of the four buttons in the cell (xib file)
// should be the same to make them look completely circles.
// Then, the cell's width should be equal to cell's height
// plus the tick buttons's width.
// We have a constraint in the IB to define the tick button's width
// equal to one-fourth width of the container view
// so this size will fit them right.
let cellHeight = collectionView.bounds.height - 10
let tickButtonWidth = cellHeight / 4
let cellWidth = tickButtonWidth + cellHeight
return CGSize(width: cellWidth, height: cellHeight)
}
This is an example of how to set the space between cell in the same row:
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 25
}
The example below tells how to set the space between the collection view and its contents:
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
}
References
https://www.youtube.com/watch?v=SL1ZmIp83iI