May 18, 2024
Anne Lu
The Airbnb Tech Blog

How Airbnb enabled hosts and company 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 offer Hosts a strategy to introduce themselves, and begin constructing a extra private reference to their company. To that finish, we created the Host Passport, which seems within the backside nook of every Non-public Room itemizing end result with a photograph of the Host on the quilt. Visitors can faucet it to totally open the Host Passport and be taught extra concerning the Host and get a way for the actual stay individual they’d be staying with.

The Passport animation

The Host Passport affords Hosts a strategy to introduce themselves and set visitor expectations, and permits company to rapidly begin discovering who they could possibly 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 net, Android, and iOS apps, this text focuses particularly on the iOS implementation.

Whereas we’ve nearly fully converted to SwiftUI in the case of 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 permits the event of clean, polished animations. Mixed with our in-house declarative transition framework, we have been beginning with a stable basis that we might leverage to create complicated 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 moderately coordinating many for a cohesive impact that’s not solely useful, 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 heart. Rotation animations rotate round this anchor level, so by default, views rotate round their midpoints, which provides a card rotating impact moderately 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 might accomplish the web page turning impact by shifting it to the view’s main aspect, however that method had the potential to disrupt different facets of the animation — it’s because the anchor level is used not solely as the premise for rotation, however for different transforms, resembling scaling and translation. Altering the anchor level for three-dimensional rotation has a knock-on impact on these different transforms, inflicting surprising negative effects we might then need to work round.

With this in thoughts, we used another method: as a substitute of immediately 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 heart level for the precise rotation.

With this, we’re in a position to animate our e-book web page rotation with out introducing problems to the opposite transforms. See the instance under, the place there’s a border added across the total 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 learn how to compose the view to appear to be a e-book. We ended up undertaking that impact through the use of a compound view. At a primary stage, the booklet consists of a entrance web page and two inside pages. That meant we would have liked three separate views:

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

By stitching them collectively, we create the Passport booklet.

To create the impression of a web page flip, we would have liked to make use of one other trick; whereas actual life pages have a entrance and a again, the identical just isn’t true of a view. Subsequently, to be able to make it look like a web page turning, we timed it in order that through 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.

As a way to accomplish the subsequent step within the animation we would have liked 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 component transition, the place a view animates seamlessly between two separate screens, in just some traces 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 hooked up 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 closing 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 through the animation. This permits us to play the animation of the view shifting from one place to a different in a performant means whereas protecting the view hierarchy intact.

In our case, nevertheless, a static snapshot didn’t have the performance we would have liked, which was the flexibility to play the web page flip animation alongside the shared component transition. Subsequently, we created a customized snapshot that we used instead of the default static snapshot. This practice snapshot was a duplicate of the view that did have animation capabilities, that we then triggered to play alongside the animated transition in order that they’d be completely in sync. Enter UIViewPropertyAnimator: a category that permits us to outline animation blocks and dynamically management their playback. It supplies the pliability to begin, cease, or modify animations in real-time.

It neatly encapsulated our animations inside a single object, which might 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’d like much more specificity than that; our design requires these to begin and cease at totally different factors alongside the animation period. For that, we time particular occasions to relative factors throughout the timing curve by way of keyframes. To broaden on our earlier instance, right here is our animator with keyframes set.

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

// Allow keyframe animations, inheriting the period of the
// dad or mum 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, we now 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