Expanding Cells in iOS Collection Views

Learn how to make expanding cells in iOS collection views, as in the Ultravisual app. By Naeem Shaikh.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Adding Cell Images

Colored cells are great and all, but RWDevCon cannot be expressed in color!

The starter project includes a set of images just begging to be used. (They're in Inspirations.xcassets if you want to steal a quick glance. :] )

But you can't just use them in any old way — if you're doing this tutorial, then, clearly, you're all about that awesome user experience.

Not only is it time to replace the colors with images, but you'll do so in such a way that the image actually reveals more of itself as the user scrolls the cell up to be a featured cell.

First, add a new image view to the collection view cell. Go to Main.storyboard, select InspirationCell, and resize it to 200✕200. This is not strictly necessary, but it helps you visually see what's going on more easily than the standard cell size does.

 InspirationCell

Next, open the Identity inspector and set the Class type as InspirationCell.

Custom Class Selection

Then, drag-and-drop a UIImageView object from the Xcode 10 Library onto the cell. Select the UIImageView you just added, go to the Attributes inspector and change the Content Mode to Aspect Fill.

Xcode Library

Now for a few Auto Layout constraints: Select the Add New Constraints menu at the bottom of the layout view and set up the constraints as follows:

  • Uncheck Constrain to Margins.
  • Set the leading and trailing spaces (the left and right boxes) to 0.
  • Check Height and set its value to 280 (the height of the featured cell).
  • Click Apply 3 New Constraints.

It should appear something like this:

UIImageView Contraints

From the Align menu — located to the left of the Pin menu — select Vertically in Container and apply that single constraint.

Alignment Contraints

This creates a cool effect that centers the image in the image view in proportion to the full height of the featured cell, but it appears masked by the standard cell height until the cell is fully in view.

Finally, add an outlet connection by right-clicking on InspirationCell in the Document Outline and connecting the imageView outlet to the UIImageView that you just added.

Jump over to InspirationsViewController.swift and replace the implementation of collectionView(_:cellForItemAt:) with the following:

guard let cell = collectionView.dequeueReusableCell(
  withReuseIdentifier: InspirationCell.reuseIdentifier, for: indexPath)
  as? InspirationCell else {
    return UICollectionViewCell()
}
cell.inspiration = inspirations[indexPath.item]
return cell

Since you set the cell's class in Interface Builder, you start by casting to InspirationsCell in the dequeue call. Rather than set the cell's background color, you set the cell's inspiration property to the correct entry from the array of all inspirations.

Lastly, at the top of the file, remove the definition of the colors array because you no longer need it.

Build and run — behold pure image glory!

iOS Simulator Screen Shot May 17, 2015, 11.16.04 PM

Featuring Featured Cells

The new images look great, but one thing you'll notice is that all of the images are competing for your attention regardless of where they are in the list.

In reality, only the featured cell should grab your attention.

Next, you'll add a simple UIView overlay to manage the opacity of each cell. This time, the trickery you'll use is a mask to darken cells as they move away from the featured view and lighten as they get closer to the top.

Go back to Main.storyboard and add a UIView under the UIImageView you added previously.

imageCoverView

In the Add New Constraints menu, uncheck Constrain to margins if it is selected, and this time, set all four Spacing to nearest neighbor values to 0 and select Add 4 Constraints.

ImageCoverView Contraints

Next, hook up the imageCoverView outlet from InspirationCell to the UIView you just added. Select the view again, and, in Attributes inspector, set the Background Color to Black Color.

Now that you've set up the UI to mask the images, it's time to update the mask in code.

Go to InspirationCell.swift in the Views folder and add the following method to the class:

override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
  super.apply(layoutAttributes)
  
  // 1
  let standardHeight = UltravisualLayoutConstants.Cell.standardHeight
  let featuredHeight = UltravisualLayoutConstants.Cell.featuredHeight
  
  // 2
  let delta = 1 - (
    (featuredHeight - frame.height) / (featuredHeight - standardHeight)
  )
  
  // 3
  let minAlpha: CGFloat = 0.3
  let maxAlpha: CGFloat = 0.75
  imageCoverView.alpha = maxAlpha - (delta * (maxAlpha - minAlpha))
}

This method updates the effects applied to the cell as it's rendering and moving up or down the screen. Here's what's happening step-by-step:

  1. These are the two convenience height constants that you've used previously.
  2. Calculate the delta of the cell as it's moving to figure out how much to adjust the alpha in the following step.
  3. Based on the range constants, update the cell's alpha based on the delta value.

The delta is calculated as a range of 0 to 1 as it determines the percentage of the height change from the standard height to the featured-height cells. From there, the alpha can be calculated as the percentage delta is applied to the acceptable alpha range, which is between 0.3 and 0.75, in this case.

Build and run!

Alpha

Adding Session Details

At this point, you've got the images looking great with a subtle parallax effect and alpha transparency, and you're probably feeling ready to take a victory lap around your workstation.

But before you get too excited, keep in mind that there's just one problem: Without the context of the session talk, time and room, the images are little more than pretty pictures! You'll add those bits next.

First, add the session title to each item. Open Main.storyboard and drag a UILabel from the Library onto the InspirationCell in the Document Outline. Make sure the label is created as a sibling, meaning it's on the same level in the hierarchy, of Image View and View.

Select the label and, in the Attributes inspector, make the following changes:

  • Set Text to “Inspiration.”
  • Set Color to White Color.
  • Set Font to Custom, Family to Avenir Next, with a Style of Demi Bold and a Size of 38.
  • Set Alignment to Center.

Inspiration Attribute Inspector

With the label still selected, click the Add New Constraints button in the bottom right-hand corner of Interface Builder. In the pop-up, make sure Constrain to margins is unchecked, and then add the following layout constraints:

  • Select Leading Space and set the constant to 0.
  • Select Trailing Space and set the constant to 0.
  • Select Height and set the constant to 44.

Select Add 3 Constraints.

Inspiration Label Constraints

Finally, click the Align button, select Vertically in Container, and select Add 1 Constraint:

Alignment Contraints

Your cell should now look like this:

Inspiration Label Design

Next, you'll have to hook up the new label to the cell so that you can set the text correctly. Open InspirationCell.swift and add a new property right after the declaration of imageCoverView:

@IBOutlet private weak var titleLabel: UILabel!

Then, inside of the if block of didSet, add:

titleLabel.text = inspiration.title

This ensures that the text of the label updates each time the value of the property changes.

Jump back to Main.storyboard and right-click on InspirationCell in the Document Outline to show the connections pop-up. Drag from titleLabel to the label that you just created to connect the two:

Inspiration Label Outlet

Build and run — check out those sweet, sweet session titles!

Session Title

You know what would be a cool effect on the title labels? Having them scale as the user scrolls!