Pop Animation Header

Take iOS Animation To Another Level With Facebook POP

Using animation can be a great way to dramatically improve the feel of your app. Users have come to love delightful little animations and fluid movements. As a developer it can be tough to know what animations to add. Even if you do add a few animations they may come across as too harsh or feel like a gimmick. So what can we do about this?

Over the last several months I’ve come to love a library Facebook released called POP. This library powers the animation in their Facebook Paper app and it works wonderfully. There are a few things to love about this library:

  • It’s easy to use and fun
  • The look and feel of animations can be greatly enhanced with subtle bounces at the end of an animation
  • It plays well with auto layout by allowing you to interact at the layer level
  • You can animate constraints when needed
  • It supports spring and dynamic animations

If you’ve spent any time with iOS animation you know how crazy things can get. It takes a lot of LOC to do fairly trivial tasks. Well, Facebook POP is here to help you with that. Let’s introduce you to it.

[alert color=”yellow”]github.com project[/alert]

Installing

If you already have CocoaPods added to your project then you’ll just need to add the following line to your Podfile:

pod ‘pop’, ‘~> 1.0’

If you’re not using CocoaPods you can find more instructions over on the GitHub page (why are you not using CocoaPods?).

Once you have POP added to your workspace you’ll just add the following header to your project. If you’re using Swift add this to your bridged header.

#import <POP/POP.h>

Four Animation Types

In POP you have access to four different animation styles that you can take advantage of.

Spring Animation

This is the animation I use most often simply because I love adding a slight bounce to the interface object I apply an animation to.

Let’s say we have constraints applied to the object we wish to move. We can modify the value of kPOPLayoutConstraintConstant to animate our interface object. Grab the sample project to see this in action.

func animateTop() {
    let spring = POPSpringAnimation(propertyNamed: kPOPLayoutConstraintConstant)
    spring.toValue = 200
    spring.springBounciness = bounciness // a float between 0 and 20
    spring.springSpeed = 8
    ballCenterYConstraint.pop_addAnimation(spring, forKey: "moveUp")
}

Decay Animation

If we need to move an object and return it to a starting position gradually, we can use a decay animation. This would work well if you were simulating a throw, where you want the item to return to a particular position gradually. Alternatively, loading bars could make use of this movement. Instead of using toValue you set the velocity of the object.

func animateRight() {
    let spring = POPDecayAnimation(propertyNamed: kPOPLayoutConstraintConstant)
    spring.velocity = NSValue(CGPoint: CGPointMake(-642, 0))
    rightBallCenterY.pop_addAnimation(spring, forKey: "moveRight")
}

Basic Animation

When you don’t need the power of the spring or decay animations, use the basic animation. Update properties without bounce or decay playing a factor. In the provided example I simply change the background color and alpha value for view items. In order to get the looping feel I set repeatForever and autoreverses to true.

func basicAnimation() -> POPBasicAnimation {
    let basic = POPBasicAnimation(propertyNamed: kPOPViewBackgroundColor)
    basic.toValue = randomColor()
    basic.repeatForever = true
    basic.autoreverses = true
    return basic
}
    
func alphaAnimation() -> POPBasicAnimation {
    let basic = POPBasicAnimation(propertyNamed: kPOPViewAlpha)
    basic.toValue = 0.0
    basic.repeatForever = true
    basic.autoreverses = true
    basic.duration = 2.4
    return basic
}

Custom Animation

This is where we get into advanced functionality. I’ll cover this more in a different article, but for now you can reference the examples in the Facebook pop repository. These are best used when building custom transitions and advanced animations. You’d use this when you need to manage every step of the animation (handles CADisplayLink and time-step management). I rarely have a reason to drop this low. If you’ve taken advantage of this let me know! I’d love to hear about it.

Delegation Handling

POP comes loaded with a few delegate methods that alert you to specific events. You may need to take advantage of these when you are stacking animations in order to get the feel you are going for. It may make sense to interrupt an animation the moment it reaches the expected value, but hasn’t completed the animation fully.

// Called on animation start.
pop_animationDidStart(anim: POPAnimation!)
 
// Called when value meets or exceeds to value.
pop_animationDidReachToValue(anim: POPAnimation!)
 
// Called on animation stop.
pop_animationDidStop(anim: POPAnimation!, finished: Bool)
 
// Called each frame animation is applied
pop_animationDidApply(anim: POPAnimation!)

In order to properly use these you will want to create an animation and set a name value. Additionally, you’ll set the appropriate delegate value. When one of these methods is hit you can check the animation name to verify the animation is the one you need. For example:

let spring = POPSpringAnimation(propertyNamed: kPOPLayoutConstraintConstant)
spring.toValue = 200
spring.springBounciness = bounciness
spring.springSpeed = 8
spring.name = "moveUp"
spring.delegate = self
ballCenterYConstraint.pop_addAnimation(spring, forKey: "moveUp")

Now we can observe a delegate method:

func pop_animationDidReachToValue(anim: POPAnimation!) {
    if anim.name == "moveUp" {
        // perform a new animation or action
    }
}

Properties To Know

Here is a glimpse of the more useful properties you will be taking advantage of:

  • toValue: id // value type should match the property
  • fromValue: id // value type should match the property
  • velocity: id
  • springBounciness: CGFloat // from 1 to 20
  • springSpeed: CGFloat // from 1 to 20
  • repeatForever: Bool // a convenient way to loop an animation
  • duration: CFTimeInterval // defaults to 0.4
  • beginTime: CFTimeInterval // if you want to delay the beginning of an animation
  • name: NSString // identify the animation when delegate methods are called
  • autoreverses: Bool // this will complete one full animation cycle; use repeateForever to loop the effect

Takeaway

Adding animation is easy enough! Spend some time thinking about how you can enhance the user experience by adding a few animated elements to your app. If you’re having trouble, hit me up.

Expect more from me here in the future. This is one of the areas I have a lot of fun with.

Your Turn

Have you done anything cool with POP? Let me know, I’d love to check it out.


Posted

in

by

Comments

2 responses to “Take iOS Animation To Another Level With Facebook POP”

  1. Michael Eisel Avatar
    Michael Eisel

    I had to use custom animations on a recent project. I animated the selected area of a graph from one area of the graph to another, and at each time-step I displayed the integral of the selected area.

    1. David McGraw Avatar

      That sounds cool! Have a video of it in action? Did you use anything special to help create the graph?

Leave a Reply

Your email address will not be published. Required fields are marked *