How to create cells that peek on the sides like iOS 11 App Store

Maher Santina
4 min readJun 18, 2018

Collection view scrolling and paging have always been a mystery to me. It was until recently we had a requirement for a project where there’s a collection view that shows a part of the previous and next items. So it was time to dig deeper to implement this feature.

I finally decided to implement my own logic and create a pod out of it so it can be easily integrated into projects.

The feature is available here:

The Readme file contains all the necessary information to make it working. For convenience, here’s an example:

Complete Example

After installing the pod and wiring the collection view outlet to the storyboard, here’s the result:

Collection view with peeking cell demonstration

If you’re interested in knowing the inner workings of the MSPeekCollectionViewDelegateImplementation, continue to the next section.

How does it work?

This section will cover the main functionality of the peeking delegate implementation. (Not all code is shown here but everything is there in the Github repository)

We will not rely on the already existing paging behavior in the collection view, we will implement our own logic. So the Paging Enabled checkbox will be unchecked.

The Layout:

Here’s a diagram to show the different components of the view:

Cell Spacing and Cell Peeking

You can set any value for the cell spacing by using the delegate function:

Minimum Line Spacing

It’s important to note that, for the feature to work, the cell should be centered in the view. So to do that, we need to set the left and right insets of the collection view to match the peek width and the cell spacing as shown in the figure below.

Inset and cell spacing + peeking should be equal

We can do this using the delegate function:

Inset For Section At Index Path

Since the cell will occupy the remaining space, we can set the cell’s item size as shown in the delegate function below:

Size For Item At Index Path

Since there’s two cells peeking from the sides and there’s two spaces between the cells from the left and right itemWidth can be calculated using this equation:

let itemWidth = collectionView.frame.size.width - 2 * (cellSpacing + cellPeekWidth)

The max function is used just to prevent negative values if the collection view’s width is less than the peek + spacing.

We’ll also set the minimum inter-item spacing to 0 just to be on the safe side:

Minimum Interitem Spacing

The Logic:

We will introduce a new parameter called scrollThreshold. This will determine how much scrolling is needed to snap to the adjacent cell.

We will calculate the distance scrolled by saving the scroll offset when the user starts dragging using:

Scroll View Will Begin Dragging

Here’s the main part. We can implement the logic using the delegate function scrollViewWillEndDragging .

Scroll View Will End Dragging

Let’s break this down into several steps:

  1. We get the destination where the scroll view‘s dragging will stop from the targetContentOffset pointer. The pointer points to the value where the scroll view will stop. Changing this value will change where the scroll view will stop, and it automatically animates it without any extra work.
  2. Calculate the total distance for the scroll.
  3. Check if the scroll’s magnitude is greater than the scrollThreshold and create a coefficient that has one of 3 values (-1, 0, 1). This will be added to the current index.
  4. Get the current index by dividing the offset over the item width
  5. Add the coefficient retrieved in step 3 to the current index.
  6. Get the adjacent item scroll offset by adding the item width to the cell spacing first, and then multiplying it by the new adjacent item index retrieved in step 5
  7. Set the targetContentOffset pointee to the new value, which will scroll the collection view to that offset.

Note: Make sure you set the deceleration rate to fast for the collection view or the animation would be slow:

collectionView.decelerationRate = UIScrollViewDecelerationRateFast

Thank you for checking out this tutorial. The repository is still in it’s early stages and new features are planned to be implemented in the near future. Anyone is welcome to contribute to the project and add issues.

Don’t forget to star and share the repo if you found it useful.

--

--