PART 2— Creating a custom animation inspired by InVision Projects Space 💪🏾

This part focuses on creating a custom animation from the cell view to the detail view controller. This is possible by using a custom transition when presenting the detail view controller

But before getting to deep into the animation code let’s decompose the animation

  • the cell frame goes from current to full screen
  • the logo goes from being centered in the main image to the center Y being 20% of the main image height
  • the main image with a parallax goes full width
  • the main image height is 70% of the cell height and goes 50% of the full screen
  • project name and number of projects labels fade out
  • neighbours cells slide off the screen
Animation First and Last state

I’ve refactored the CollectionViewCell to use a CardView object, so the view can be reused in our DetailViewController. Note that CardView also implement NSCopying protocol, this is required to make a clone of our view, needed for the animation.

I created a protocol CardViewTemplateProtocol who will be responsible for drawing the view in two different states (card state and full screen state).

Template Protocol

In my custom cardView class I create my template object and call the drawRect method on layoutSubviews

redraw CardView

Now let’s get back to the custom transition.

Custom Transition

We implement UIViewControllerTransitioningDelegate on the InvisionProjectSpaceCollectionViewController.

When presenting our detail view controller animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) gets called and we return the custom transition class that will be used to animate in the detail view controller.

When dismissing animationController(forDismissed dismissed: UIViewController) gets called and we return the custom transition class that will be used to animate out the detail view controller

UIViewControllerTransitioningDelegate implementation

Notice our custom transition class InvisionProjectSpaceTransition takes a constructor parameter isDismissed, so we know the current presentation state.

Before getting into the custom transition class it’s important to set the transitioningDelegate and the modalPresentationStyle of the detail view controller. Otherwise the animationController delegate won’t be called.

Set the transitioningDelegate

Let’s create our custom transition class, we conform to UIViewControllerAnimatedTransitioning protocol, and implement the 2 required method, transitionDuration and animateTransition.

animateTransition is where the magic happen 😆

We retrieve the from and to view controller using the transition context. We also have access to a containerView, it’s a temporary view in which we can add and animate our views for the duration of the animation. When the animation is done we add the final view to the container and call transitionContext.completeTransition(true)

Skeleton of the animation

1. presentController Animation

First we clone the visible views from the collectionViewController and add them to the containerView, then we animate the selected view to a full screen state and animate the other views to slide off the screen.

Present View Controller Animation

It’s important to set the options layoutSubviews of UIViewPropertyAnimator, so the cardView get’s redrawn

UIViewPropertyAnimator.runningPropertyAnimator(withDuration: duration,
delay: 0.0,
options: [.curveEaseOut, .layoutSubviews],
animations: {..}

//1. clone visible cells and get a reference to the selected cell

The helper method return a tuple, the cloned visible cells, and a pointer to the selected cell. We also convert the cell location to a global location so they appear at the exact same location when being added to the containerView.

copyVisisbleCells Helper

2. dimissController Animation

Dismissing the detail view controller uses the same principle, we do the reverse animation.

The selected cell goes from a FullScreen template to a CardView template state.

First we get the visible cells of the toViewController and set the selected view in a full screen mode.

That’s it! Hope this article was useful, Like if you enjoyed it! 💪🏾🙏🏾

The result is pretty slick, from using the same principles you could do all kind of crazy transitions requested by those creative designers 🦄 😎

You can download the final project here.