How to present view controller modally with custom transition animation v2.0
Good day. It has been about a year since my first publication.
How to present view controller modally with custom transition animation
Fully programmatically created project with custom transitioning animation.
Today, this publication, among the rest, is the most read, which, of course, suggests an idea of supplementing and expanding the material based on the development experience gained. In this article, you, as before, will find a solution that allows you to modally present a screen with custom animation and, additionally, swipe the presented view using the physics of real objects — UIKit Dynamics, as well as implement the effect of resistance when swiping outside the limits — Rubber Band Effect. In the example, the SnapKit library was used to speed up the layout development process (simplify the creation of constraints).
Custom animation presentation
For learning purposes, an usual UIViewController was created with an orange background color and a single "Present" button, by tapping on which a new screen is presented.
At the same time, this UIViewController implements the UIViewControllerTransitioningDelegate protocol. The implementation of this protocol allows you to specify a custom class as an animator. The link to the animator must be stored, since ARC will deinit this object otherwise and the application will crush during the presentation.
The animator class, again, is pretty straightforward to implement. For convenience, the presenting and presented UIViewControllers are passed to the initializer, as well as the isPresenting property, which is responsible for what the animator is used for — presenting or dismissing the screen.
The animateTransition(using:) method is also worth noting here. First, a snapshot of the presentation screen is created and added to the containerView of the animation context. If this is not done, then the area under the presented screen will be empty. Above the snapshot, the presented view is already added. Before starting the animation, the presented UIViewController needs to load the view and perform the layout process. This is indicated by lines 44 and 45. The animation itself is implemented in the presented UIViewController, in the slide(direction:) method, so it is enough to call this method in UIView.animate(withDuration:animation:). In the example, the call to this method is refined with additional parameters to add a springy effect and interactivity during animation.
The slide(direction:) method slides the vContent vertically in the direction that is passed as an argument to the method. Those, when presenting, vContent is positioned outside the screen, and is slides up to the desired height. When dismissing, vContent is slides down outside the screen. Also during animation, the alpha of the background changes, this helps the user to focus on the content of the presented screen.
Physics of real objects with translation of the presented screen
Based on data from a verified source (I mean a manufacturer, i.e. Apple)
it becomes obvious that in order to take into account the velocity of vContent it is necessary to use UIKitDynamics objects. There are many examples of using these objects, so it’s just worth briefly describing why a combination of three UIDynamicBehavior was used.
UIAttachmentBehavior.slidingAttachment(with:attachmentAnchor:axisOfTranslation:) — used to disable horizontal translation (set by the axisOfTranslation argument).
UIDynamicItemBehavior(items:) — used to give vContent the acceleration (velocity, which is calculated by the UIPanGestureRecognizer) with which the user performed the translation. The resistance is additionally set so that the animation is not too fast.
And finally, UISnapBehavior(item:snapTo:) is used to snap view to the desired point. When you drag an object, it will tend to the specified point. There is a more subtle way of pinning to a point — using UIAttachmentBehavior(item:attachedTo:) instead of snap. However, this is to complicated, adjust friction, distance, etc.
Together with the UIPanGestureRecognizer, this combination allows you to create a very nice translation animation that takes velocity into account.
Rubber band effect when swiped out of bounds
As you may have noticed, apple system applications implement resistance, which increases when the modal screen is moved out of bounds. Obviously, when calculating the translation, the logarithm is involved in the formula, since the larger the translation, the stronger the resistance.
Having studied a little the textbook of arithmetic of Ancient Egypt and the latest discovery of the Nobel laureate in the field of astrophysics
The Nobel Prize in Physics 2019
The Nobel Prize in Physics 2019 was awarded "for contributions to our understanding of the evolution of the universe…
, managed to derive a formula that calculates the translation with resistance. Of course, a slightly different solution is implemented in the Apple system (the Planck constant is probably used), but even without this coefficient it was possible to recreate a fairly acceptable solution.
Everything is quite simple, the limits are set in before and then, when translating, new coordinates of vContent are calculated.
About a year has passed since the publication of the previous article on this topic and it is very pleasant to share new experience with other developers. Let me wish you a great mood and that’s it.