About a month ago, Facebook hosted Mobile@Scale, the second in our series of small technical conferences, with speakers from Facebook, LinkedIn, Pinterest, Dropbox, and Twitter. During the conference, we announced a new open-source spring dynamics animation library for Android called Rebound. We've seen a lot of interest in this project on GitHub, so I'd like to take this opportunity share some of the motivations and concepts behind it, as well as some tips on how you can integrate it into your own applications to create physics-based animations.
Mocking up animations with Quartz Composer
Designers at Facebook work with a tool called Quartz Composer to build rich interactive prototypes before engineering work begins. Quartz Composer is a node-based visual programming language provided as part of the Xcode development environment in Mac OS X, and is used for processing and rendering graphical data. Quartz Composer includes a simple physics system that allows you to create physics-driven animation prototypes. For example, the Chat Heads feature of Facebook Messenger allows the user to drag friends' profile photos, representing ongoing conversations, around the screen. Flinging a stack of Chat Heads causes the stack to attract toward the edge of the screen and eventually come to rest after expending the energy of the fling. This is achieved by applying a spring force to the Chat Head stack, which pulls it to the target point on the edge of the screen and integrates the velocity imparted by the user's initial fling gesture.
Other examples of physics-driven animations can be seen in Facebook Home, including flinging through pages in Cover Feed, the bouncing "double-tap-to-Like" indicator, or swiping your profile picture to unlock your phone. All these interactions were initially prototyped in Quartz Composer based on its simple physics engine.
Understanding spring forces
Most of the physics animations our designers have created can be modeled using simple spring forces. A spring force is defined by Hooke's law, which states:
"…The force F needed to extend or compress a spring by some distance X is proportional to that distance.
That is, F = kx
where k is a constant factor characteristic of the spring, its stiffness."
Spring forces based on Hooke's law combined with a damping or friction force can be integrated to determine the net force acting on an object in a physics system, which according to Newton's second law can be used to determine acceleration. Integrating these forces over time can be used to solve for an equilibrium point where the spring returns to its resting position. Modifications to the tension and friction of the spring can yield different types of animation curves. For example, low friction and high tension will create an animation that moves rapidly and oscillates many times before coming to a rest or equilibrium. Low tension and high friction will create an animation that moves slowly and does not oscillate when coming to a rest.
Evaluating existing animations frameworks
Implementing gestural physics-based animations required the engineering team to do an investigation of what tools were at our disposal. We began by looking into what was available in the Android SDK. Android includes three powerful frameworks for doing animation: property animation, view animation, and drawable animation. Property animation, introduced in API level 11, allows animations to be performed on arbitrary properties of any object. View animation is the older API for doing UI animation and provides many of the same features for timing and controlling animations as property animation; however, it works only with certain transformation properties of views. Drawable animation allows frame-by-frame presentation of drawable resources in sequence to generate an animation. These frameworks all give you the ability to create animations that will execute within a specific time duration. Interpolators can be used to modify the animation timing curve to achieve effects like acceleration, deceleration, and overshooting; but they are all based on a predetermined duration for the animation whose completion ratio is applied to the interpolator function curve.
Many of the interactions we wanted for projects like Home did not seem like a good fit for this sort of time-based animation. For example, flinging a page of Cover Feed at high velocity should cause it to overshoot the target page more than a fling with less velocity. Incorporating variable velocities and travel distances to create a predetermined time-based animation felt awkward, was more difficult to program, and didn't yield the desired smooth transition from free scrolling to bouncing overshoot that we were looking for.
Since the animations mocked up in Quartz Composer were developed on a physics simulation, we decided that we should explore using a similar technique to implement these animations in Android. We believed that a physics simulation would make it much simpler and cleaner to integrate velocity, friction, and spring forces into the movement of Chat Heads or Cover Feed pages.
Initially we considered pulling in an open source physics library such as Box2d; however, we recognized that the animations the designers were creating were almost entirely based on simple spring forces. Adding a full physics engine to achieve these spring animations would add unnecessary bloat to our project, and the API might not be ideally suited for the problem we were trying to solve.
We wanted something simple, lightweight, and well-suited to the task of animating user interface elements based on physics rules and spring forces. Initially we thought of building a new type of SpringAnimator on top of the built-in ObjectAnimator framework. Since the animator framework on Android is inherently time-based, we found it wasn't the right abstraction for doing physics-driven animation. Our SpringAnimator used a trick to tell the animator system that the animation's duration was essentially infinite until the physics simulation resolved, at which point the animation was immediately finished. Although this did allow us to get realistic models of springs with input velocity and configurable tension and friction running on the animator framework, the abstraction felt wrong. We really just wanted springs or sets of springs and the ability to listen to events on those springs such as start, stop, and update, as well as the progress of the spring system as a whole (such as notifications before and after the springs in a system have been updated). These SpringListeners would allow us to perform arbitrary transformations on object properties based on the state of the spring or some mapping thereof.
Rebound is our solution to this set of requirements. Rebound provides a SpringSystem object that can manage a set of spring objects and the ability to listen to various events indicating the state of both the SpringSystem and the springs it manages.
A simple example of using rebound is presented at facebook.github.io/rebound. In this example, a mouse or touch down on the photo sets a spring value to 1 and releasing sets the spring value back to 0. The graph to the right shows the curve of the updates to the spring value as it seeks the end state of 0 or 1. The photo is scaled based on a mapping of the 0 to 1 states of the spring. One important thing to notice here is that the existing momentum and position of the spring are accounted for when the end state of the spring moves between 0 and 1. This allows code that controls Rebound animations to be more declarative. With a time-based animation, the programmer needs to create the animation, determine what the duration of it should be, start the animation, and potentially cancel and re-create another animation if the user interrupts the ongoing animation with a touch. With Rebound, you merely change the target end state and/or friction and tension configuration of the spring and let the physics engine do the work of determining how the spring will get from where it is now to the new target state. Along the way, any listeners attached to the spring will ensure that the UI is updated to represent the current state of the physics model.
These are some of the simplest examples of working with springs. However, the power of simple building blocks is that they can be combined into more-complex abstractions. A set of springs can be used to govern the motion of satellite buttons in a radial menu or the movement of pages in Pager View, or turning pages in a book, or throwing panels or dialogs off of the screen. A spring with friction but no tension can be used to model inertia so that an object just eventually slides to a stop when the friction force reduces the velocity of the object to 0. At this point, another spring could take over to cause the object to settle into a particular predetermined slot. And I'm sure you can imagine many other uses for springs. The library is intentionally simple to allow you to build the abstractions you want on top of it without incurring the weight of a full physics engine.
Will Bailey is a software engineer on Android.
Want to work on things that matter?We're hiring