Architecture
This library requires to wrap an app with KeyboardProvider
component. It's needed because it stores animated values in context
.
Process overview
Library exposes KeyboardControllerView
with onKeyboardMove
method. This method is fired when keyboard frame is changed. KeyboardProvider
automatically maps these events to Animated.Value
and Reanimated.SharedValue
and stores it in context
.
Under the hood KeyboardControllerView
is a simple View
with one additional onKeyboardMove
callback method, so it inherits all props from plain View
, such as style
, etc.
Thus we have a single source of truth about keyboard position. Since values are stored in context
we can use it in any component where we need them. Moreover, we can consume context
values in class components as well as in hooks.
Design principles
The library was designed to use a context
as a global store for animated values and have a single Provider
across the app. As of now it may be not very obvious, why it was needed to have a single source of data flow, but in future it may significantly simplify the process of the integration new features.
Why custom KeyboardControllerView
is needed?
Initially I had a choice which approach to use in order to send events about keyboard frames: EventEmitters
vs View
with callbacks. I decided to use View
with callbacks because of several reasons:
react-native
core team uses similar approach foronScroll
event fromScrollView
component (also I knew, that it's possible to map events from such callbacks toAnimated.Value
and thus reduce bridge usage);- to track keyboard frames on Android we need to enter to edge-to-edge mode and it changes view paddings. Since it's managed through
View
it's easier to change padding of this view. reanimated
allows to interceptview
events using theirsuseEvent
hook and move the event handling into worklet runtime. Thus sending events viaview
allows to make an integration withreanimated
package and handle events/animate everything directly on the UI thread.