{"id":358,"date":"2016-05-29T02:21:58","date_gmt":"2016-05-29T02:21:58","guid":{"rendered":"http:\/\/strawberrycode.com\/blog\/?p=358"},"modified":"2016-05-29T02:25:25","modified_gmt":"2016-05-29T02:25:25","slug":"uicollectionview-custom-layout-the-ultimate-tutorial-part-1","status":"publish","type":"post","link":"https:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/","title":{"rendered":"UICollectionView Custom Layout: the Ultimate Tutorial &#8211; Part 1"},"content":{"rendered":"<p>I\u2019m working every day with <code>UICollectionViews<\/code> and until recently never used a custom layout. I decided to take the plunge and learn how to create one when I had to deal with a complex layout on a <code>UICollectionView<\/code> and make my designer happy. So here is everything I learned (or everything you need to know &#8212; to start with) about custom layouts for <code>UICollectionView<\/code>.<\/p>\n<p>Let&#8217;s imagine that you have a &#8220;complex&#8221; design to integrate in a <code>UICollectionView<\/code>. And yes, you need a <code>collectionView<\/code>. When I say complex, I mean different types of cells, some of them will have a fixed size, some others will be resized on the fly depending on their content.<br \/>\nYou can always try to do things manually, it may work, but it may also take a (huge) lot of time and memory to get displayed on your device. So let&#8217;s see what a custom layout or <code>UICollectionViewFlowLayout<\/code> can do for us.<\/p>\n<p>This tutorial will be split into two parts. In the first one, we will create the <code>UICollectionView<\/code> and cells that we are going to use in the second part where we will create the custom layout.<\/p>\n<p>First, the collection view:<\/p>\n<p>To cover most of the configurations you can encounter while working on a <code>UICollectionView<\/code>, let&#8217;s imagine 3 sections with 3 different layouts &#8212; have a look at the <a href=\"https:\/\/github.com\/strawberrycode\/SCCollectionViewCustomLayout\/blob\/master\/Images\/Wireframe.png\" alt=\"Wireframe for the SCCollectionViewCustomLayout project\" target=\"_blank\">wireframe<\/a> of the layout we want to achieve:<\/p>\n<ul>\n<li>section 1: a cell with fixed size<\/li>\n<li>section 2: a cell with a fixed width and a dynamic length<\/li>\n<li>section 3: multiple cells aligned on a grid, with fixed size<\/li>\n<\/ul>\n<p>Then you can have fun and mix all that together. That&#8217;s up to you.<\/p>\n<p>Now, let&#8217;s create the <code>UICollectionView<\/code> and the cells.<\/p>\n<h2>View Controller<\/h2>\n<p>Create a new file (Cocoa Class) subclass of <code>UIViewController<\/code> and call it <code>MyCollectionView<\/code>.<br \/>\nOn the storyboard, add a <code>UICollectionView<\/code>, extend its size to match the view and add the missing constraints. Set the class to <code>MyCollectionView<\/code>.<br \/>\nLink the <code>DataSource<\/code> and Delegate to the MyCollectionView.<\/p>\n<p>Here is the skeleton of our <code>UICollectionView<\/code>:<\/p>\n<p><img src=\"https:\/\/raw.githubusercontent.com\/strawberrycode\/SCCollectionViewCustomLayout\/master\/Images\/MyCollectionView.png\" alt=\"Collection View XCode\" class=\"aligncenter\" \/><\/p>\n<p>Note: you can also create a <code>UICollectionViewController<\/code> from the beginning and skip the rest. It&#8217;s up to you.<\/p>\n<h2>Section 1:<\/h2>\n<p>Create a new file, subclass of <code>UICollectionViewCell<\/code> and name it <code>ImageCell<\/code>.<br \/>\nOpen the storyboard and in your <code>UICollectionView<\/code>, add a <code>UICollectionViewCell<\/code> (or use the default one), drag an <code>UIImageView<\/code> in the cell, expand it to match the cell edges, add missing constraints, and set the class to <code>ImageCell<\/code>.<\/p>\n<p><img src=\"https:\/\/raw.githubusercontent.com\/strawberrycode\/SCCollectionViewCustomLayout\/master\/Images\/ImageCell.png\" alt=\"Image cell XCode\" class=\"aligncenter\" \/><\/p>\n<p>In the class, create an <code>imageView<\/code> variable and connect it to the <code>UIImageView<\/code> in the Storyboard.<\/p>\n<pre class=\"lang:swift decode:true \" title=\"ImageCell\">class ImageCell: UICollectionViewCell {\r\n    \r\n    @IBOutlet weak var imageView: UIImageView!\r\n    \r\n}<\/pre>\n<p>Easy!<\/p>\n<h2>Section 2:<\/h2>\n<p>Again, create <code>UICollectionViewCell<\/code> and name it <code>TextCell<\/code>.<br \/>\nBack to the storyboard, we will create the text cell. Please pay attention, it will be slightly more complicated (2 extra steps, how difficult!).<\/p>\n<ul>\n<li>Drag a <code>UIStackView<\/code>, resize it and pin it with a small margin to the cell edges (Params: Axis = Vertical, Alignment = Fill, Distribution = Fill, Spacing = 8). I love <code>UIStackViews<\/code> btw. I&#8217;m using them all the time! (More about that in a coming article, hopefully)<\/li>\n<li>Then, drag a <code>UILabel<\/code> and drop it in the <code>UIStackView<\/code>. That&#8217;s your title, you can style it as you want (Bold, centered, &#8230;)<\/li>\n<li>And finally drag a second Label and drop it in the <code>UIStackView<\/code>, right below the title.<\/li>\n<\/ul>\n<p>Set the number of lines of the <code>UILabels<\/code> to <code>0<\/code> to enable multiline.<br \/>\nSet the class to <code>TextCell<\/code> and resolve the warnings or errors.<\/p>\n<p><img src=\"https:\/\/raw.githubusercontent.com\/strawberrycode\/SCCollectionViewCustomLayout\/master\/Images\/ImageCell.png\" alt=\"Text Cell Xcode\" class=\"aligncenter\" \/><\/p>\n<p>In the class, create a <code>titleLabel<\/code> and a <code>textLabel<\/code> variable and connect them to the labels in the Storyboard. And copy the code below in the class.<\/p>\n<pre class=\"lang:swift decode:true \" title=\"TextCell\">class TextCell: UICollectionViewCell {\r\n    \r\n    @IBOutlet weak var titleLabel: UILabel!\r\n    @IBOutlet weak var textLabel: UILabel!\r\n    \r\n    \r\n    override func awakeFromNib() {\r\n        backgroundColor = UIColor.whiteColor()\r\n    }\r\n    \r\n    \r\n    override func preferredLayoutAttributesFittingAttributes(layoutAttributes: UICollectionViewLayoutAttributes) -&gt; UICollectionViewLayoutAttributes {\r\n        \r\n        let attr = layoutAttributes.copy() as! UICollectionViewLayoutAttributes\r\n        \r\n        self.setNeedsLayout()\r\n        self.layoutIfNeeded()\r\n        \r\n        let desiredHeight: CGFloat = self.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height\r\n        attr.frame.size.height = desiredHeight\r\n        self.frame = attr.frame  \/\/ Do NOT forget to set the frame or the layout won't get it !!!\r\n        \r\n        return attr\r\n    }\r\n\r\n}<\/pre>\n<p>Beautiful!<\/p>\n<h2>Section 3:<\/h2>\n<p>Let&#8217;s do the last one, shall we? You know how to create a <code>UICollectionViewCell<\/code>, name it <code>ItemCell<\/code>.<br \/>\nAdd a <code>UIStackView<\/code> just like before.<br \/>\nThen add an <code>UIImageView<\/code> to the <code>UIStackView<\/code>. Resize it to a square and add an Aspect Ratio constraint.<br \/>\nAnd add a <code>UILabel<\/code> below the image, as we did for the <code>TextCell<\/code>.<br \/>\nDon&#8217;t forget to set the class to <code>ItemCell<\/code>.<\/p>\n<p><img src=\"https:\/\/raw.githubusercontent.com\/strawberrycode\/SCCollectionViewCustomLayout\/master\/Images\/ItemCell.png\" alt=\"Item cell Xcode\" class=\"aligncenter\" \/><\/p>\n<p>In the class, create a <code>imageView<\/code> and an <code>itemLabel<\/code> variables and connect them to the Storyboard.<\/p>\n<pre class=\"lang:swift decode:true \" title=\"ItemCell\">class ItemCell: UICollectionViewCell {\r\n\r\n    @IBOutlet weak var imageView: UIImageView!\r\n    @IBOutlet weak var itemLabel: UILabel!\r\n \r\n    override func awakeFromNib() {\r\n        setBorder(UIColor.redColor())\r\n    }\r\n    \r\n}\r\n<\/pre>\n<p>Wonderful, we&#8217;re nearly there!<\/p>\n<h2>MyCollectionView<\/h2>\n<p>Bear with me, 2 more minutes, and we&#8217;re done for part 1!<br \/>\nOpen the <code>MyCollectionView<\/code> class and follow the instructions:<\/p>\n<ol>\n<li>If you have created a <code>UIViewController<\/code>, add <code>UICollectionViewDataSource<\/code> and <code>UICollectionViewDelegate<\/code>.<br \/>\nIf <code>MyCollectionView<\/code> is a <code>UICollectionView<\/code>, skip this step.<\/li>\n<li>Create the sections variables<\/li>\n<pre class=\"lang:swift decode:true \">class MyCollectionView: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {\r\n\r\n    \r\n    @IBOutlet var collectionView: UICollectionView!\r\n    \r\n    let sectionImage = 0\r\n    let sectionText = 1\r\n    let sectionItem = 2\r\n\r\n\/\/ [...]\r\n\r\n}<\/pre>\n<li>Add the following code for the <code>UICollectionViewDataSource<\/code>.<\/li>\n<pre class=\"lang:swift decode:true \" title=\"MyCollectionView DataSource\" >    \/\/ MARK: - UICollectionViewDataSource\r\n    \r\n    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -&gt; Int {\r\n        return 3\r\n    }\r\n    \r\n    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -&gt; Int {\r\n        if (section == sectionItem) {\r\n            return 10\r\n        }\r\n        return 1\r\n    }\r\n    \r\n    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -&gt; UICollectionViewCell {\r\n        \r\n        if (indexPath.section == sectionImage) {\r\n            let cell = collectionView.dequeueReusableCellWithReuseIdentifier(\"ImageCell\", forIndexPath: indexPath) as! ImageCell\r\n            \r\n            cell.imageView.image = UIImage(named: \"InstaCat\")\r\n            \r\n            return cell\r\n            \r\n        } else if (indexPath.section == sectionText) {\r\n            let cell = collectionView.dequeueReusableCellWithReuseIdentifier(\"TextCell\", forIndexPath: indexPath) as! TextCell\r\n            \r\n            cell.titleLabel.text = \"The Cat - Wikipedia\"\r\n            cell.textLabel.text = \"The domestic cat (Felis catus or Felis silvestris catus) is a small, typically furry, domesticated, and carnivorous mammal. They are often called house cats when kept as indoor pets or simply cats when there is no need to distinguish them from other felids and felines. Cats are often valued by humans for companionship and their ability to hunt vermin. \\n\\nCats are similar in anatomy to the other felids, with strong, flexible bodies, quick reflexes, sharp retractable claws, and teeth adapted to killing small prey. Cat senses fit a crepuscular and predatory ecological niche. Cats can hear sounds too faint or too high in frequency for human ears, such as those made by mice and other small animals. They can see in near darkness. Like most other mammals, cats have poorer color vision and a better sense of smell than humans. \\n\\nDespite being solitary hunters, cats are a social species and cat communication includes the use of a variety of vocalizations (mewing, purring, trilling, hissing, growling, and grunting), as well as cat pheromones and types of cat-specific body language.\"\r\n            \r\n            cell.setBorder(UIColor.blueColor())\r\n            \r\n            return cell\r\n            \r\n        } else if (indexPath.section == sectionItem) {\r\n            let cell = collectionView.dequeueReusableCellWithReuseIdentifier(\"ItemCell\", forIndexPath: indexPath) as! ItemCell\r\n            \r\n            cell.imageView.image = UIImage(named: \"InstaCat\")\r\n            cell.itemLabel.text = \"Kitten \\(indexPath.item)\"\r\n            cell.setBorder(UIColor.redColor())\r\n            \r\n            return cell\r\n        }\r\n        \r\n        \r\n        return UICollectionViewCell()\r\n    }\r\n<\/pre>\n<li>Congrats! Job done! Run and see what happens&#8230;<\/li>\n<\/ol>\n<p><img src=\"https:\/\/raw.githubusercontent.com\/strawberrycode\/SCCollectionViewCustomLayout\/master\/Images\/MyCollectionView_NoLayout.png\" alt=\"CollectionView without UICollectionViewFlowLayout\" class=\"aligncenter\" \/><\/p>\n<p>Meh&#8230; You have a <code>UICollectionView<\/code> with cells, but why does it look like that?<br \/>\nWell we talked about using a custom layout so you didn&#8217;t expect it to work by magic, didn&#8217;t you?<br \/>\nSpeaking of the devil, we will tackle the custom <code>UICollectionViewFlowLayout<\/code> in <a href=\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-2\/\" alt=\"UICollectionView Custom Layouts: the Ultimate Tutorial - Part 2\">Part 2<\/a> of this tutorial if you don&#8217;t mind. In the meantime, you can have a look at the GitHub project if you want: <a href=\"https:\/\/github.com\/strawberrycode\/SCCollectionViewCustomLayout\" target=\"_blank\">SCCollectionViewCustomLayout<\/a> ;)<\/p>\n<p>Stay tuned!<\/p>\n<p><a href=\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-2\/\" alt=\"UICollectionView Custom Layouts: the Ultimate Tutorial - Part 2\">Part 2 of this tutorial &#8211;> this way!<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I\u2019m working every day with UICollectionViews and until recently never used a custom layout. I decided to take the plunge and learn how to create one when I had to deal with a complex layout on a UICollectionView and make my designer happy. So here is everything I learned (or everything you need to know &#8212; to start with) about custom layouts for UICollectionView. Let&#8217;s imagine that you have a &#8220;complex&#8221; design to integrate in a UICollectionView. And yes, you need a collectionView. When I say complex, I mean different types of cells, some of them will have a fixed &hellip; <a href=\"https:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">UICollectionView Custom Layout: the Ultimate Tutorial &#8211; Part 1<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":459,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[40],"tags":[17,82,41,69,85],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v16.1.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>UICollectionView Custom Layout: the Ultimate Tutorial - Part 1 - StrawberryCode<\/title>\n<meta name=\"description\" content=\"If you want to know how to create a custom layout for UICollectionView, this article is for you! This is Part 1 of UICollectionView Custom Layout tutorial.\" \/>\n<link rel=\"canonical\" href=\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"UICollectionView Custom Layout: the Ultimate Tutorial - Part 1 - StrawberryCode\" \/>\n<meta property=\"og:description\" content=\"If you want to know how to create a custom layout for UICollectionView, this article is for you! This is Part 1 of UICollectionView Custom Layout tutorial.\" \/>\n<meta property=\"og:url\" content=\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/\" \/>\n<meta property=\"og:site_name\" content=\"StrawberryCode\" \/>\n<meta property=\"article:published_time\" content=\"2016-05-29T02:21:58+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2016-05-29T02:25:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/strawberrycode.com\/blog\/wp-content\/uploads\/2016\/05\/Layout.png\" \/>\n\t<meta property=\"og:image:width\" content=\"200\" \/>\n\t<meta property=\"og:image:height\" content=\"200\" \/>\n<meta name=\"twitter:label1\" content=\"Estimated reading time\">\n\t<meta name=\"twitter:data1\" content=\"6 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/strawberrycode.com\/blog\/#website\",\"url\":\"https:\/\/strawberrycode.com\/blog\/\",\"name\":\"StrawberryCode\",\"description\":\"Fruit for Thought\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/strawberrycode.com\/blog\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-GB\"},{\"@type\":\"ImageObject\",\"@id\":\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/#primaryimage\",\"inLanguage\":\"en-GB\",\"url\":\"https:\/\/strawberrycode.com\/blog\/wp-content\/uploads\/2016\/05\/Layout.png\",\"contentUrl\":\"https:\/\/strawberrycode.com\/blog\/wp-content\/uploads\/2016\/05\/Layout.png\",\"width\":200,\"height\":200,\"caption\":\"UICollectionView Custom Layouts\"},{\"@type\":\"WebPage\",\"@id\":\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/#webpage\",\"url\":\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/\",\"name\":\"UICollectionView Custom Layout: the Ultimate Tutorial - Part 1 - StrawberryCode\",\"isPartOf\":{\"@id\":\"https:\/\/strawberrycode.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/#primaryimage\"},\"datePublished\":\"2016-05-29T02:21:58+00:00\",\"dateModified\":\"2016-05-29T02:25:25+00:00\",\"author\":{\"@id\":\"https:\/\/strawberrycode.com\/blog\/#\/schema\/person\/c328d959959928f47281d7a0ec779e2a\"},\"description\":\"If you want to know how to create a custom layout for UICollectionView, this article is for you! This is Part 1 of UICollectionView Custom Layout tutorial.\",\"breadcrumb\":{\"@id\":\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/strawberrycode.com\/blog\/\",\"url\":\"https:\/\/strawberrycode.com\/blog\/\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"position\":2,\"item\":{\"@type\":\"WebPage\",\"@id\":\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/\",\"url\":\"http:\/\/strawberrycode.com\/blog\/uicollectionview-custom-layout-the-ultimate-tutorial-part-1\/\",\"name\":\"UICollectionView Custom Layout: the Ultimate Tutorial &#8211; Part 1\"}}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/strawberrycode.com\/blog\/#\/schema\/person\/c328d959959928f47281d7a0ec779e2a\",\"name\":\"StrawberryCode\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/posts\/358"}],"collection":[{"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/comments?post=358"}],"version-history":[{"count":32,"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/posts\/358\/revisions"}],"predecessor-version":[{"id":483,"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/posts\/358\/revisions\/483"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/media\/459"}],"wp:attachment":[{"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/media?parent=358"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/categories?post=358"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/strawberrycode.com\/blog\/wp-json\/wp\/v2\/tags?post=358"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}