Loading video...

Video Failed to Load

Go Home

Custom view controller transition I built at work this week. A few interesting engineering challenges… 1) Presenting the half sheet during the custom transition. 2) Animating the frame/transform of an MKMapView! 3) Ensuring continuity of the activity indicator before/after the transition begins/ends. Details below 👇🏽

50,368 views • 1 year ago •via X (Twitter)

11 Comments

Seb Vidal's profile picture
Seb Vidal1 year ago

1) UIKit has an interesting limitation which is that a presented view controller cannot present another view controller itself until its presentation animation is complete. The work around here was to create a UIView subclass with a single subview of type UIWindow. UIWindow is, itself, just a UIView subclass - so it can be treated like any other UIView. From here, you can set the window’s rootViewController and tell it to present any view controller you like, without animation. A few considerations to make: a) You’ll need to override the view hosting the window’s hitTest(_:with:) method to ignore all touches outside the presented sheet. This way, the map view below can still be interacted with. b) You’ll need to manually set the window’s traitCollection and safeAreaInsets as, unlike other UIView subclasses, UIWindow does not inherit these properties from its superview. c) If you’re presenting UIMenus from this additional window, you’ll need to dismiss them manually when a touch is registered outside the bounds of the menu. You can do this in the overridden hitTest(_:with:) method.

Seb Vidal's profile picture
Seb Vidal1 year ago

2) Animating the MKMapView was particularly tricky. For some reason, annotations and overlays would end up in the wrong position, and they’d jump around when the transition completed. The solution was to not animate the map view at all. Instead, I used a _UIPortalView during the transition. This view is created using the initWithSourceView: initialiser and composites the supplied sourceView and all of its subviews into a single CALayer. Then, I animated the portal view’s frame and transform, keeping the original map view unaltered - works a charm!

Seb Vidal's profile picture
Seb Vidal1 year ago

3) Ensuring continuity between the activity indicator at the start of the transition, during the transition, and at the end of the transition is key to making the illusion of a custom view controller transition work. If the progress of spinner were to jump around, it would break the illusion. The fix? Simple… Rather than starting the animation of the spinner based on when it was added to the view hierarchy, use a CADisplayLink to base the rotational transform off 1 radian divided by the millisecond on the device’s clock. Here’s UIView.animate versus CADisplayLink…

Julien Sagot's profile picture
Julien Sagot1 year ago

Looking good! The only thing that bothers me a bit is the top gradient blur that should (IMHO) progressively fade in once the transition is almost complete instead of being visible immediately. But that’s barely noticeable at normal speed. Great work 👏

Seb Vidal's profile picture
Seb Vidal1 year ago

That’s not a bad idea actually… Will resist the urge to do this until Monday though 😉

Fran's profile picture
Fran1 year ago

King of details! It looks so smooth!

Seb Vidal's profile picture
Seb Vidal1 year ago

Thanks Fran 🙏🏽

Eslam's profile picture
Eslam1 year ago

amazing! disappointed though that there aren’t any private APIs here 😔

Seb Vidal's profile picture
Seb Vidal1 year ago

Haha thanks Eslam! Did you read the thread below? Hint hint… 👀

백수 집돌이's profile picture
백수 집돌이1 year ago

so beautiful transition 🤩

Seb Vidal's profile picture
Seb Vidal1 year ago

Thank you friend 🙏🏽

Related Videos