Movement Engineering at Scale. How Airbnb is making use of declarative… | by Cal Stephens | The Airbnb Tech Weblog | Dec, 2022

How Airbnb is making use of declarative design patterns to quickly construct fluid transition animations

By: Cal Stephens

Movement is a key a part of what makes a digital expertise each straightforward and pleasant to make use of. Fluid transitions between states and screens are key for serving to the person protect context as they navigate all through a function. Fast thrives of animation make an app come alive, and assist give it a definite character.

At Airbnb we launch a whole lot of options and experiments which were developed by engineers throughout many groups. When constructing at this scale, it’s vital to contemplate effectivity and maintainability all through our tech stack–and movement isn’t any exception. Including animations to a function must be quick and simple. The tooling should praise and match naturally with different elements of our function structure. If an animation takes too lengthy to construct or is simply too troublesome to combine with the general function structure, then it’s usually the primary a part of a product expertise that will get dropped when translating from design to implementation.

On this submit, we’ll talk about a brand new framework for iOS that we’ve created to assist make this imaginative and prescient a actuality.

Let’s take into account this transition on the Airbnb app’s homepage, which takes customers from search outcomes to an expanded search enter display screen:

An instance transition from Airbnb’s iOS app of increasing and collapsing the search enter display screen

The transition is a key a part of the design, making all the search expertise really feel cohesive and light-weight.

Inside conventional UIKit patterns, there are two methods to construct a transition like this. One is to create a single, large view controller that incorporates each the search outcomes and the search enter screens, and orchestrates a transition between the 2 states utilizing crucial UIView animation blocks. Whereas this method is straightforward to construct, it has the draw back of tightly coupling these two screens, making them far much less maintainable and transportable.

The opposite method is to implement every display screen as a separate view controller, and create a bespoke UIViewControllerAnimatedTransitioning implementation that extracts related views from every view hierarchy after which animates them. That is usually extra difficult to implement, however has the important thing advantage of letting every particular person display screen be constructed as a separate UIViewController such as you would for every other function.

Previously, we’ve constructed transitions with each of those approaches, and located that they each usually require a whole lot of traces of fragile, crucial code. This meant customized transitions had been time consuming to construct and troublesome to take care of, in order that they had been usually not included as a part of a staff’s major function improvement circulation.

A standard pattern has been to maneuver away from this kind of crucial system design and in the direction of declarative patterns. We use declarative programs extensively at Airbnb–we leverage frameworks like Epoxy and SwiftUI to declaratively outline the structure of every display screen. Screens are mixed into options and flows utilizing declarative navigation APIs. We’ve discovered these declarative programs unlock substantial productiveness features, by letting engineers give attention to defining how the app ought to behave and abstracting away the advanced underlying implementation particulars.

To simplify and speed-up the method of including transitions to our app, we’ve created a new framework for constructing transitions declaratively, slightly than imperatively as we did earlier than. We’ve discovered that this new method has made it a lot easier to construct customized transitions, and in consequence much more engineers have been capable of simply add wealthy and pleasant transitions to their screens even on tight timelines.

To carry out a transition with this framework, you merely present the preliminary state and last state (or within the case of a display screen transition, the supply and vacation spot view controllers) together with a declarative transition definition of how every particular person factor on the display screen must be animated. The framework’s generic UIViewControllerAnimatedTransitioning implementation handles every part else mechanically.

This new framework has turn into instrumental to how we construct options. It powers most of the new options included in Airbnb’s 2022 Summer Release and 2022 Winter Release, serving to make them straightforward and pleasant to make use of:

Instance transitions in Airbnb’s iOS app from new options launched in 2022

As an introduction, let’s begin with a instance. Right here’s a easy “search” interplay the place a date picker in a backside sheet slides up over a web page of content material:

An instance transition for a easy “search” function

On this instance, there are two separate view controllers: the search outcomes display screen and the date picker display screen. Every of the elements we wish to animate are tagged with an identifier to determine their identification.

Diagram exhibiting the search outcomes display screen and date picker display screen annotated with element identifiers

These identifiers allow us to refer to every element semantically by title, slightly than by immediately referencing the UIView occasion. For instance, the Discover.searchNavigationBarPill element on every display screen is a separate UIView occasion, however since they’re tagged with the identical identifier the 2 view situations are thought-about separate “states” of the identical element.

Now that we’ve recognized the elements that we wish to animate, we will outline how they need to animate. For this transition we would like:

  1. The background to fade in
  2. The underside sheet to slip up from the underside of the display screen
  3. The navigation bar to animate between the primary state and second state (a “shared factor” animation).

We will specific this as a easy transition definition:

