Advanced Screen Transitions on iOS

Dimitri James Tsiflitzis

CocoaheadsSKG

for the rest of us

About CocoaheadsSKG

CocoaHeads is a group devoted to the discussion of Swift,  Objective-C and Cocoa. During meetings, members present on their projects, offer tutorials and discuss the latest news over a drink or two.

CocoaheadsSKG

  • 4 years
  • 32 Meetups
  • 276 members
  • Every month
  • Post meetup drinks
  • New feature 2019: Restaurant meetups
  • Best members ever in the universe and in perpetuity

About CocoaheadsSKG

CocoaheadsSKG

Animation in mobile applications

  • Animation is an essential part of the user experience.
  • There are many things you can subtly convey animating.
    • ​Send a message
    • Turn a switch on
    • Navigate to another page
  • Animating is a pretty good way to reinforce a user initiated action.

CocoaheadsSKG

...and bringing a user interface to life.

Animation in mobile applications

CocoaheadsSKG

About me

I could have been somebody

I'm Dimitri

I could have been a contender

Instead I'm just a simple man trying to make my way in the universe

CocoaheadsSKG

  • Oftentimes users go through a series of steps to complete an action
    • ​Sign up for a service
    • Create a post
  • It should be clear that steps are connected to each other.
  • Animation can help you to connect each step to create a homologous journey.

When to use custom transitions

To connect multiple steps in a series

CocoaheadsSKG

Out of the box transitions on iOS

Presenting a view controller

CocoaheadsSKG


let viewController = ...

present(viewController, animated: true)

Out of the box transitions on iOS

Code for presenting a view controller

CocoaheadsSKG

Out of the box transitions on iOS

Pushing a view controller onto the navigation stack

CocoaheadsSKG


let vc = ...

navigationController?.pushViewController(vc, animated: true)

Out of the box transitions on iOS

Code for pushing

CocoaheadsSKG

Custom transitions on iOS

To create custom transitions you have to follow three steps:

  • Create a class that implements the UIViewControllerAnimatedTransitioning protocol
  • Before presenting a view controller, set a class as its transitioning delegate 
  • Implement an animation controller
  • Optionally make it interactive (like the built in push transition)

CocoaheadsSKG

Some transitions already out there

CocoaheadsSKG

UIKit custom transition API

  • Any view controller can have a transition delegate
  • In that implementation you can provide your custom animation and interaction controllers
  • They will be responsible for the actual animation process
  • This delegate is the location where you can inject your own animation code

UIViewControllerTransitioningDelegate

CocoaheadsSKG

These objects are returned by the transition delegate, so you can implement your own desired custom view animations.

UIKit custom transition API

UIViewControllerAnimatedTransitioning

CocoaheadsSKG

  • This context encapsulates transition information
  • You can get references to all views, subviews and controllers from this object
  • The transitioning context is available for you to use it during the animation
  • This is the only place you could write your own code that isn't boilerplate

UIKit custom transition API

UIViewControllerContextTransitioning

CocoaheadsSKG

This gives you the "magical" ability to swipe a navigation controller interactively back and forth from the edge of the 📱

UIKit custom transition API

UIPercentDrivenInteractiveTransition

CocoaheadsSKG

UIKit custom transition API

CocoaheadsSKG

UIKit custom transition API

CocoaheadsSKG

Using their imagination

CocoaheadsSKG

Using their imagination

CocoaheadsSKG

Using their imagination

CocoaheadsSKG

Using their imagination

CocoaheadsSKG

Let's look at some actual code

CocoaheadsSKG

Set the transitioning delegate


class DetailViewController: UIViewController {
 
     /* ... */

    override func prepare(for segue: UIStoryboardSegue, 
                             sender: Any?) {

        super.prepare(for: segue, sender: sender)

        guard 
            let controller = segue.destination as? ModalViewController 
        else {
            return
        }
        
        controller.transitioningDelegate = self
    }
}

CocoaheadsSKG

UIViewControllerAnimatedTransitioning


extension DetailViewController: UIViewControllerTransitioningDelegate {

    func animationController(forPresented presented: UIViewController,
                             presenting: UIViewController,
                             source: UIViewController) 
                             -> UIViewControllerAnimatedTransitioning? {
        return FadePushAnimator()
    }

    func animationController(forDismissed dismissed: UIViewController)
                             -> UIViewControllerAnimatedTransitioning? {
        return FadePopAnimator()
    }
}

CocoaheadsSKG

The animation controller

open class FadeOutAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    
    let duration: TimeInterval
    
    public init(type: TransitionType, duration: TimeInterval = 0.25) {
        self.duration = duration
        super.init()
    }

    open func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) 
                                 -> TimeInterval {
        return self.duration
    }
    
    open override func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {

        guard
            let fromViewController = transitionContext.viewController(forKey: .from)
        else {
            return
        }
        
        let duration = self.transitionDuration(using: transitionContext)
        UIView.animate(withDuration: duration, animations: {
            fromViewController.view.alpha = 0
        }, completion: { _ in
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        })
    }
}

CocoaheadsSKG

The end result

CocoaheadsSKG

3rd party libraries

CocoaheadsSKG

3rd party libraries

CocoaheadsSKG

3rd party libraries


self.hero.isEnabled = true
redView.hero.id = "ironMan"
blackView.hero.id = "batMan"
whiteView.hero.modifiers = [.translate(y:100)]



redView.hero.id = "ironMan"
blackView.hero.id = "batMan"

View controller 1

View controller 2

CocoaheadsSKG

Conclusion

  • Animation is powerful when used responsibly
  • It brings interfaces to life...
  • ...and tells a story much more effectively.

CocoaheadsSKG

Ευχαριστούμε 🎈

CocoaheadsSKG

Advanced Screen Transitions on iOS

By tsif

Advanced Screen Transitions on iOS

  • 318