TBA
This library is being re-written to support the new architecture. Please see this is issue for progress š
The initial version of this library (0.x
) was made possible through a generous sponsorship by beatgig from 11/15/2023
to 04/30/2024
at $1,535
/month (totaling ā $9,100
over the course of 6 months)
very special thanks to: junzhengca, brentvatne, expo, EvanBacon, corasan, lauridskern, and ronintechnologies for becoming a monthly sponsor and fobos531 for being a one time sponsor š„ŗ (if you have the means to do so, please considering sponsoring here)
TBA
For bare React Native projects, you must ensure that you have installed and configured the expo
package before continuing.
# 1. install library + dependencies
npm install react-native-ios-utilities
npm install react-native-ios-adaptive-modal
# 2. then run pod install (uses auto-linking)
cd ios && pod install
TBA
TBA
AdaptiveModal
All of the modal presentation and animation is handled by a small library written in swift called: adaptive-modal
. This library uses it under the hood for natively presenting a view controller with custom modal presentation.
adaptive-modal
accepts a config that describes the state, behavior and layout of the modal:
The config defines all the various snapping points (e.g. the position of the modal, and its layout, e.g. height, width, margin, padding, etc).
The config defines the presentation, dismissal, and snapping animations, as well as how the modal should be animated (e.g. the animation duration, easing, etc),
The config defines the associated keyframes to apply for each snap point (e.g. the type and intensity of background + modal content background blur, the background color, corner radius, etc).
Etc.
the modal config is then evaluated, and gets "transformed" into something UIKit
can understand via:
UIViewControllerAnimatedTransitioning
, UIAdaptivePresentationControllerDelegate
, UIViewControllerTransitioningDelegate
UIViewPropertyAnimator
, and CADisplayLink
.ComputableLayout
To define the various snapping points for the modal, a small helper library written in swift called ComputableLayout
is used to configure the size and position of the modal. This library is a very naive layout system/calculator custom built for adaptive-modal
.
This helper library is essentially just a function that turns a config (e.g. the desired horizontal/vertical position) into a CGRect
value (i.e. raw x, y, width and height values); in other words, this library is used to cheaply calculate layout for a given configuration without having to instantiate a view.
The layout config allows us to add placeholder "layout values" that are then substituted to the real values during calculation; some of these values are:
CGRect
/CGSize
of various views, e.g target view, the current window, the device's screen, etc.The layout config also allows for the composition of multiple "layout values" together, or have conditions that get evaluated during calculation.
The layout config is calculated based on a provided target view/rect, i.e. in the case for adaptive-modal
, the target view would be the UITransitionView
where the modal UIViewController
gets attached to.
In summary: ComputableLayout
allows us to compute all the snapping points for a target view's size, this allows for the quick recalculation of all the snapping points whenever there's a layout change for the target view (e.g. when the screen rotates, the window resizes, the appearance of a keyboard, etc).
DGSwiftUtilities
and react-native-ios-utilities
are just helper libraries.
DGSwiftUtilities
contains shared code + helpers for the swift libraries.react-native-ios-utilities
contains shared code + helpers for the react-native
libraries on iOS.The layout config you provide defines the snapping point.
To be more specific, the layout config is used to calculate the position of the modal. The computed position of the modal in the screen defines the snapping point.
A snapping point is a unique position in the screen that we want the modal to āsnap toā either viaļæ¼ gesture (e.g. a user dragging the modal), or programmatically (via a function call).
As the modal is being dragged around, it will morph between each snapping point you defined; using the gestureās position to drive the interpolation of the modal.
Each snapping point has a corresponding āpercentageā that is derived based on its position on the screen, in relation to the current modal direction defined in the modal config.
The snap point's computed percentage is then used in the interpolation function to drive the modal animation as the user drags the modal around.
Due to the quirks described in the previous bullet points, it is recommended that each snapping point be unique (no repeats or duplicates), and their corresponding computed percentage must changeāeither increasing or decreasing consistently in one direction.
CGRect.maxX
(rightmost edge) increases continuously.CGRect.minY
(topmost edge) increases continuously.CGRect.minX
(leftmost edge) decreases continuously.CGRect.minX
(leftmost edge) decreases continuously.adaptive-modal
as a very limited/naive "range interpolator" (e.g. something like lerp
). Because of this, the values in the "range" (in this case, the snapping points) must be continuous in one direction only, otherwise the resulting interpolated value (e.g. the position of the modal) will be invalid.TBA
TBA
TBA
@GoDominic
dominicgo@dominicgo.dev