Animations: Bringing the Host Passport to Life on iOS | by Anne Lu | The Airbnb Tech Weblog | Might, 2024

Anne Lu
The Airbnb Tech Blog

How Airbnb enabled hosts and friends to attach and introduce themselves via the Host Passport.

By: Anne Lu

In Might 2023 we launched the Host Passport as a part of our Summer Release. We wished to provide Hosts a solution to introduce themselves, and begin constructing a extra private reference to their friends. To that finish, we created the Host Passport, which seems within the backside nook of every Non-public Room itemizing outcome with a photograph of the Host on the quilt. Visitors can faucet it to totally open the Host Passport and be taught extra in regards to the Host and get a way for the actual stay individual they might be staying with.

The Passport animation

The Host Passport provides Hosts a solution to introduce themselves and set visitor expectations, and permits friends to shortly begin discovering who they might be sharing an area with.

Delivering this animation with excessive pixel accuracy, fluidity, excessive efficiency, and a spark of enjoyment led us to come across and resolve many novel technical points distinctive to every shopper platform that we help. Whereas the Host Passport seems within the internet, Android, and iOS apps, this text focuses particularly on the iOS implementation.

Whereas we’ve virtually completely converted to SwiftUI relating to constructing new parts and screens in our app, we opted to make use of UIKit for the passport animation. We did this for a few causes. Firstly, on the time of this writing, SwiftUI doesn’t have APIs supporting customized transitions and navigation patterns, so our display navigation and transition layer stays in UIKit. And secondly, whereas keyframe timing was launched for SwiftUI animations with iOS 17, our model help prolonged again to iOS 15 on the time of launch.

UIKit supplies a ready-to-use framework that allows the event of clean, polished animations. Mixed with our in-house declarative transition framework, we have been beginning with a stable basis that we may leverage to create advanced animations. The work lay in bridging the hole between established patterns and our novel necessities; whereas we have been already skilled in creating pleasant two-dimensional animations, three-dimensional animation was uncharted territory.

The complexity of this animation lies in its many shifting elements. The problem lies not in animating single properties, however fairly coordinating many for a cohesive impact that isn’t solely practical, but in addition pleasant.

The anchor point is a property of a view’s bounds, defaulting to the relative [0.5, 0.5], or actual middle. Rotation animations rotate round this anchor level, so by default, views rotate round their midpoints, which supplies a card rotating impact fairly than a web page flipping one.

A rounded rectangle rotating round a middle anchor level

To realize the specified web page rotation, we confronted a dilemma with the anchor level. Shifting the anchor level to [0, 0.5] within the coordinate house may accomplish the web page turning impact by shifting it to the view’s main facet, however that method had the potential to disrupt different features of the animation — it is because the anchor level is used not solely as the premise for rotation, however for different transforms, akin to scaling and translation. Altering the anchor level for three-dimensional rotation has a knock-on impact on these different transforms, inflicting surprising uncomfortable side effects we’d then must work round.

With this in thoughts, we used an alternate method: as a substitute of straight manipulating the anchor level, we created clear views the place the seen content material occupied solely half of the house. Because the rotation happens, the view seemingly rotates across the left edge, whereas nonetheless leveraging the default middle level for the precise rotation.

With this, we’re capable of animate our e book web page rotation with out introducing issues to the opposite transforms. See the instance under, the place there’s a border added across the complete view, together with the clear half, to indicate its precise dimension.

A rounded rectangle with a pink half and a clear half rotating round a middle anchor level

With the rotation solved, we subsequent had to consider tips on how to compose the view to appear like a e book. We ended up engaging in that impact through the use of a compound view. At a fundamental stage, the booklet consists of a entrance web page and two inside pages. That meant we wanted three separate views:

A view that rotates like a folding web page with View 1 (entrance), View 2 (internal left) and View 3 (internal proper)

By stitching them collectively, we create the Passport booklet.

To create the impression of a web page flip, we wanted to make use of one other trick; whereas actual life pages have a entrance and a again, the identical is just not true of a view. Due to this fact, so as to make it look like a web page turning, we timed it in order that throughout the web page flip, the entrance view is swapped for the again view on the actual level when the web page is totally orthogonal to the viewer’s perspective. This creates the phantasm of a entrance and a again. Et voila!

A rotating rounded rectangle that modifications from blue to pink when it’s perpendicular to the display

At this level, we had a passport booklet with the flexibility to flip open in three dimensions.

With the intention to accomplish the subsequent step within the animation we wanted to combine our e book animation with our declarative animation framework, which dealt with transitioning the animating passport from the itemizing outcomes view onto the modal view. Our animation framework permits us to carry out a shared ingredient transition, the place a view animates seamlessly between two separate screens, in only a few strains of code.

First, we created a transition definition that describes the kind of animation we wished:

let passportTransition: TransitionDefinition = [
SharedElementIdentifiers.Passport.passport(listingId): .sharedElement
]

Subsequent, we connected these identifiers to the supply view (the passport within the itemizing search outcomes) and the vacation spot (the open passport card within the context sheet.) We set the transition definition on the modal presentation, and from there, the framework created the animation that moved our passport view from its beginning location within the itemizing outcomes to its remaining location within the modal.

Beneath typical circumstances, our framework captures a “snapshot” of the view by rendering it as a static picture. The snapshot is then animated from the preliminary place to the ultimate place, whereas the unique supply and vacation spot views are hidden throughout the animation. This enables us to play the animation of the view shifting from one place to a different in a performant approach whereas holding the view hierarchy intact.

In our case, nonetheless, a static snapshot didn’t have the performance we wanted, which was the flexibility to play the web page flip animation alongside the shared ingredient transition. Due to this fact, we created a customized snapshot that we used rather than the default static snapshot. This tradition snapshot was a replica of the view that did have animation capabilities, that we then triggered to play alongside the animated transition in order that they might be completely in sync. Enter UIViewPropertyAnimator: a category that enables us to outline animation blocks and dynamically management their playback. It supplies the pliability to start out, cease, or modify animations in real-time.

It neatly encapsulated our animations inside a single object, which may then be handed alongside to our animation framework. As our framework dealt with the display to display transition, it triggered the customized animation to play in sync with that transition.

It isn’t solely the place a view strikes that determines realism, but in addition very importantly when. The passport opens within the span of a second, however the easy class belies the complexity beneath.

On a better look, our animation consists of many synchronized particular person animations. The passport grows in dimension, strikes alongside the x and y axis, rotates its pages in 3D house, and shadows transfer to simulate mild and motion. To get issues good, we use a separate timing curve for every property.

However we want much more specificity than that; our design requires these to start out and cease at totally different factors alongside the animation length. For that, we time particular occasions to relative factors inside the timing curve by way of keyframes. To broaden on our earlier instance, right here is our animator with keyframes set.

let animator = UIViewPropertyAnimator(length: 2.0, curve: .easeInOut) 

// Allow keyframe animations, inheriting the length of the
// mum or dad property animator
UIView.animateKeyframes(withDuration: 0, delay: 0)

// Firstly of the animation, translate the view 100 pixels downwards
UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5)
cardView.rework = CGAffineTransform(translationX: 0, y: 100)

// On the midway level, flip the colour to coincide with the turning
// level of our view.
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0)
cardView.backgroundColor = .pink

// Return to unique place
UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5)
cardView.rework = .id


animator.startAnimation()

Subsequent, let’s take a better take a look at spring timings and their distinctive traits. When creating animations, now we have the choice of various kinds of easing features for a naturalistic really feel.

Easing features like linear and cubic are widespread timing curves, as depicted within the graphs under. They provide us the flexibility to specify the velocity of our animation over time.

Linear