let transitionDefinition: TransitionDefinition = [
BottomSheet.backgroundView: .crossfade,
BottomSheet.foregroundView: .edgeTranslation(.bottom),
Explore.searchNavigationBarPill: .sharedElement,
]

Revisiting the instance above for increasing and collapsing the search enter display screen, we would like:

  1. The background to blur
  2. The highest bar and backside bars to slip in
  3. The house display screen search bar to transition into the “the place are you going?” card
  4. The opposite two search playing cards to fade in whereas staying anchored relative to the “the place are you going? card

Right here’s how that animation is outlined utilizing the declarative transition definition syntax:

let transitionDefinition: TransitionDefinition = [
SearchInput.background: .blur,
SearchInput.topBar: .translateY(-40),
SearchInput.bottomBar: .edgeTranslation(.bottom),

SearchInput.whereCard: .sharedElement,
SearchInput.whereCardContent: .crossfade,
SearchInput.searchInput: .crossfade,

SearchInput.whenCard: .anchorTranslation(relativeTo: SearchInput.whereCard),
SearchInput.whoCard: .anchorTranslation(relativeTo: SearchInput.whereCard),
]

This declarative transition definition API is highly effective and versatile, but it surely solely tells half the story. To truly carry out the animation, our framework supplies a generic UIViewControllerAnimatedTransitioning implementation that takes the transition definition and orchestrates the transition animation. To discover how this implementation works, we’ll return to the easy “search” interplay.

First, the framework traverses the view hierarchy of each the supply and vacation spot screens to extract the UIView for every of the identifiers being animated. This determines whether or not or not a given identifier is current on every display screen, and types an identifier hierarchy (very similar to the view hierarchy of a display screen).

The “identifier hierarchy” of the supply and vacation spot screens

The identifier hierarchies of the supply and vacation spot are diffed to find out whether or not a person element was added, eliminated, or current in each. If the view was added or eliminated, the framework will use the animation specified within the transition definition. If the view was current in each states, the framework as a substitute performs a “shared factor animation” the place the element animates from its preliminary place to its last place whereas its content material is up to date. These shared components are animated recursively–every element can present its personal identifier hierarchy of kid components, which is diffed and animated as effectively.

The ultimate identifier hierarchy after diffing the supply and vacation spot screens

To truly carry out these animations, we want a single view hierarchy that matches the construction of our identifier hierarchy. We will’t simply mix the supply and vacation spot screens right into a single view hierarchy by layering them on prime of one another, as a result of the ordering can be incorrect. On this case, if we simply positioned the vacation spot display screen over the supply display screen then the supply Discover.searchNavigationBarPill view can be under the vacation spot BottomSheet.backgroundView factor, which doesn’t match the identifier hierarchy.

As an alternative, we’ve to create a separate view hierarchy that matches the construction of the identifier hierarchy. This requires making copies of the elements being animated and including them to the UIKit transition container. Most UIViews aren’t trivially copyable, so copies are usually made by “snapshotting” the view (rendering it as a picture). We briefly cover the “authentic view” whereas the animation is taking part in, so solely the snapshot is seen.

As soon as the framework has arrange the transition container’s view hierarchy and decided the particular animation to make use of for every element, the animations simply need to be utilized and performed. That is the place the underlying crucial UIView animations are carried out.

Like with Epoxy and different declarative programs, abstracting away the underlying complexity and offering a easy declarative interface makes it potential for engineers to give attention to the what slightly than the how. The declarative transition definition for these animations are just a few traces of code, which is by itself a large enchancment over any possible crucial implementation. And since our declarative feature-building APIs have first-class assist for UIKit UIViewControllerAnimatedTransitioning implementations, these declarative transitions will be built-in into current options with out making any structure adjustments. This considerably accelerates function improvement, making it simpler than ever to create extremely polished transitions, whereas additionally enabling long-term flexibility and maintainability.

Now we have a packed roadmap forward. One space of energetic work is bettering interoperability with SwiftUI. This lets us seamlessly transition between UIKit and SwiftUI-based screens, which unlocks incremental adoption of SwiftUI in our app with out having to sacrifice movement. We’re additionally exploring making related frameworks out there on internet and Android. Our long-term purpose right here is to make it as straightforward as potential to translate our designer’s nice concepts into precise delivery merchandise, on all platforms.

All for working at Airbnb? Take a look at these open roles:

Staff Software Engineer, Wishlists

Staff Software Engineer, Guests & Hosts

Staff Android Software Engineer, Guest

Many because of Eric Horacek and Matthew Cheok for his or her main contributions to Airbnb’s movement structure and our declarative transition framework.