OVERVIEW
The best and most effective way to make a rectangular grid of images is to use the CollectionView object. Though one would assume the TableView would be a better approach, but the CollectionView offers far more in terms of customization and features and the usage is basically the same as that of a TableView.
I am going to use the default ViewController for this purpose and not creating a separate Controller for the CollectionView. I am using the Storyboard and it is assumed that the View will contain other components apart from the image grid, which is quite often a real-world case.
IMAGE DATA
The images used to populate the grid are taken from images in the Assets.xcassets list. In this case there are two images, which are stored in an array and they are repeated through the grid.
STEPS
It is not complicated to setup a CollectionView , but generally it involves several small steps and its easy to sometimes forget one step, which causes the CollectionView to not work. The steps are given below:
1.Create a Single View Application
2.Open Storyboard and put a title label in the center. Set the constraints so that it is centered horizontally.
3.We are going to use the iPhone 6 simulator. But you are free to use any target device.
4.On building and running the app, this is how the title label should look.
5.Now we will add a CollectionView to the View. Let it fill the whole width of the view and as much height as you want. Note that we will not be adding a Collection View Controller or a Collection View Cell, since the default View Controller will handle our Collection and the CollectionView already has a CollectionViewCell.
6.We are using two images added to our assets folder
7.We will now set the size of each of the Cell in the CollectionView which will hold the images. This is done by clicking the CollectionView in the storyboard and going to the Size Inspector . Change the Cell Size to 100 x 100 as shown below. This is because our images will be 95 x 95 in size, and we want to keep a little padding around each image. Set the Min Spacing for Cells and Lines to 2. This represents the gap between cells and rows.
8. We will now add an ImageView to the CollectionView cell. Drag the ImageView over the cell till it gets highlighted in blue and then drop it.
9.Click on the ImageView and then change the size from the Size Inspector to make it 95 x 95
10.The CollectionView needs to be assigned a Delegate and a DataSource . This will be the current ViewController in which the CollectionView is placed. Right click on the CollectionView, Under Outlets. drag the empty circle in front of dataSource and drag it to the yellow icon at the top of the View Controller. Repeat the same for delegate.
11. We need to create a new Class which will control the CollectionViewCell in the Collection. All that this class will contain are the subviews that will go into the Cell. In our case, it will contain only an Image. So we create a new Class first by going to File->New->File->Cocoa Touch Class and entering a name for our Class: MyImageCell
12.In the Storyboard, we select the CollectionViewCell, open the Identity Inspector and assign it the classname of MyImageCell. Note that this Class is assigned to the Cell and not the ImageView which is contained in it.
13.We now need to create an IBOutlet for the ImageView within the Cell. Keeping the Storyboard open and ImageView selected, click on Assistant Editor. You will have to manually choose the MyImage.Swift file and then ctrl-drag the ImageView into the swift file to create an IBOutlet. Lets call it image
14.In Storyboard, select the CollectionViewCell, (not ImageView) and open the Attributes Inspector. Give it an id which will be called in the swift code.
15.Select the CollectionView and set the height and width as required. We are going to make it fill up the screen width.
16.Now we will add in the code to the ViewController.swift file.
- Two variables: imageData to hold a string array of the image names, imageCounter, which will be used to iterate through the imageData.
- ViewController will declare UICollectionViewDelegateFlowLayout, UICollectionViewDataSource in its definition since it is acting as a controller and datasource for the CollectionView
- Four methods which need to be implemented for handling the Collection:
- collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
- numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
- collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
- collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
The collectionView function with cellForItemAtIndexPath handles the actual populating of the image data. The numberOfSectionsInCollectionView sets up the number of sections in the Collection, which is 1 in this case. numberOfItemsInSection sets how many items are there in the section. We have hard coded it to 20. sizeForItemAtIndexPath sets the width and height of the invidual cells. This value decides when a new row will be started. Generally a new row will start if the remaining space in the current row is less than the size of the Cell.
// // ViewController.swift // ImageGrid // // Created by Amit Sengupta on 10/4/15. // Copyright © 2015 amit. All rights reserved. // import UIKit class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { var imageData: [String] = [String]() var imageCounter: Int = 0 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. imageData = ["box-8", "box-9"] } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cellId", forIndexPath: indexPath) as! MyImageCell cell.backgroundColor = UIColor.blackColor() var currImage:String = "" currImage = self.imageData[self.imageCounter] self.imageCounter += 1 if self.imageCounter >= self.imageData.count { self.imageCounter = 0 } cell.image.image = UIImage(named: currImage) return cell } func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { return 1 } func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 20 } func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { return CGSize(width: 90, height: 90) } }
The output should look like this.
Leave a Reply