Want to offer native, in-app customer service to your users? Get going quickly with Zendesk’s Mobile SDKs. Free with Zendesk.

Active Filters: Animation

Animation plays a key role in how we understand the user interfaces in the software we use. This role expands itself when animations are driven directly from a user's gestures or interactions with the interface. Today we'll look at a new framework that can help us create these types of experiences without breaking a sweat. Let's dive in.

It's called Interpolate and it's by Roy Marmelstein.

As the project's README puts it: "all animation is the interpolation of values over time."

Interpolate helps us describe the relationships that we want to exist between a user's gesture and the interpolated values that should result for the properties of our views. Let's try it by animating a color.

let colorChange = Interpolate(
  from: UIColor.whiteColor(),
  to: UIColor.redColor(),
  apply: { [weak self] (result) in
    if let color = result as? UIColor {
      self?.view.backgroundColor = color

The Interpolate type holds some configuration, next we'll want to wire it up to a gesture:

func handlePan(recognizer: UIPanGestureRecognizer) {
  let translation = recognizer.translationInView(self.view)
  let translatedCenterY = view.center.y + translation.y
  let progress = translatedCenterY / self.view.bounds.size.height

  colorChange.progress = progress

Since Pan GRs report every step of their progress as a simple float (from 0.0 - 1.0), we can simply set that progress percentage value directly on the Interpolate object.

There's tons more too, Interpolate supports easing functions, and works on all sorts of foundation types (points, rects, colors, etc.).

More info about Interpolate can be found at git.io/interpolate

Creating good-looking animations can be a lot of work. We could spend our whole day learning about curves and scaling, and transforms, and oh boy...

Instead, what if we could simply apply some popular animations to our UI elements with almost no effort at all? Today we'll check out a library called Spring that allows us to do just that.

Spring supplies a ton of common animations like shake, pop, squeeze, wobble, etc.

If we're using Interface Builder, we actually don't even need any code at all. We just use one of Spring's UIView-subclasses, then we supply our animation by name.

In code, it's equally simple:

layer.animation = "shake"

These all work great out of the box, but we can still customize the curve or individual properties if needed. Neat!

More info about Spring can be found at git.io/spring


#193: UIView Transition Basics 🐛


Most iOS developers have used the fantastic UIView animateWithDuration family of functions. But there's another, slightly-lesser known static function on UIView that can help us transition like a pro. Let's check it out:

The function we'll be trying is transitionWithView. At first glance you'll see it's takes the same duration, options, and closures as its more-popular sister function.

However, instead of applying our changes over time, this function will (conceptually) take a snapshot of our view before and after the work in the animations** closure** is performed, then visually transition from the first snapshot to the second.

func flip() {
  flipped = !flipped

    duration: 0.3,
    options: .TransitionFlipFromTop,
    animations: {
      self.button.setTitle(self.flipped ? "👎🏻" : "👍🏻", forState: .Normal)
    completion: nil

The type of transition depends on the animation option we pass in. We can do everything from simple cross-dissolves (fades), to fancy 3D flips. Super handy for simple transitions.

Download a sample project at j.mp/bite193. In it, we flip a thumbs up emoji using this incredibly simple technique.


#106: EasyAnimation 🏃


Animation is one of the greatest parts about building (and using) iOS apps. The APIs however, can feel a bit scattered. UIView's animation functions are wonderful, but some animations require using Core Animation directly.

When they do, things get progressively more complex depending on if we need to run multiple animations in succession, or just run code after an animation completes.

Today we'll look at a great library from Marin Todorov called EasyAnimation that improves on all of this. Let's dive in:

EasyAnimation makes animating CALayers that normally would require CABasicAnimation (or one of its siblings) work with the standard UIView.animateWithDuration functions:

UIView.animateWithDuration(0.3, animations: {
  self.view.layer.position.y = 64.0

Under the hood, EasyAnimation does all the heavy lifting of translating our animations back into CAAnimation code and handling all of the implementation details for us. Neat!

Normally, if we wanted to run code after one the animations on a CALayer finished, we'd need to wire up an animation delegate, implement the callback functions, make sure to clean up after ourselves, etc.

With EasyAnimation though, we're able to just use the normal completion closure.

  delay: 0.1,
  options: [.BeginFromCurrentState],
  animations: {
  self.view.layer.borderWidth = 2.0
  self.view.layer.cornerRadius = 12.0
}, completion: { finished in

Last but certainly not least, EasyAnimation makes "chaining" multiple animations together (running one after another) extremely convenient. It also supports cancelling the chain, repeating, delays and more:

let chain = UIView.animateAndChainWithDuration(0.3, animations: {
  self.avatarView.center = headerView.center
}).animateWithDuration(0.2, animations: {
  self.headerView.alpha = 1.0

More info about EasyAnimation can be found at git.io/easyanimation


#82: Keyboard Notifications 🔔


iOS's software keyboard has evolved quite a bit over the years. Just last week we saw a new variant of it on the new iPad Pro. The user can also connect a hardware keyboard at anytime, hiding the software one. It's important, now more than ever, that we not make any assumptions about how and when the keyboard will transition on and off the screen.

It'd be great if the system could tell us all the details of how and where it's about to animate. Then we could use that info to move our own controls and views right alongside it. For this we can listen for some keyboard notifications_, and react appropriately. Let's take a look.

We'll start by registering for two notifications in viewDidLoad:

  selector: "keyboardWillShowOrHide:", name: UIKeyboardWillShowNotification, object: nil)

  selector: "keyboardWillShowOrHide:", name: UIKeyboardWillHideNotification, object: nil)

Fun fact: Starting in iOS 9, we don't need to unregister these in deinit, the system now does it for us! 🎉

Next, we'll grab all the necessary values out of the notification's userInfo, and use them to animate our own views exactly alongside the keyboard as it slides on or off the screen:

func keyboardWillShowOrHide(notification: NSNotification) {
  let i = notification.userInfo!
  let start = view.convertRect(i[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue(), fromView: view.window)
  let end = view.convertRect(i[UIKeyboardFrameEndUserInfoKey]!.CGRectValue(), fromView: view.window)

  bottomConstraint.constant -= (end.origin.y - start.origin.y)

  let duration = i[UIKeyboardAnimationDurationUserInfoKey]!.doubleValue

  UIView.animateWithDuration(duration, delay: 0, options: .BeginFromCurrentState, animations: {
  }, completion: nil)

We grab the start and end frames, convert them to our view controller's view's coordinate space, and use the difference to move a constraint. Then we animate the constraint like we covered Bite #9.

Animating between two sets of Auto Layout constraints is quite simple.

All you have to do is update your installed/configured constraints and then call layoutIfNeeded inside of a UIView.animateWith* closure.

class DoorsViewController: UIViewController {
    var open: Bool = false {
        didSet { transition() }

    func transition() {
        self.view.layoutIfNeeded() // force layout before animating

        UIView.animateWithDuration(0.4) {
            // change constraints inside animation block

            // force layout inside animation block

    func updateConstraintsForDoors() {
        leftDoorHorizontalConstraint.constant = open ? -16 : -leftDoorView.bounds.size.width
        rightDoorHorizontalConstraint.constant = open ? -16 : -rightDoorView.bounds.size.width

Download sample project