Expanding Cells in iOS Collection Views
Learn how to make expanding cells in iOS collection views, as in the Ultravisual app. By Naeem Shaikh.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Expanding Cells in iOS Collection Views
25 mins
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.
Next, open the Identity inspector and set the Class type as InspirationCell.
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.
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:
From the Align menu — located to the left of the Pin menu — select Vertically in Container and apply that single constraint.
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!
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.
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.
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:
- These are the two convenience height constants that you've used previously.
- Calculate the delta of the cell as it's moving to figure out how much to adjust the alpha in the following step.
- 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!
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.
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.
Finally, click the Align button, select Vertically in Container, and select Add 1 Constraint:
Your cell should now look like this:
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:
Build and run — check out those sweet, sweet session titles!
You know what would be a cool effect on the title labels? Having them scale as the user scrolls!