Create Grid Layout Using UICollectionView in iOS 6

Do you still remember the Recipe app that we have worked on several months ago? At that time, we showed you how to display a list of recipes using UITableView. Wouldn’t be great if it can display the recipe in a nice grid view?

The iOS 6 SDK introduces a new class called UICollectionView that allows developers to create grid-like layout out of the box.

If you have no idea about grid-like layout, just take a look at the built-in Photos app. The app presents your photos in grid format. In the pre-iOS 6 world, you have to write lots of code or make use of other libraries in order to build a similar layout. The UICollectionView, in my opinion, is the most spectacular API in iOS 6. Not only it simplifies the way to arrange visual elements in grid layout, it even lets developers customize the layout (e.g. circular, cover flow style layout) without changing the data.

Grid based Photo App

In this tutorial, we will build a simple app to display a collection of recipe photos in grid layout. Here are what you’re going to learn:

  1. Introduction to UICollectionView
  2. How to Use UICollectionView to build a simple Grid-based layout
  3. Customizing the Collection Cell Background

UICollectionView Basics

The UICollectionView operates in a similar way to UITableView. While UITableView manages a collection of data items and displays them on screen in a single-column layout, the UICollectionView class offers developers flexibility to present items using customizable layouts. By default, the SDK comes with a UICollectionViewFlowLayout class that organizes items into a grid with optional header and footer views for each section.

The UICollectionView class manages an ordered collection of data items and presents them using customizable layouts. Collection views provide the same general function as table views except that a collection view is able to support more than just single-column layouts. Collection views support customizable layouts that can be used to implement multi-column grids, tiled layouts, circular layouts, and many more. You can even change the layout of a collection view dynamically if you want.

The UICollectionView is composed of several components:

  • Cells – instances of UICollectionViewCell. Like UITableViewCell, a cell represents a single item in the data collection. The cells are the main elements organized by the associated layout. If a UICollectionViewFlowLayout is used, the cells are arranged in a grid-like format.
  • Supplementary views – Optional. It’s usually used to implement the header or footer views of sections. (We’ll cover this in the next tutorial)
  • Decoration views – think of it as another type of supplementary view but for decoration purpose only. The decoration view is unrelated to the data collection. We simply create decoration views to enhance the visual appearance of the collection view. (We’ll cover this in the next tutorial)

Create Simple App with Grid Layout

To better understand how UICollectionView work, let’s get some hand-on experience and build a simple app. Open Xcode and create a new project using the “Single View application” template. Name the project as “RecipePhoto” with “Use Storyboard” and “Use Automatic Reference Count” enabled.

Note: Please make sure you use Xcode 4.5 or up to create the project.
UICollectionView - New Xcode Project

RecipePhoto – New Xcode Project

Designing the Collection View

Go to Storyboard and delete the default view controller. Instead, add a Collection View Controller from object library.

RecipePhoto Add Collection View Controller

Add a Collection View Controller

In the “Size Inspector” of the Collection View, you can change various size-related attributes. Let’s alter the size of the cell and change it to 100 by 100 pixels.

RecipePhoto Change Cell Size

Change the size of Collection View Cell

Next, select the Collection View Cell and set the identifier as “Cell” in the Attribute Inspector.

RecipePhoto Cell Reuse Identifier

Cell Reuse Identifier

Then, add an Image View to the cell. Xcode automatically resizes the image view and make it fit into the cell. In the “Attribute Inspector”, set the tag value to 100 for later reference.

RecipePhoto Add Image View to Cell

Add Image View to Cell

Coding the Collection View

In Project Navigator, right-click and select “New File”. Create a new class that is a subclass of UICollectionViewController and name it as RecipeCollectionViewController.

RecipePhoto Create RecipeCollectionViewController

Create RecipeCollectionViewController

Go back to Storyboard and assign it as the custom class of the Collection View Controller.

RecipePhoto Assign Custom Class

Assign RecipeCollectionViewController as the custom class

As said, the UICollectionView operates in a very similar way to UITableView. To populate data in UITableView, we have to implement two methods defined in the UITableViewDataSource protocol. Much like the UITableView, the UICollectionViewDataSource protocol defines data source methods for providing the data of the collection view. At least, you have to implement the collectionView:numberOfItemsInSection: and collectionView:cellForItemAtIndexPath: methods.

