Adding an AppStore like card animation to your app

If you don’t have time for this jump to the code.


We needed an AppStore like card animation for one of our apps. While there are a few examples available on the internet that shows you how to do it, they do not look production ready, nor are they easy to integrate in your app this is why we developed this library.

There were 2 things that we kept as a guide:

  • We want it to be easy to integrate in a new/existing app
  • We want it to be as customisable as possible (should work with both scrollviews and tableviews, the content of both the card and the details screen should by fully customisable)

Luckily, Swift is pretty handy when it comes to this so we employed a series of extensions and closures to achieve just this.

Without getting into details here are the steps you need to follow do have your own AppStore like card animation:

  1. Add the library to your project either using cocoapods or the old fashioned way

2. Create your card cell and your detail view controller:

  • your card cell must have a content view (the view that will animate, 99% of the time this is the actual card) your card cell must implement CardCollectionViewCell. This is as easy as:
extension YourCollectionViewCell: CardCollectionViewCell {
    var cardContentView: UIView {
        get {
            return containerView
        }
    }
}
  • if you want the nice push effect on the card you should also add the following to your cell:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    animate(isHighlighted: true)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesEnded(touches, with: event)
    animate(isHighlighted: false)
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesCancelled(touches, with: event)
    animate(isHighlighted: false)
}
  • your detail view controller must implement CardDetailViewController:
extension YourDetailsViewController: CardDetailViewController {
    var scrollView: UIScrollView {
        return contentScrollView // the scrollview (or tableview) you use in your details view controller
    }
    var cardContentView: UIView {
        return headerView // can be just a view at the top of the scrollview or the tableHeaderView
    }
}

Note: It is your responsability to make sure the detail view controller looks in collapsed state exactly like the card cell (you can check the demo for some examples of this). This is necessarily because the detail view controller is the animated part. It starts from the same size as the card and gets expanded to fullscreen so you have to make sure that your elements overlap 1:1 over the card and are expanded smoothly.

  • to be able to dismiss the card we need to hook up into the scrollViewDidScroll method:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    dismissHandler.scrollViewDidScroll(scrollView)
}

Now you should be done, you are ready to do the transition.

3. Perform the transition:

In your cellForRowAt you can just perform the transition:

cell.settings.cardContainerInsets = UIEdgeInsets(top: 8.0, left: 16.0, bottom: 8.0, right: 16.0) //set this only if your cardContentView has some margins relative to the actual cell content view.
transition = CardTransition(cell: cell, settings: cell.settings) //create the transition
viewController.settings = cell.settings //make sure same settings are used by both the details view controller and the cell
//set the transition
viewController.transitioningDelegate = transition
viewController.modalPresentationStyle = .custom
//actually present the details view controllerpresentExpansion(viewController, cell: cell, animated: true)

You should now have a basic AppStore like card animation!

4. Animate content alongside the card transition.

Sometimes the basic card animation is not enough. You might have some other views that you want to appear/disappear, scale or do some other kind of animations alongside. Don’t worry, we’ve covered you! Here are some callbacks you can use to start/stop your animations:

extension YourDetailsViewController: CardDetailViewController {
    func didStartPresentAnimationProgress() { ... }
    func didFinishPresentAnimationProgress() { ... }
    func didBeginDismissAnimation() { ... }
    func didChangeDismissAnimationProgress(progress:CGFloat) { ... }
    func didFinishDismissAnimation() { ... }
    func didCancelDismissAnimation(progress:CGFloat) { ... }
}

Saw the GIF at the beginning of the article? It uses these callbacks to make the comment bar appear/disappear.

This is it guys, hope you liked it and please let me know what awesome card transition you built using this library!