Create Grid Layout Using UICollectionView in iOS 6

83 Flares 83 Flares ×

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:

Get Free Chapters of Our AppCoda Book

Learn iOS 7 Programming from Scratch

The Learn iOS 7 Programming from Scratch is a 400-page eBook written for beginners with little or even no programming experience. It is based on the tutorials of our popular programming course. The book starts with the basics and walks you through the process to create iOS apps using iOS 7 SDK and Xcode 5. Want to learn more? Check it out here and get two free chapters.


Build Your Own Game and Monetize on the Side

Learn how to develop your first iOS game and make money on the side. The starter kit will come with full source code of a memory game for both iPhone and iPad, as well as, a complete guide to explain how the code works. Check out the starter kit to learn more.


  • 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

  • Juan González

    Hi, this is a great initiation tutorial for UICollectionView. I have a few questions though. First, why don’t you set the protocols and delegates at the @interface section of the .m file? Also, when I implemented the same example on my app whenever I try to scroll the app crashes with no more output that “(lldb)” and a EXEC_BAD_ACCESS on Thread 1.

    Any idea of what could be happening? I’ve checked many times item by item on your code and my implementation and it’s exactly the same.

    Thanks again for such a great example!

  • Ankit

    nice Tutorial..!!

  • k0e3

    Why is it that in UITableView we had to add the protocols UITableViewDelegate and UITableViewDataSource, but here we don’t?

    • Anonymous

      The tutorial with the UITableView used a ViewController but here it starts off as a CollectionViewController instead of a ViewController with a CollectionView on it.

    • DoctorCobweb

      also, since we are subclassing UICollectionViewController it implicitly implies that the controller adheres to the UIControllerViewDataSource protocol (even though you dont see the typical thing in the .h file)

  • Abilash

    I used your code. In the UICollectionview, is there any way to limit the number
    of rows in section to 1 row per section. I kept multiple images under
    one section. but these images are equally divided and kept under section
    in some ‘n’ rows. My requirement is to keep all the images under one
    row and let the user scroll horizontally. Is it possible to limit the
    number of rows per section?

  • abdullatif

    nice Tutorial

  • Artem

    Hello,

    Thank you for this introduction tutorial. It looks very interesting for me (I am totally new to iOS development). I am trying to follow these instructions and was stuck on the following line

    recipeImageView.image = [UIImage imageNamed:[recipeImages objectAtIndex:indexPath.row]];

    I got the following exception

    -[UICollectionViewCell setImage:]: unrecognized selector sent to instance 0x1d0210a0

    Probably I missed something but can not see what is wrong.

    Could you please advise what should I check (I fixed recipePhotos/recipeImages typo)

    • John Kealy

      I have the same issue. Did you manage to fix this on your end?

    • raj

      I had this same problem and for the life of me couldn’t figure it out at first. Finally, I realized that I had used the ’100′ tag for BOTH the CollectionViewCell and the UIImageView. Only the UIImageView should be tagged 100

      • Hok Shun Poon

        The tutorial sets 100 for both the CollectionViewCell and the UIImageView. I unset the one on the CollectionViewCell, but now nothing shows up.

        • raj

          I used something else for CollectionViewCell. Can’t remember at the moment, but probably something like 101.

  • Pingback: ViewWithTag causing problems with UICollectionView CopyQuery | Question & Answer Tool for your Technical Queries

  • Elro

    Hello, I have a problem with code when I add this line: recipeImageView.image = [UIImage imageNamed:[recipeImages objectAtIndex:indexPath.row]];the bug is “property image is not found on object of type Array, are we declaring it?

    • DoctorCobweb

      there is an error in this tutorial code show here:

      1.the declared name of the photos array is NSArray *recipePhotos
      but
      2. the rest of the tutorial refers to NSArray *recipeImages

      so just rename recipePhotos to be recipeImages and it hopefully should work.

  • gaztesk

    Thanks !!

  • sankar ram

    Nice Tutorial !!!!! But in here I am Unable to set the Frame Setting of the Cell that you Set here X=0,Y=20& length and width I can’t set the value Please help me in this!!!!!!

    • abhi ram

      I am struggling how to use CollectionViewFlowLayout… I need to add Labels dynamically using collection view… I have posted an image below… I want exactly the same layout… Please help me out… I would be very grateful to you…. Thanks in advance….

      • sankar ram

        I hope You had follow the Tutorial for UICollectioView Layout UI so to integrate the Grid View With Label and Some other UI elements you have to use UIView in the collection View Cells , Adding those give UI-elements with UICollectionView is Simple .here I given the ScreenShot that to delete the Default viewController in the Storyboard and get the UICollectionView Controller That it!!!!

    • Guest

      great. thanks for the tutorial.

  • cybergenie

    When I run this app, it complies without errors but shows blank screen on the simulator. Can anyone suggest what would be the problem.

    • DoctorCobweb

      it probably means that you have not set the UICollectionViewController to use the custom RecipeCollectionViewController class you wrote.

      in the storyboard, click on the UICollectionViewController, then on the right hand side panel click Identity Inspector. then in the Custom Class field select the RecipeCollectionViewController option.

      hope that works.

  • abhi ram

    I am struggling how to use CollectionViewFlowLayout… I need to add Labels dynamically using collection view… I have posted an image below…I am adding labels dynamically by using a text field and depending on the width of the string the cell size should be increasing….I am unable to make size of cell…. I want exactly the same layout as shown in below image … Please help me out… I would be very grateful to you…. Thanks in advance….

    • abhi ram

      Please anybody help me out

  • Peter

    Thank You.. I always get proper solution from this site. Thanks.

  • Yuva Bharathi

    its a cool tutorial

  • Pingback: Ios 7 with xcode 5 training | Iphone Tutorial Point

  • DoctorCobweb

    great. thanks for the tutorial!

  • AJ

    That was really helpful and easy to understand, thnx

  • Pingback: Baby maglia. Facili lavori a maglia per bambini da 0 a 2 anni pdf

  • Pingback: Collection View | kamanijaydeep

  • BorisYurkevich

    Thanks, for the article. Dropbox link to ZIP archive is broken

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

      Just tried the dropbox link again. It works. Would you please try again?

  • Francisco Paredes

    Hello, this is a great tutorual! I am creating my own app which has a collectionview, within it I have collection cells containing images. When I run the simulator everything runs smoothly and my collectionview has a nice image gallery.
    When I try to archive the project and ad-hoc test it on my phone everything works perfectly but the collectionview. All my collection cell images seem to disappear and are replaced with grey blocks. Any suggestions or ideas??

  • DoctorCobweb

    that’s cray cray.

83 Flares Twitter 19 Facebook 53 Google+ 11 LinkedIn 0 83 Flares ×