Let’s move on to code the RecipeCollectionViewController class. First, download this image pack, unzip it and add all the images into the Xcode project.

In RecipeCollectionViewController.m, declare an array for the image files:

1
2
3
@interface RecipeCollectionViewController () {
    NSArray *recipePhotos;
}

And initialize it in viewDidLoad method:

1
2
3
4
5
6
7
8
- (void)viewDidLoad
{
    [super viewDidLoad];
   
    // Initialize recipe image array
    recipeImages = [NSArray arrayWithObjects:@"angry_birds_cake.jpg", @"creme_brelee.jpg", @"egg_benedict.jpg", @"full_breakfast.jpg", @"green_tea.jpg", @"ham_and_cheese_panini.jpg", @"ham_and_egg_sandwich.jpg", @"hamburger.jpg", @"instant_noodle_with_egg.jpg", @"japanese_noodle_with_pork.jpg", @"mushroom_risotto.jpg", @"noodle_with_bbq_pork.jpg", @"starbucks_coffee.jpg", @"thai_shrimp_cake.jpg", @"vegetable_curry.jpg", @"white_chocolate_donut.jpg", nil];

}

Next, implement the two mandatory methods of UICollectionViewDataSource protocol:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return recipeImages.count;
}


- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *identifier = @"Cell";
   
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
   
    UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
    recipeImageView.image = [UIImage imageNamed:[recipeImages objectAtIndex:indexPath.row]];
   
    return cell;
}

The collectionView:numberOfItemsInSection: method returns the number of recipe images. The cellForItemAtIndexPath: method provides the data for the collection view cells. We first define a cell identifier and then request the collectionView to dequeue a reusable cell using that reuse identifier. In iOS 6, you no longer need to create the cell manually. The dequeueReusableCellWithReuseIdentifier: method will automatically create a cell or return you with a cell from re-use queue. At last, we get the image view by using the tag value and assign it with a recipe image.

Now compile and run the app. You should have a grid-based photo app.

RecipePhoto App First Version

RecipePhoto App with Grid-based Layout

Customizing the Collection Cell Background

Isn’t UICollectionView great? With a few lines of code, you can create a grid-based photo app. But what if you want to add a picture frame to the photos? Like other UI elements, the design of the collection view cell lets developers customize the background easily. The UICollectionViewCell is actually comprised of three different views including background, selected background and content view. It’s best to illustrate the cell views using a picture:
UICollectionViewCell View Components

  • Background View – background view of the cell
  • Selected Background View – the background view when the cell is selected. When user selects the cell, this selected background view will be layered above the background view.
  • Content View – obviously, it’s the cell content.

We have already used the content view to display the recipe photo. We’ll make use of the background view to show the picture frame. In the image pack you downloaded earlier, it includes a file named “pic_frame.png”, which is the picture frame. The size of the frame is 100 by 100 pixel. In order to frame the recipe photo, we’ll first resize the image view of cell and re-arrange its position.

Go to Storyboard and select the image view. Set X to 5 and Y to 8. The width and height should be changed to 90 and 72 pixels respectively.

RecipePhoto Resize Image View

Resize image view to fit into the photo frame

In the cellForItemAtIndexPath: method of RecipeCollectionViewController.m, add the following line of code:

1
    cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"photo-frame.png"]];

We first load the photo frame image and set it as the cell background. Now compile and run the app again. Your app should look like this:

RecipePhoto App with Photo Frame

RecipePhoto App with Photo Frame

What’s Coming Next

Cool, right? That’s why I said the UICollectionView is a great addition in iOS 6 SDK. In this tutorial, we just explore the basics of the class and using the default grid-based layout (i.e. UICollectionViewFlowLayout). By developing custom layout, you can organize the collection of data in coverflow style or even more stylish format.

In later tutorials, we’ll further talk about the decoration view, supplementary view and show you how to create your own layout. If you’ve followed our Recipe App tutorial, try to modify the app and convert it to use UICollectionView.

For your complete reference, you can download the full source code here. As always, leave us comment and share your thought about the tutorial.

You May Like These:

  • Việt Coding

    Nice tutorial ! But it’s if run on iOS < 6.0 ?

  • Osvaldo Cipriano

    How can we make the photo to display in a new window and also pass them with the finger to the next one. Also with double click to make zoom.

  • napolux

    Copyright suggestion: polaroid owns the copyright for the bordered picture with more “white” at bottom. Avoid using this in your app, it could be rejected. http://www.pcworld.com/article/197976/App_Store.html

    • _Mac

      Good point! But I belive it’s enough to just make the white background color a bit gray (or any other color than white), right?

  • Toby

    another fantastic tutorial, this is my favorite ios resource, great, easy to understand tutorials!
    keep making these tuts!!!! thanks

  • Joe G

    I would like to be a me to click on the collection cell and have a full size view of the image. How would I go about it? Love your tutorials!!

    • _Mac

      +1

    • Wouter

      I just managed to do this, piecing together what we learned in previous tutorials! Allow me to write you a mini tutorial for it, since I am trying to impress Simon so he will do next tutorials on using web services as I asked in another comment :)

      Anyway, the steps:

      - first you need to make sure to embed your collection view in a ‘navigation controller’ by clicking it and then in the menu choose Editor > embed in > navigation controller. This enables you to use segues.

      - then add a new View Controller on your storyboard. CTRL-drag from the collectionview cell to that new view controller and select ‘push’ as segue. Click the segue thingie and give it the identifier ‘displayDetail’.

      - in your file navigator, rightclick and do ‘new file…’, Chose Objective C class, name it RecipeDetailView Controller and make it a subclass of UIViewController. Go Back to the storyboard, and of that latest view, change the class from the default ‘UIViewController’ to your ‘RecipeDetailViewController’ (creating this sub class because we will want to add an image property to it!).

      - In storyboard, drag an image view on your detail view. Switch to ‘assistant editor’ mode in the top right, and control-drag that imageview to RecipeDetailViewController.h, so it will create the new IBOutlet UIImageview property thingie. Give it a name like ‘imageview’, and make sure there is an @synthesize imageview; in the RecipeDetailViewController.m.

      - to assure that we will be able to set the image from that imageview from another class (we will set it in the segue like Simon did in a previous tutorial): also add @property (nonatomic, strong) bigimage; to your RecipeDetailViewController.h, and the corresponding @synthesize bigimage; in the RecipeDetailViewController.m

      - now you can configure that necessary prepareForSegue method in RecipeCollectionViewController.m. Make sure there is an #import “RecipeDetailViewController.h” at the top, and then add a function like this, completely analogous to the ‘passing data between views with a segue’ tutorial:

      - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
      if ([segue.identifier isEqualToString:@"displayDetail"]) {
      NSLog(@”Was here”);
      NSIndexPath *indexPath = [[self.collectionView indexPathsForSelectedItems] objectAtIndex:0];
      DetailViewController *destViewController = segue.destinationViewController;
      NSString *imagename = [recipeImages objectAtIndex:indexPath.row];
      NSLog(@”Image named: %@ at row %d”, imagename, indexPath.row);
      destViewController.bigimage = [UIImage imageNamed:imagename];
      }}

      - The ‘bigimage’ property of your detailview will now be filled with the correct image that you selected. The last thing to do is to actually show it in that imageview UI object: in RecipeDetailViewController.m, add the following line to the viewDidLoad function:

      imageview.image = bigimage;

      Tataaah, that should do it! If you run your app now and tap one of his images, it should now go to a ‘detail view’ showing a large version of the image.

      • Rodrigo

        Hi! Thanks for your mini-tutorial.
        I think you made ​​a mistake: “also add @property (nonatomic, strong) bigimage;”

        @property (nonatomic, strong) UIImage *bigimage;

        Thanks again :)

      • LighthouseRich

        Wouter, Thanks for that extra tutorial. I found it very helpful as Simon’s kept crashing for no apparent reason where as your’s seems to do the trick without being overcomplicated.

        For other newbies, I picked up slight typo in your code:

        Within the segue section the line of code

        DetailViewController *destViewController = segue.destinationViewController;

        should read:

        RecipeDetailViewController *destViewController = segue.destinationViewController;

        Thanks again,
        Lighthouse Rich.

  • _Mac

    Nice introduction to UICollectionView Simon – thank’s, just what I needed. Clean, simple tutorial with just the basics. That I then can mess around with. Really looking forward to the “customization” tutorials on this :-)

    Q: Do you know if it’s possible to use UIColletionrow to make items scroll horizontially / section? Would make a very nice UI for apps w different categories and subitems.

    BTW: Found a little typo in your tutorial…
    In the interface you create the iVar “NSArray *recipePHOTOS;” but in the viewDidLoad you initialize “recipeIMAGES = [NSArray arrayWithObjects:@”angry_birds_cake.jpg”…”

  • C.H

    When I use tabBarController as project, It will crash.

  • Hugh Jeremy

    It would be great if you could post a tutorial on giving it a detail view for this collection view. I had a go myself but couldn’t get it to work. Thanks

    • http://www.simonblog.com Simon Ng

      Yes, we’ll talk about it later. Stay tuned.

      • Wouter

        FYI for those here looking for the same: I wrote in another comment a bit below a fairly detailed explanation of how to do just this, using only the stuff that we already learned here!

  • LittlePeculiar

    Great starter for me. thanks

  • http://www.facebook.com/pattyla.patty.7 Pattyla Patty

    Hey, how to create (tab bar+collection)–>navigation–>tableView–> viewController by storyboard or code only?

    • http://www.simonblog.com Simon Ng

      Both will work. But for beginner, it’s easier to use Storyboard to embed a view controller into a navigation controller / tab bar controller. First, select the view controller you want to embed in Storyboard. From the Xcode menu, select Editor -> Embed in -> Navigation Controller / Tab Bar Controller.

      We have written a Tab Bar tutorial some time ago. You can refer to the following link for details:

      http://www.appcoda.com/storyboard-tutorial-create-tab-bar-controller-and-web-view/

      • http://www.facebook.com/pattyla.patty.7 Pattyla Patty

        Tks! no problem for the courses(TabBar+Nav+Table) &(Collection+ViewController/WebView), but my idea app is like yours style https://itunes.apple.com/us/app/tips-tricks-handbook-for-iphone/id463462029?mt=8 ….select a collectionCell–>show a table list –>ViewController(ImageView/webView…) How to write a segue for UICollectionViewCell + UITableViewController

  • Mcgvr

    What do you write in the RecipeCollectionViewController.h ?? I cant seem to connect the code with the Storyboard, PLEASE HELP :D

    • http://joshuadance.com/ Joshua Dance

      You don’t put anything in the .h file. The important step is to tell the storyboard which class it is. Simon tells you how to do this in the Coding the CollectionView section of the tutorial. If you can’t get it look up how to assign a custom class to the storyboard.

  • http://profiles.google.com/pinhojoao João Pinho

    Great tutorial!
    How can i make the cell stay always in the center of the collection view?

    Thanks!!!

  • Pingback: uicollectionview in iphone | rushabhspaceo

  • Pingback: uicollectionview in iphone | jaydeepkamani1

  • maxn00b

    Hi all, im a complete beginner and i tried to to complete this tutorial but when i run the project it stops at main.m:

    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

    I don’t get the grid layout and the app crashes in the simulator.

    im using Xcode 4.6.1, What am i doing wrong?

    Thanks in advance.

    • http://joshuadance.com/ Joshua Dance

      We would need more info to find your problem. I would try downloading the source code and then compare your project to the working one side by side. You can then see what you did wrong.

  • http://www.facebook.com/govind.narayan.56 Govind Narayan

    Hi,nice tutorial.i need a help.i am creating a sound based app.when person click on grid element a corresponding sound to be played.can you tell me how to get it done?

  • Pingback: UICollectionView Basics | rhezjovovich

  • Pingback: UICollectionView tutorial | Long Wharf

  • art

    I get “Unknown receiver ‘collectionView’. Did you mean ‘UICollectionView’?” error at the line that contains “UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];”

    Anybody have any idea on this error?

  • npersson

    If you want IOS 5 support this totorial still works with the PSTCollectionView