react-native-keyboard-controller 1.0.0-beta.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -50
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/reactnativekeyboardcontroller/KeyboardAnimationCallback.kt +188 -0
- package/android/src/main/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +28 -24
- package/android/src/main/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt +16 -2
- package/ios/.clang-format +90 -0
- package/ios/KeyboardController.xcodeproj/project.pbxproj +4 -0
- package/ios/KeyboardControllerModule.m +2 -2
- package/ios/KeyboardControllerViewManager.m +1 -1
- package/ios/KeyboardControllerViewManager.swift +13 -64
- package/ios/KeyboardMovementObserver.swift +90 -0
- package/lib/commonjs/animated.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/monkey-patch.js.map +1 -1
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/replicas.js.map +1 -1
- package/lib/module/animated.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/monkey-patch.js.map +1 -1
- package/lib/module/native.js.map +1 -1
- package/lib/module/replicas.js.map +1 -1
- package/lib/typescript/replicas.d.ts +3 -5
- package/package.json +11 -9
- package/android/src/main/java/com/reactnativekeyboardcontroller/TranslateDeferringInsetsAnimationCallback.kt +0 -152
package/README.md
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
Keyboard manager which works in identical way on both iOS and Android.
|
|
4
4
|
|
|
5
|
-
> **Note**: This library is still in development and in `beta` stage. So most likely it has bugs/issues - don't hesitate to report if you find them 🙂.
|
|
6
|
-
|
|
7
5
|
## Demonstration
|
|
8
6
|
|
|
9
7
|
<img src="./gifs/demo.gif?raw=true" width="60%">
|
|
@@ -27,55 +25,9 @@ yarn add react-native-keyboard-controller
|
|
|
27
25
|
# npm install react-native-keyboard-controller --save
|
|
28
26
|
```
|
|
29
27
|
|
|
30
|
-
##
|
|
31
|
-
|
|
32
|
-
For more comprehensive usage you can have a look on [example](https://github.com/kirillzyusko/react-native-keyboard-controller/tree/main/example).
|
|
33
|
-
|
|
34
|
-
Below you can see a short overview of library API:
|
|
35
|
-
|
|
36
|
-
```js
|
|
37
|
-
import {
|
|
38
|
-
KeyboardProvider,
|
|
39
|
-
useKeyboardAnimation,
|
|
40
|
-
} from 'react-native-keyboard-controller';
|
|
28
|
+
## Documentation
|
|
41
29
|
|
|
42
|
-
|
|
43
|
-
<KeyboardProvider>
|
|
44
|
-
<AppContainer />
|
|
45
|
-
</KeyboardProvider>
|
|
46
|
-
|
|
47
|
-
// 2. get animation values where you need them
|
|
48
|
-
const { height, progress } = useKeyboardAnimation();
|
|
49
|
-
|
|
50
|
-
// 3. Animate any elements as you wish :)
|
|
51
|
-
<Animated.View
|
|
52
|
-
style={{
|
|
53
|
-
width: 50,
|
|
54
|
-
height: 50,
|
|
55
|
-
backgroundColor: 'red',
|
|
56
|
-
borderRadius: 25,
|
|
57
|
-
// the element will move up with the keyboard
|
|
58
|
-
transform: [{ translateY: height }],
|
|
59
|
-
}}
|
|
60
|
-
/>
|
|
61
|
-
<Animated.View
|
|
62
|
-
style={{
|
|
63
|
-
width: 50,
|
|
64
|
-
height: 50,
|
|
65
|
-
backgroundColor: 'green',
|
|
66
|
-
borderRadius: 25,
|
|
67
|
-
transform: [
|
|
68
|
-
{
|
|
69
|
-
// or use custom interpolation using `progress`
|
|
70
|
-
translateX: progress.interpolate({
|
|
71
|
-
inputRange: [0, 1],
|
|
72
|
-
outputRange: [0, 100],
|
|
73
|
-
}),
|
|
74
|
-
},
|
|
75
|
-
],
|
|
76
|
-
}}
|
|
77
|
-
/>
|
|
78
|
-
```
|
|
30
|
+
Check out our dedicated documentation page for info about this library, API reference and more: [https://kirillzyusko.github.io/react-native-keyboard-controller/](https://kirillzyusko.github.io/react-native-keyboard-controller/)
|
|
79
31
|
|
|
80
32
|
## Contributing
|
|
81
33
|
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
package com.reactnativekeyboardcontroller
|
|
2
|
+
|
|
3
|
+
import android.animation.ValueAnimator
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.os.Build
|
|
6
|
+
import android.util.Log
|
|
7
|
+
import android.view.View
|
|
8
|
+
import androidx.core.animation.doOnEnd
|
|
9
|
+
import androidx.core.graphics.Insets
|
|
10
|
+
import androidx.core.view.OnApplyWindowInsetsListener
|
|
11
|
+
import androidx.core.view.ViewCompat
|
|
12
|
+
import androidx.core.view.WindowInsetsAnimationCompat
|
|
13
|
+
import androidx.core.view.WindowInsetsCompat
|
|
14
|
+
import com.facebook.react.bridge.Arguments
|
|
15
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
16
|
+
import com.facebook.react.bridge.WritableMap
|
|
17
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
18
|
+
import com.facebook.react.uimanager.UIManagerModule
|
|
19
|
+
import com.facebook.react.uimanager.events.Event
|
|
20
|
+
import com.facebook.react.views.view.ReactViewGroup
|
|
21
|
+
import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
|
|
22
|
+
|
|
23
|
+
fun toDp(px: Float, context: Context?): Int {
|
|
24
|
+
if (context == null) {
|
|
25
|
+
return 0
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (px / context.resources.displayMetrics.density).toInt()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class KeyboardAnimationCallback(
|
|
32
|
+
val view: ReactViewGroup,
|
|
33
|
+
val persistentInsetTypes: Int,
|
|
34
|
+
val deferredInsetTypes: Int,
|
|
35
|
+
dispatchMode: Int = DISPATCH_MODE_STOP,
|
|
36
|
+
val context: ReactApplicationContext?,
|
|
37
|
+
val onApplyWindowInsetsListener: OnApplyWindowInsetsListener
|
|
38
|
+
) : WindowInsetsAnimationCompat.Callback(dispatchMode), OnApplyWindowInsetsListener {
|
|
39
|
+
private val TAG = KeyboardAnimationCallback::class.qualifiedName
|
|
40
|
+
private var persistentKeyboardHeight = 0
|
|
41
|
+
private var isKeyboardVisible = false
|
|
42
|
+
private var isTransitioning = false
|
|
43
|
+
|
|
44
|
+
init {
|
|
45
|
+
require(persistentInsetTypes and deferredInsetTypes == 0) {
|
|
46
|
+
"persistentInsetTypes and deferredInsetTypes can not contain any of " +
|
|
47
|
+
" same WindowInsetsCompat.Type values"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* When keyboard changes its size we have different behavior per APIs.
|
|
53
|
+
* On 21<=API<30 - WindowInsetsAnimationCompat dispatches onStart/onProgress/onEnd events.
|
|
54
|
+
* On API>=30 - WindowInsetsAnimationCompat doesn't dispatch anything. As a result behavior
|
|
55
|
+
* between different Android versions is not consistent. On old Android versions we have a
|
|
56
|
+
* reaction, on newer versions - not. In my understanding it's a bug in core library and the
|
|
57
|
+
* behavior should be consistent across all versions of platform. To level the difference we
|
|
58
|
+
* have to implement `onApplyWindowInsets` listener and simulate onStart/onProgress/onEnd
|
|
59
|
+
* events when keyboard changes its size.
|
|
60
|
+
* In the method below we fully recreate the logic that is implemented on old android versions:
|
|
61
|
+
* - we dispatch `keyboardWillShow` (onStart);
|
|
62
|
+
* - we dispatch change height/progress as animated values (onProgress);
|
|
63
|
+
* - we dispatch `keyboardDidShow` (onEnd).
|
|
64
|
+
*/
|
|
65
|
+
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
|
|
66
|
+
// when keyboard appears values will be (false && true)
|
|
67
|
+
// when keyboard disappears values will be (true && false)
|
|
68
|
+
// `!isTransitioning` check is needed to avoid calls of `onApplyWindowInsets` during keyboard animation
|
|
69
|
+
// having such check allows us not to dispatch unnecessary incorrect events
|
|
70
|
+
// the condition will be executed only when keyboard is opened and changes its size
|
|
71
|
+
// (for example it happens when user changes keyboard type from 'text' to 'emoji' input
|
|
72
|
+
if (isKeyboardVisible && isKeyboardVisible() && !isTransitioning && Build.VERSION.SDK_INT >= 30) {
|
|
73
|
+
val keyboardHeight = getCurrentKeyboardHeight()
|
|
74
|
+
|
|
75
|
+
this.emitEvent("KeyboardController::keyboardWillShow", getEventParams(keyboardHeight))
|
|
76
|
+
|
|
77
|
+
val animation = ValueAnimator.ofInt(-this.persistentKeyboardHeight, -keyboardHeight)
|
|
78
|
+
animation.addUpdateListener { animator ->
|
|
79
|
+
val toValue = animator.animatedValue as Int
|
|
80
|
+
this.sendEventToJS(KeyboardTransitionEvent(view.id, toValue, -toValue.toDouble() / keyboardHeight))
|
|
81
|
+
}
|
|
82
|
+
animation.doOnEnd {
|
|
83
|
+
this.emitEvent("KeyboardController::keyboardDidShow", getEventParams(keyboardHeight))
|
|
84
|
+
}
|
|
85
|
+
animation.setDuration(250).startDelay = 0
|
|
86
|
+
animation.start()
|
|
87
|
+
|
|
88
|
+
this.persistentKeyboardHeight = keyboardHeight
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return onApplyWindowInsetsListener.onApplyWindowInsets(v, insets)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
override fun onStart(
|
|
95
|
+
animation: WindowInsetsAnimationCompat,
|
|
96
|
+
bounds: WindowInsetsAnimationCompat.BoundsCompat
|
|
97
|
+
): WindowInsetsAnimationCompat.BoundsCompat {
|
|
98
|
+
isTransitioning = true
|
|
99
|
+
isKeyboardVisible = isKeyboardVisible()
|
|
100
|
+
val keyboardHeight = getCurrentKeyboardHeight()
|
|
101
|
+
|
|
102
|
+
if (isKeyboardVisible) {
|
|
103
|
+
// do not update it on hide, since back progress will be invalid
|
|
104
|
+
this.persistentKeyboardHeight = keyboardHeight
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this.emitEvent("KeyboardController::" + if (!isKeyboardVisible) "keyboardWillHide" else "keyboardWillShow", getEventParams(keyboardHeight))
|
|
108
|
+
|
|
109
|
+
Log.i(TAG, "HEIGHT:: $keyboardHeight")
|
|
110
|
+
|
|
111
|
+
return super.onStart(animation, bounds)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
override fun onProgress(
|
|
115
|
+
insets: WindowInsetsCompat,
|
|
116
|
+
runningAnimations: List<WindowInsetsAnimationCompat>
|
|
117
|
+
): WindowInsetsCompat {
|
|
118
|
+
// onProgress() is called when any of the running animations progress...
|
|
119
|
+
|
|
120
|
+
// First we get the insets which are potentially deferred
|
|
121
|
+
val typesInset = insets.getInsets(deferredInsetTypes)
|
|
122
|
+
// Then we get the persistent inset types which are applied as padding during layout
|
|
123
|
+
val otherInset = insets.getInsets(persistentInsetTypes)
|
|
124
|
+
|
|
125
|
+
// Now that we subtract the two insets, to calculate the difference. We also coerce
|
|
126
|
+
// the insets to be >= 0, to make sure we don't use negative insets.
|
|
127
|
+
val diff = Insets.subtract(typesInset, otherInset).let {
|
|
128
|
+
Insets.max(it, Insets.NONE)
|
|
129
|
+
}
|
|
130
|
+
val diffY = (diff.top - diff.bottom).toFloat()
|
|
131
|
+
val height = toDp(diffY, context)
|
|
132
|
+
|
|
133
|
+
var progress = 0.0
|
|
134
|
+
try {
|
|
135
|
+
progress = Math.abs((height.toDouble() / persistentKeyboardHeight))
|
|
136
|
+
} catch (e: ArithmeticException) {
|
|
137
|
+
// do nothing, send progress as 0
|
|
138
|
+
}
|
|
139
|
+
Log.i(TAG, "DiffY: $diffY $height $progress")
|
|
140
|
+
|
|
141
|
+
this.sendEventToJS(KeyboardTransitionEvent(view.id, height, progress))
|
|
142
|
+
|
|
143
|
+
return insets
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
override fun onEnd(animation: WindowInsetsAnimationCompat) {
|
|
147
|
+
super.onEnd(animation)
|
|
148
|
+
|
|
149
|
+
isTransitioning = false
|
|
150
|
+
this.persistentKeyboardHeight = getCurrentKeyboardHeight()
|
|
151
|
+
this.emitEvent("KeyboardController::" + if (!isKeyboardVisible) "keyboardDidHide" else "keyboardDidShow", getEventParams(this.persistentKeyboardHeight))
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private fun isKeyboardVisible(): Boolean {
|
|
155
|
+
val insets = ViewCompat.getRootWindowInsets(view)
|
|
156
|
+
|
|
157
|
+
return insets?.isVisible(WindowInsetsCompat.Type.ime()) ?: false
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private fun getCurrentKeyboardHeight(): Int {
|
|
161
|
+
val insets = ViewCompat.getRootWindowInsets(view)
|
|
162
|
+
val keyboardHeight = insets?.getInsets(WindowInsetsCompat.Type.ime())?.bottom ?: 0
|
|
163
|
+
val navigationBar = insets?.getInsets(WindowInsetsCompat.Type.navigationBars())?.bottom ?: 0
|
|
164
|
+
|
|
165
|
+
// on hide it will be negative value, so we are using max function
|
|
166
|
+
return Math.max(toDp((keyboardHeight - navigationBar).toFloat(), context), 0)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private fun sendEventToJS(event: Event<*>) {
|
|
170
|
+
context
|
|
171
|
+
?.getNativeModule(UIManagerModule::class.java)
|
|
172
|
+
?.eventDispatcher
|
|
173
|
+
?.dispatchEvent(event)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private fun emitEvent(event: String, params: WritableMap) {
|
|
177
|
+
context?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)?.emit(event, params)
|
|
178
|
+
|
|
179
|
+
Log.i(TAG, event)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private fun getEventParams(height: Int): WritableMap {
|
|
183
|
+
val params: WritableMap = Arguments.createMap()
|
|
184
|
+
params.putInt("height", height)
|
|
185
|
+
|
|
186
|
+
return params
|
|
187
|
+
}
|
|
188
|
+
}
|
package/android/src/main/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.reactnativekeyboardcontroller
|
|
2
2
|
|
|
3
|
+
import android.util.Log
|
|
3
4
|
import androidx.appcompat.widget.FitWindowsLinearLayout
|
|
4
5
|
import androidx.core.view.ViewCompat
|
|
5
6
|
import androidx.core.view.WindowInsetsAnimationCompat
|
|
@@ -13,6 +14,7 @@ import com.facebook.react.views.view.ReactViewManager
|
|
|
13
14
|
import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
|
|
14
15
|
|
|
15
16
|
class KeyboardControllerViewManager(reactContext: ReactApplicationContext) : ReactViewManager() {
|
|
17
|
+
private val TAG = KeyboardControllerViewManager::class.qualifiedName
|
|
16
18
|
private var mReactContext = reactContext
|
|
17
19
|
private var isStatusBarTranslucent = false
|
|
18
20
|
|
|
@@ -20,34 +22,36 @@ class KeyboardControllerViewManager(reactContext: ReactApplicationContext) : Rea
|
|
|
20
22
|
|
|
21
23
|
override fun createViewInstance(reactContext: ThemedReactContext): ReactViewGroup {
|
|
22
24
|
val view = EdgeToEdgeReactViewGroup(reactContext)
|
|
23
|
-
val
|
|
24
|
-
val decorView = window.decorView
|
|
25
|
+
val activity = mReactContext.currentActivity
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
R.id.action_bar_root
|
|
30
|
-
)
|
|
31
|
-
content?.setPadding(
|
|
32
|
-
0, if (this.isStatusBarTranslucent) 0 else insets?.getInsets(WindowInsetsCompat.Type.systemBars())?.top ?: 0, 0,
|
|
33
|
-
insets?.getInsets(WindowInsetsCompat.Type.navigationBars())?.bottom ?: 0
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
insets
|
|
27
|
+
if (activity == null) {
|
|
28
|
+
Log.w(TAG, "Can not setup keyboard animation listener, since `currentActivity` is null")
|
|
29
|
+
return view
|
|
37
30
|
}
|
|
38
31
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
32
|
+
val callback = KeyboardAnimationCallback(
|
|
33
|
+
view = view,
|
|
34
|
+
persistentInsetTypes = WindowInsetsCompat.Type.systemBars(),
|
|
35
|
+
deferredInsetTypes = WindowInsetsCompat.Type.ime(),
|
|
36
|
+
// We explicitly allow dispatch to continue down to binding.messageHolder's
|
|
37
|
+
// child views, so that step 2.5 below receives the call
|
|
38
|
+
dispatchMode = WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE,
|
|
39
|
+
context = mReactContext,
|
|
40
|
+
onApplyWindowInsetsListener = { v, insets ->
|
|
41
|
+
val content =
|
|
42
|
+
mReactContext.currentActivity?.window?.decorView?.rootView?.findViewById<FitWindowsLinearLayout>(
|
|
43
|
+
R.id.action_bar_root
|
|
44
|
+
)
|
|
45
|
+
content?.setPadding(
|
|
46
|
+
0, if (this.isStatusBarTranslucent) 0 else insets?.getInsets(WindowInsetsCompat.Type.systemBars())?.top ?: 0, 0,
|
|
47
|
+
insets?.getInsets(WindowInsetsCompat.Type.navigationBars())?.bottom ?: 0
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
insets
|
|
51
|
+
}
|
|
50
52
|
)
|
|
53
|
+
ViewCompat.setWindowInsetsAnimationCallback(view, callback)
|
|
54
|
+
ViewCompat.setOnApplyWindowInsetsListener(view, callback)
|
|
51
55
|
|
|
52
56
|
return view
|
|
53
57
|
}
|
package/android/src/main/java/com/reactnativekeyboardcontroller/StatusBarManagerCompatModule.kt
CHANGED
|
@@ -3,6 +3,7 @@ package com.reactnativekeyboardcontroller
|
|
|
3
3
|
import android.animation.ArgbEvaluator
|
|
4
4
|
import android.animation.ValueAnimator
|
|
5
5
|
import android.os.Build
|
|
6
|
+
import android.util.Log
|
|
6
7
|
import androidx.annotation.RequiresApi
|
|
7
8
|
import androidx.core.view.WindowInsetsCompat
|
|
8
9
|
import androidx.core.view.WindowInsetsControllerCompat
|
|
@@ -12,6 +13,7 @@ import com.facebook.react.bridge.ReactMethod
|
|
|
12
13
|
import com.facebook.react.bridge.UiThreadUtil
|
|
13
14
|
|
|
14
15
|
class StatusBarManagerCompatModule(private val mReactContext: ReactApplicationContext) : ReactContextBaseJavaModule(mReactContext) {
|
|
16
|
+
private val TAG = StatusBarManagerCompatModule::class.qualifiedName
|
|
15
17
|
private var controller: WindowInsetsControllerCompat? = null
|
|
16
18
|
|
|
17
19
|
override fun getName(): String = "StatusBarManagerCompat"
|
|
@@ -30,8 +32,14 @@ class StatusBarManagerCompatModule(private val mReactContext: ReactApplicationCo
|
|
|
30
32
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
|
31
33
|
@ReactMethod
|
|
32
34
|
private fun setColor(color: Int, animated: Boolean) {
|
|
35
|
+
val activity = mReactContext.currentActivity
|
|
36
|
+
if (activity == null) {
|
|
37
|
+
Log.w(TAG, "StatusBarManagerCompatModule: Ignored status bar change, current activity is null.")
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
33
41
|
UiThreadUtil.runOnUiThread {
|
|
34
|
-
val window =
|
|
42
|
+
val window = activity.window
|
|
35
43
|
|
|
36
44
|
if (animated) {
|
|
37
45
|
val curColor: Int = window.statusBarColor
|
|
@@ -71,7 +79,13 @@ class StatusBarManagerCompatModule(private val mReactContext: ReactApplicationCo
|
|
|
71
79
|
|
|
72
80
|
private fun getController(): WindowInsetsControllerCompat? {
|
|
73
81
|
if (this.controller == null) {
|
|
74
|
-
val
|
|
82
|
+
val activity = mReactContext.currentActivity
|
|
83
|
+
if (activity == null) {
|
|
84
|
+
Log.w(TAG, "StatusBarManagerCompatModule: can not get `WindowInsetsControllerCompat` because current activity is null.")
|
|
85
|
+
return this.controller
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
val window = activity.window
|
|
75
89
|
|
|
76
90
|
this.controller = WindowInsetsControllerCompat(window, window.decorView)
|
|
77
91
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
AccessModifierOffset: -1
|
|
3
|
+
AlignAfterOpenBracket: AlwaysBreak
|
|
4
|
+
AlignConsecutiveAssignments: false
|
|
5
|
+
AlignConsecutiveDeclarations: false
|
|
6
|
+
AlignEscapedNewlinesLeft: true
|
|
7
|
+
AlignOperands: false
|
|
8
|
+
AlignTrailingComments: false
|
|
9
|
+
AllowAllParametersOfDeclarationOnNextLine: false
|
|
10
|
+
AllowShortBlocksOnASingleLine: false
|
|
11
|
+
AllowShortCaseLabelsOnASingleLine: false
|
|
12
|
+
AllowShortFunctionsOnASingleLine: Empty
|
|
13
|
+
AllowShortIfStatementsOnASingleLine: false
|
|
14
|
+
AllowShortLoopsOnASingleLine: false
|
|
15
|
+
AlwaysBreakAfterReturnType: None
|
|
16
|
+
AlwaysBreakBeforeMultilineStrings: true
|
|
17
|
+
AlwaysBreakTemplateDeclarations: true
|
|
18
|
+
BinPackArguments: false
|
|
19
|
+
BinPackParameters: false
|
|
20
|
+
BraceWrapping:
|
|
21
|
+
AfterClass: false
|
|
22
|
+
AfterControlStatement: false
|
|
23
|
+
AfterEnum: false
|
|
24
|
+
AfterFunction: false
|
|
25
|
+
AfterNamespace: false
|
|
26
|
+
AfterObjCDeclaration: false
|
|
27
|
+
AfterStruct: false
|
|
28
|
+
AfterUnion: false
|
|
29
|
+
BeforeCatch: false
|
|
30
|
+
BeforeElse: false
|
|
31
|
+
IndentBraces: false
|
|
32
|
+
BreakBeforeBinaryOperators: None
|
|
33
|
+
BreakBeforeBraces: Attach
|
|
34
|
+
BreakBeforeTernaryOperators: true
|
|
35
|
+
BreakConstructorInitializersBeforeComma: false
|
|
36
|
+
BreakAfterJavaFieldAnnotations: false
|
|
37
|
+
BreakStringLiterals: false
|
|
38
|
+
ColumnLimit: 80
|
|
39
|
+
CommentPragmas: '^ IWYU pragma:'
|
|
40
|
+
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|
41
|
+
ConstructorInitializerIndentWidth: 4
|
|
42
|
+
ContinuationIndentWidth: 4
|
|
43
|
+
Cpp11BracedListStyle: true
|
|
44
|
+
DerivePointerAlignment: false
|
|
45
|
+
DisableFormat: false
|
|
46
|
+
ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, ]
|
|
47
|
+
IncludeCategories:
|
|
48
|
+
- Regex: '^<.*\.h(pp)?>'
|
|
49
|
+
Priority: 1
|
|
50
|
+
- Regex: '^<.*'
|
|
51
|
+
Priority: 2
|
|
52
|
+
- Regex: '.*'
|
|
53
|
+
Priority: 3
|
|
54
|
+
IndentCaseLabels: true
|
|
55
|
+
IndentWidth: 2
|
|
56
|
+
IndentWrappedFunctionNames: false
|
|
57
|
+
KeepEmptyLinesAtTheStartOfBlocks: false
|
|
58
|
+
MacroBlockBegin: ''
|
|
59
|
+
MacroBlockEnd: ''
|
|
60
|
+
MaxEmptyLinesToKeep: 1
|
|
61
|
+
NamespaceIndentation: None
|
|
62
|
+
ObjCBlockIndentWidth: 2
|
|
63
|
+
ObjCSpaceAfterProperty: true
|
|
64
|
+
ObjCSpaceBeforeProtocolList: true
|
|
65
|
+
PenaltyBreakBeforeFirstCallParameter: 1
|
|
66
|
+
PenaltyBreakComment: 300
|
|
67
|
+
PenaltyBreakFirstLessLess: 120
|
|
68
|
+
PenaltyBreakString: 1000
|
|
69
|
+
PenaltyExcessCharacter: 1000000
|
|
70
|
+
PenaltyReturnTypeOnItsOwnLine: 200
|
|
71
|
+
PointerAlignment: Right
|
|
72
|
+
ReflowComments: true
|
|
73
|
+
SortIncludes: true
|
|
74
|
+
SpaceAfterCStyleCast: false
|
|
75
|
+
SpaceBeforeAssignmentOperators: true
|
|
76
|
+
SpaceBeforeParens: ControlStatements
|
|
77
|
+
SpaceInEmptyParentheses: false
|
|
78
|
+
SpacesBeforeTrailingComments: 1
|
|
79
|
+
SpacesInAngles: false
|
|
80
|
+
SpacesInContainerLiterals: true
|
|
81
|
+
SpacesInCStyleCastParentheses: false
|
|
82
|
+
SpacesInParentheses: false
|
|
83
|
+
SpacesInSquareBrackets: false
|
|
84
|
+
Standard: Cpp11
|
|
85
|
+
TabWidth: 8
|
|
86
|
+
UseTab: Never
|
|
87
|
+
---
|
|
88
|
+
Language: ObjC
|
|
89
|
+
ColumnLimit: 100
|
|
90
|
+
BreakBeforeBraces: WebKit
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
/* Begin PBXBuildFile section */
|
|
10
10
|
F359D34D28133BE1000B6AFE /* KeyboardControllerModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = F359D34C28133BE1000B6AFE /* KeyboardControllerModule.swift */; };
|
|
11
11
|
F359D34F28133C26000B6AFE /* KeyboardControllerModule.m in Sources */ = {isa = PBXBuildFile; fileRef = F359D34E28133C26000B6AFE /* KeyboardControllerModule.m */; };
|
|
12
|
+
F3626A0728B3FE760021B2D9 /* KeyboardMovementObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3626A0628B3FE760021B2D9 /* KeyboardMovementObserver.swift */; };
|
|
12
13
|
F3FF0915281851CC006831B1 /* KeyboardMoveEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3FF0914281851CC006831B1 /* KeyboardMoveEvent.swift */; };
|
|
13
14
|
F4FF95D7245B92E800C19C63 /* KeyboardControllerViewManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FF95D6245B92E800C19C63 /* KeyboardControllerViewManager.swift */; };
|
|
14
15
|
/* End PBXBuildFile section */
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
F359D34C28133BE1000B6AFE /* KeyboardControllerModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardControllerModule.swift; sourceTree = "<group>"; };
|
|
32
33
|
F359D34E28133C26000B6AFE /* KeyboardControllerModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeyboardControllerModule.m; sourceTree = "<group>"; };
|
|
33
34
|
F359D35028133C6F000B6AFE /* KeyboardControllerModule-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KeyboardControllerModule-Header.h"; sourceTree = "<group>"; };
|
|
35
|
+
F3626A0628B3FE760021B2D9 /* KeyboardMovementObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardMovementObserver.swift; sourceTree = "<group>"; };
|
|
34
36
|
F3FF0914281851CC006831B1 /* KeyboardMoveEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardMoveEvent.swift; sourceTree = "<group>"; };
|
|
35
37
|
F4FF95D5245B92E700C19C63 /* KeyboardController-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KeyboardController-Bridging-Header.h"; sourceTree = "<group>"; };
|
|
36
38
|
F4FF95D6245B92E800C19C63 /* KeyboardControllerViewManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardControllerViewManager.swift; sourceTree = "<group>"; };
|
|
@@ -58,6 +60,7 @@
|
|
|
58
60
|
58B511D21A9E6C8500147676 = {
|
|
59
61
|
isa = PBXGroup;
|
|
60
62
|
children = (
|
|
63
|
+
F3626A0628B3FE760021B2D9 /* KeyboardMovementObserver.swift */,
|
|
61
64
|
F3FF0914281851CC006831B1 /* KeyboardMoveEvent.swift */,
|
|
62
65
|
F359D35028133C6F000B6AFE /* KeyboardControllerModule-Header.h */,
|
|
63
66
|
F359D34E28133C26000B6AFE /* KeyboardControllerModule.m */,
|
|
@@ -127,6 +130,7 @@
|
|
|
127
130
|
buildActionMask = 2147483647;
|
|
128
131
|
files = (
|
|
129
132
|
F3FF0915281851CC006831B1 /* KeyboardMoveEvent.swift in Sources */,
|
|
133
|
+
F3626A0728B3FE760021B2D9 /* KeyboardMovementObserver.swift in Sources */,
|
|
130
134
|
F359D34F28133C26000B6AFE /* KeyboardControllerModule.m in Sources */,
|
|
131
135
|
F359D34D28133BE1000B6AFE /* KeyboardControllerModule.swift in Sources */,
|
|
132
136
|
F4FF95D7245B92E800C19C63 /* KeyboardControllerViewManager.swift in Sources */,
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
#import <React/RCTBridgeModule.h>
|
|
10
10
|
#import <React/RCTEventEmitter.h>
|
|
11
11
|
|
|
12
|
-
@interface RCT_EXTERN_MODULE(KeyboardController, RCTEventEmitter)
|
|
12
|
+
@interface RCT_EXTERN_MODULE (KeyboardController, RCTEventEmitter)
|
|
13
13
|
|
|
14
14
|
// Android stubs
|
|
15
|
-
RCT_EXTERN_METHOD(setInputMode: (nonnull NSNumber*)
|
|
15
|
+
RCT_EXTERN_METHOD(setInputMode : (nonnull NSNumber *)mode)
|
|
16
16
|
RCT_EXTERN_METHOD(setDefaultMode)
|
|
17
17
|
|
|
18
18
|
// event emitter
|
|
@@ -10,6 +10,7 @@ class KeyboardControllerViewManager: RCTViewManager {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
class KeyboardControllerView: UIView {
|
|
13
|
+
private var keyboardObserver: KeyboardMovementObserver?
|
|
13
14
|
private var eventDispatcher: RCTEventDispatcherProtocol
|
|
14
15
|
@objc var onKeyboardMove: RCTDirectEventBlock?
|
|
15
16
|
|
|
@@ -26,81 +27,29 @@ class KeyboardControllerView: UIView {
|
|
|
26
27
|
override func willMove(toWindow newWindow: UIWindow?) {
|
|
27
28
|
if newWindow == nil {
|
|
28
29
|
// Will be removed from a window
|
|
29
|
-
|
|
30
|
-
NotificationCenter.default.removeObserver(self)
|
|
30
|
+
keyboardObserver?.unmount()
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
override func didMoveToWindow() {
|
|
35
35
|
if window != nil {
|
|
36
36
|
// Added to a window
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
selector: #selector(keyboardWillDisappear),
|
|
40
|
-
name: UIResponder.keyboardWillHideNotification,
|
|
41
|
-
object: nil
|
|
42
|
-
)
|
|
43
|
-
NotificationCenter.default.addObserver(
|
|
44
|
-
self,
|
|
45
|
-
selector: #selector(keyboardWillAppear),
|
|
46
|
-
name: UIResponder.keyboardWillShowNotification,
|
|
47
|
-
object: nil
|
|
48
|
-
)
|
|
49
|
-
NotificationCenter.default.addObserver(
|
|
50
|
-
self,
|
|
51
|
-
selector: #selector(keyboardDidAppear),
|
|
52
|
-
name: UIResponder.keyboardDidShowNotification,
|
|
53
|
-
object: nil
|
|
54
|
-
)
|
|
55
|
-
NotificationCenter.default.addObserver(
|
|
56
|
-
self,
|
|
57
|
-
selector: #selector(keyboardDidDisappear),
|
|
58
|
-
name: UIResponder.keyboardDidHideNotification,
|
|
59
|
-
object: nil
|
|
60
|
-
)
|
|
37
|
+
keyboardObserver = KeyboardMovementObserver(handler: onEvent, onNotify: onNotify)
|
|
38
|
+
keyboardObserver?.mount()
|
|
61
39
|
}
|
|
62
40
|
}
|
|
63
41
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
viewTag: reactTag,
|
|
71
|
-
height: -keyboardHeight as NSNumber,
|
|
72
|
-
progress: 1
|
|
73
|
-
)
|
|
42
|
+
func onEvent(height: NSNumber, progress: NSNumber) {
|
|
43
|
+
eventDispatcher.send(
|
|
44
|
+
KeyboardMoveEvent(
|
|
45
|
+
viewTag: reactTag,
|
|
46
|
+
height: height,
|
|
47
|
+
progress: progress
|
|
74
48
|
)
|
|
75
|
-
|
|
76
|
-
var data = [AnyHashable: Any]()
|
|
77
|
-
data["height"] = keyboardHeight
|
|
78
|
-
KeyboardController.shared?.sendEvent(withName: "KeyboardController::keyboardWillShow", body: data)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
@objc func keyboardWillDisappear() {
|
|
83
|
-
eventDispatcher.send(KeyboardMoveEvent(viewTag: reactTag, height: 0, progress: 0))
|
|
84
|
-
|
|
85
|
-
var data = [AnyHashable: Any]()
|
|
86
|
-
data["height"] = 0
|
|
87
|
-
KeyboardController.shared?.sendEvent(withName: "KeyboardController::keyboardWillHide", body: data)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
@objc func keyboardDidAppear(_ notification: Notification) {
|
|
91
|
-
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
|
|
92
|
-
let keyboardHeight = keyboardFrame.cgRectValue.size.height
|
|
93
|
-
|
|
94
|
-
var data = [AnyHashable: Any]()
|
|
95
|
-
data["height"] = keyboardHeight
|
|
96
|
-
|
|
97
|
-
KeyboardController.shared?.sendEvent(withName: "KeyboardController::keyboardDidShow", body: data)
|
|
98
|
-
}
|
|
49
|
+
)
|
|
99
50
|
}
|
|
100
51
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
data["height"] = 0
|
|
104
|
-
KeyboardController.shared?.sendEvent(withName: "KeyboardController::keyboardDidHide", body: data)
|
|
52
|
+
func onNotify(event: String, data: Any) {
|
|
53
|
+
KeyboardController.shared?.sendEvent(withName: event, body: data)
|
|
105
54
|
}
|
|
106
55
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
//
|
|
2
|
+
// KeyboardMovementObserver.swift
|
|
3
|
+
// KeyboardController
|
|
4
|
+
//
|
|
5
|
+
// Created by Kiryl Ziusko on 2.08.22.
|
|
6
|
+
// Copyright © 2022 Facebook. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
|
|
11
|
+
@objc(KeyboardMovementObserver)
|
|
12
|
+
public class KeyboardMovementObserver: NSObject {
|
|
13
|
+
var onEvent: (NSNumber, NSNumber) -> Void
|
|
14
|
+
var onNotify: (String, Any) -> Void
|
|
15
|
+
|
|
16
|
+
@objc public init(handler: @escaping (NSNumber, NSNumber) -> Void, onNotify: @escaping (String, Any) -> Void) {
|
|
17
|
+
onEvent = handler
|
|
18
|
+
self.onNotify = onNotify
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@objc public func mount() {
|
|
22
|
+
NotificationCenter.default.addObserver(
|
|
23
|
+
self,
|
|
24
|
+
selector: #selector(keyboardWillDisappear),
|
|
25
|
+
name: UIResponder.keyboardWillHideNotification,
|
|
26
|
+
object: nil
|
|
27
|
+
)
|
|
28
|
+
NotificationCenter.default.addObserver(
|
|
29
|
+
self,
|
|
30
|
+
selector: #selector(keyboardWillAppear),
|
|
31
|
+
name: UIResponder.keyboardWillShowNotification,
|
|
32
|
+
object: nil
|
|
33
|
+
)
|
|
34
|
+
NotificationCenter.default.addObserver(
|
|
35
|
+
self,
|
|
36
|
+
selector: #selector(keyboardDidAppear),
|
|
37
|
+
name: UIResponder.keyboardDidShowNotification,
|
|
38
|
+
object: nil
|
|
39
|
+
)
|
|
40
|
+
NotificationCenter.default.addObserver(
|
|
41
|
+
self,
|
|
42
|
+
selector: #selector(keyboardDidDisappear),
|
|
43
|
+
name: UIResponder.keyboardDidHideNotification,
|
|
44
|
+
object: nil
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@objc public func unmount() {
|
|
49
|
+
// swiftlint:disable notification_center_detachment
|
|
50
|
+
NotificationCenter.default.removeObserver(self)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@objc func keyboardWillAppear(_ notification: Notification) {
|
|
54
|
+
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
|
|
55
|
+
let keyboardHeight = keyboardFrame.cgRectValue.size.height
|
|
56
|
+
|
|
57
|
+
var data = [AnyHashable: Any]()
|
|
58
|
+
data["height"] = keyboardHeight
|
|
59
|
+
|
|
60
|
+
onEvent(Float(-keyboardHeight) as NSNumber, 1)
|
|
61
|
+
onNotify("KeyboardController::keyboardWillShow", data)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@objc func keyboardWillDisappear() {
|
|
66
|
+
var data = [AnyHashable: Any]()
|
|
67
|
+
data["height"] = 0
|
|
68
|
+
|
|
69
|
+
onEvent(0, 0)
|
|
70
|
+
onNotify("KeyboardController::keyboardWillHide", data)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@objc func keyboardDidAppear(_ notification: Notification) {
|
|
74
|
+
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
|
|
75
|
+
let keyboardHeight = keyboardFrame.cgRectValue.size.height
|
|
76
|
+
|
|
77
|
+
var data = [AnyHashable: Any]()
|
|
78
|
+
data["height"] = keyboardHeight
|
|
79
|
+
|
|
80
|
+
onNotify("KeyboardController::keyboardDidShow", data)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@objc func keyboardDidDisappear() {
|
|
85
|
+
var data = [AnyHashable: Any]()
|
|
86
|
+
data["height"] = 0
|
|
87
|
+
|
|
88
|
+
onNotify("KeyboardController::keyboardDidHide", data)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"names":["KeyboardControllerViewAnimated","Reanimated","createAnimatedComponent","Animated","KeyboardControllerView","defaultContext","animated","progress","Value","height","reanimated","value","KeyboardContext","React","createContext","useKeyboardAnimation","useResizeMode","context","useContext","useReanimatedKeyboardAnimation","useAnimatedKeyboardHandler","handlers","dependencies","doDependenciesDiffer","useHandler","useEvent","event","onKeyboardMove","eventName","endsWith","styles","StyleSheet","create","container","flex","hidden","display","position","KeyboardProvider","children","statusBarTranslucent","useRef","current","progressSV","useSharedValue","heightSV","useMemo","style","transform","translateX","translateY","nativeEvent","useNativeDriver","handler"],"sources":["animated.tsx"],"sourcesContent":["import React, { useContext, useMemo, useRef } from 'react';\nimport { Animated, StyleSheet, ViewStyle } from 'react-native';\nimport Reanimated, {\n useEvent,\n useHandler,\n useSharedValue,\n} from 'react-native-reanimated';\nimport {\n EventWithName,\n KeyboardControllerProps,\n KeyboardControllerView,\n NativeEvent,\n useResizeMode,\n} from './native';\n\nconst KeyboardControllerViewAnimated = Reanimated.createAnimatedComponent(\n Animated.createAnimatedComponent(\n KeyboardControllerView\n ) as React.FC<KeyboardControllerProps>\n);\n\ntype AnimatedContext = {\n progress: Animated.Value;\n height: Animated.Value;\n};\ntype ReanimatedContext = {\n progress: Reanimated.SharedValue<number>;\n height: Reanimated.SharedValue<number>;\n};\ntype KeyboardAnimationContext = {\n animated: AnimatedContext;\n reanimated: ReanimatedContext;\n};\nconst defaultContext: KeyboardAnimationContext = {\n animated: {\n progress: new Animated.Value(0),\n height: new Animated.Value(0),\n },\n reanimated: {\n progress: { value: 0 },\n height: { value: 0 },\n },\n};\nexport const KeyboardContext = React.createContext(defaultContext);\n\nexport const useKeyboardAnimation = (): AnimatedContext => {\n useResizeMode();\n const context = useContext(KeyboardContext);\n\n return context.animated;\n};\n\nexport const useReanimatedKeyboardAnimation = (): ReanimatedContext => {\n useResizeMode();\n const context = useContext(KeyboardContext);\n\n return context.reanimated;\n};\n\nfunction useAnimatedKeyboardHandler<TContext extends Record<string, unknown>>(\n handlers: {\n onKeyboardMove?: (e: NativeEvent, context: TContext) => void;\n },\n dependencies?: ReadonlyArray<unknown>\n) {\n const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);\n\n return useEvent(\n (event: EventWithName<NativeEvent>) => {\n 'worklet';\n const { onKeyboardMove } = handlers;\n\n if (onKeyboardMove && event.eventName.endsWith('onKeyboardMove')) {\n onKeyboardMove(event, context);\n }\n },\n ['onKeyboardMove'],\n doDependenciesDiffer\n );\n}\n\ntype Styles = {\n container: ViewStyle;\n hidden: ViewStyle;\n};\n\nexport const styles = StyleSheet.create<Styles>({\n container: {\n flex: 1,\n },\n hidden: {\n display: 'none',\n position: 'absolute',\n },\n});\n\ntype KeyboardProviderProps = {\n children: React.ReactNode;\n /**\n * Set the value to `true`, if you use translucent status bar on Android.\n * If you already control status bar translucency via `react-native-screens`\n * or `StatusBar` component from `react-native`, you can ignore it.\n * Defaults to `false`.\n *\n * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/14\n * @platform android\n */\n statusBarTranslucent?: boolean;\n};\n\nexport const KeyboardProvider = ({\n children,\n statusBarTranslucent,\n}: KeyboardProviderProps) => {\n const progress = useRef(new Animated.Value(0)).current;\n const height = useRef(new Animated.Value(0)).current;\n const progressSV = useSharedValue(0);\n const heightSV = useSharedValue(0);\n const context = useMemo(\n () => ({\n animated: { progress: progress, height: height },\n reanimated: { progress: progressSV, height: heightSV },\n }),\n []\n );\n const style = useMemo(\n () => [\n styles.hidden,\n { transform: [{ translateX: height }, { translateY: progress }] },\n ],\n []\n );\n\n const onKeyboardMove = useMemo(\n () =>\n Animated.event(\n [\n {\n nativeEvent: {\n progress,\n height,\n },\n },\n ],\n { useNativeDriver: true }\n ),\n []\n );\n\n const handler = useAnimatedKeyboardHandler(\n {\n onKeyboardMove: (event: NativeEvent) => {\n 'worklet';\n progressSV.value = event.progress;\n heightSV.value = event.height;\n },\n },\n []\n );\n\n return (\n <KeyboardContext.Provider value={context}>\n <KeyboardControllerViewAnimated\n onKeyboardMoveReanimated={handler}\n onKeyboardMove={onKeyboardMove}\n statusBarTranslucent={statusBarTranslucent}\n style={styles.container}\n >\n <>\n <Animated.View\n // we are using this small hack, because if the component (where\n // animated value has been used) is unmounted, then animation will\n // stop receiving events (seems like it's react-native optimization).\n // So we need to keep a reference to the animated value, to keep it's\n // always mounted (keep a reference to an animated value).\n //\n // To test why it's needed, try to open screen which consumes Animated.Value\n // then close it and open it again (for example 'Animated transition').\n style={style}\n />\n {children}\n </>\n </KeyboardControllerViewAnimated>\n </KeyboardContext.Provider>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["index.ts"],"
|
|
1
|
+
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["import './monkey-patch';\n\nexport * from './native';\nexport * from './animated';\nexport * from './replicas';\n"],"mappings":";;;;;;AAAA;;AAEA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;;AACA;;AAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"names":["getConstants","NativeAndroidManager","default","RCTStatusBarManagerCompat","NativeModules","StatusBarManagerCompat","Platform","OS","setColor","color","animated","setTranslucent","translucent","setStyle","statusBarStyle","setHidden","hidden"],"sources":["monkey-patch.tsx"],"sourcesContent":["import { NativeModules, Platform } from 'react-native';\n// @ts-expect-error because there is no corresponding type definition\nimport * as NativeAndroidManager from 'react-native/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid';\n\nconst getConstants = NativeAndroidManager.default.getConstants;\n\nconst RCTStatusBarManagerCompat = NativeModules.StatusBarManagerCompat;\n\n// On Android < 11 RN uses legacy API which breaks EdgeToEdge mode in RN, so\n// in order to use library on all available platforms we have to monkey patch\n// default RN implementation and use modern `WindowInsetsControllerCompat`.\nif (Platform.OS === 'android') {\n NativeAndroidManager.default = {\n getConstants,\n setColor(color: number, animated: boolean): void {\n RCTStatusBarManagerCompat.setColor(color, animated);\n },\n\n setTranslucent(translucent: boolean): void {\n RCTStatusBarManagerCompat.setTranslucent(translucent);\n },\n\n /**\n * - statusBarStyles can be:\n * - 'default'\n * - 'dark-content'\n */\n setStyle(statusBarStyle?: string): void {\n RCTStatusBarManagerCompat.setStyle(statusBarStyle);\n },\n\n setHidden(hidden: boolean): void {\n RCTStatusBarManagerCompat.setHidden(hidden);\n },\n };\n}\n"],"mappings":";;AAAA;;AAEA;;;;;;AADA;AAGA,MAAMA,YAAY,GAAGC,oBAAoB,CAACC,OAArB,CAA6BF,YAAlD;AAEA,MAAMG,yBAAyB,GAAGC,0BAAA,CAAcC,sBAAhD,C,CAEA;AACA;AACA;;AACA,IAAIC,qBAAA,CAASC,EAAT,KAAgB,SAApB,EAA+B;EAC7BN,oBAAoB,CAACC,OAArB,GAA+B;IAC7BF,YAD6B;;IAE7BQ,QAAQ,CAACC,KAAD,EAAgBC,QAAhB,EAAyC;MAC/CP,yBAAyB,CAACK,QAA1B,CAAmCC,KAAnC,EAA0CC,QAA1C;IACD,CAJ4B;;IAM7BC,cAAc,CAACC,WAAD,EAA6B;MACzCT,yBAAyB,CAACQ,cAA1B,CAAyCC,WAAzC;IACD,CAR4B;;IAU7B;AACJ;AACA;AACA;AACA;IACIC,QAAQ,CAACC,cAAD,EAAgC;MACtCX,yBAAyB,CAACU,QAA1B,CAAmCC,cAAnC;IACD,CAjB4B;;IAmB7BC,SAAS,CAACC,MAAD,EAAwB;MAC/Bb,yBAAyB,CAACY,SAA1B,CAAoCC,MAApC;IACD;;EArB4B,CAA/B;AAuBD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"names":["LINKING_ERROR","Platform","select","ios","default","AndroidSoftInputModes","ComponentName","RCTKeyboardController","NativeModules","KeyboardController","eventEmitter","NativeEventEmitter","KeyboardEvents","addListener","name","cb","KeyboardControllerView","UIManager","getViewManagerConfig","requireNativeComponent","Error","useResizeMode","useEffect","setInputMode","SOFT_INPUT_ADJUST_RESIZE","setDefaultMode"],"sources":["native.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport {\n requireNativeComponent,\n UIManager,\n Platform,\n NativeModules,\n NativeEventEmitter,\n NativeSyntheticEvent,\n ViewProps,\n} from 'react-native';\n\nconst LINKING_ERROR =\n `The package 'react-native-keyboard-controller' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo managed workflow\\n';\n\nexport enum AndroidSoftInputModes {\n SOFT_INPUT_ADJUST_NOTHING = 48,\n SOFT_INPUT_ADJUST_PAN = 32,\n SOFT_INPUT_ADJUST_RESIZE = 16,\n SOFT_INPUT_ADJUST_UNSPECIFIED = 0,\n}\n\nexport type NativeEvent = {\n progress: number;\n height: number;\n};\nexport type EventWithName<T> = {\n eventName: string;\n} & T;\nexport type KeyboardControllerProps = {\n onKeyboardMove: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;\n // fake prop used to activate reanimated bindings\n onKeyboardMoveReanimated: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>\n ) => void;\n statusBarTranslucent?: boolean;\n} & ViewProps;\ntype KeyboardController = {\n // android only\n setDefaultMode: () => void;\n setInputMode: (mode: AndroidSoftInputModes) => void;\n};\n\nconst ComponentName = 'KeyboardControllerView';\n\nconst RCTKeyboardController = NativeModules.KeyboardController;\nexport const KeyboardController = RCTKeyboardController as KeyboardController;\n\nconst eventEmitter = new NativeEventEmitter(RCTKeyboardController);\ntype KeyboardControllerEvents =\n | 'keyboardWillShow'\n | 'keyboardDidShow'\n | 'keyboardWillHide'\n | 'keyboardDidHide';\ntype KeyboardEvent = {\n height: number;\n};\nexport const KeyboardEvents = {\n addListener: (\n name: KeyboardControllerEvents,\n cb: (e: KeyboardEvent) => void\n ) => eventEmitter.addListener('KeyboardController::' + name, cb),\n};\nexport const KeyboardControllerView =\n UIManager.getViewManagerConfig(ComponentName) != null\n ? requireNativeComponent<KeyboardControllerProps>(ComponentName)\n : () => {\n throw new Error(LINKING_ERROR);\n };\n\nexport const useResizeMode = () => {\n useEffect(() => {\n KeyboardController.setInputMode(\n AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE\n );\n\n return () => KeyboardController.setDefaultMode();\n }, []);\n};\n"],"mappings":";;;;;;;AAAA;;AACA;;AAUA,MAAMA,aAAa,GAChB,2FAAD,GACAC,qBAAA,CAASC,MAAT,CAAgB;EAAEC,GAAG,EAAE,gCAAP;EAAyCC,OAAO,EAAE;AAAlD,CAAhB,CADA,GAEA,sDAFA,GAGA,6CAJF;IAMYC,qB;;;WAAAA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;GAAAA,qB,qCAAAA,qB;;AA4BZ,MAAMC,aAAa,GAAG,wBAAtB;AAEA,MAAMC,qBAAqB,GAAGC,0BAAA,CAAcC,kBAA5C;AACO,MAAMA,kBAAkB,GAAGF,qBAA3B;;AAEP,MAAMG,YAAY,GAAG,IAAIC,+BAAJ,CAAuBJ,qBAAvB,CAArB;AASO,MAAMK,cAAc,GAAG;EAC5BC,WAAW,EAAE,CACXC,IADW,EAEXC,EAFW,KAGRL,YAAY,CAACG,WAAb,CAAyB,yBAAyBC,IAAlD,EAAwDC,EAAxD;AAJuB,CAAvB;;AAMA,MAAMC,sBAAsB,GACjCC,sBAAA,CAAUC,oBAAV,CAA+BZ,aAA/B,KAAiD,IAAjD,GACI,IAAAa,mCAAA,EAAgDb,aAAhD,CADJ,GAEI,MAAM;EACJ,MAAM,IAAIc,KAAJ,CAAUpB,aAAV,CAAN;AACD,CALA;;;AAOA,MAAMqB,aAAa,GAAG,MAAM;EACjC,IAAAC,gBAAA,EAAU,MAAM;IACdb,kBAAkB,CAACc,YAAnB,CACElB,qBAAqB,CAACmB,wBADxB;IAIA,OAAO,MAAMf,kBAAkB,CAACgB,cAAnB,EAAb;EACD,CAND,EAMG,EANH;AAOD,CARM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"names":["availableOSEventType","Platform","OS","defaultAndroidEasing","Easing","bezier","useKeyboardAnimationReplica","height","useRef","Animated","Value","progress","animation","useMemo","current","useEffect","KeyboardController","setInputMode","AndroidSoftInputModes","SOFT_INPUT_ADJUST_RESIZE","setDefaultMode","listener","Keyboard","addListener","e","timing","toValue","endCoordinates","duration","easing","useNativeDriver","start","remove","IOS_SPRING_CONFIG","damping","stiffness","mass","overshootClamping","restDisplacementThreshold","restSpeedThreshold","useReanimatedKeyboardAnimationReplica","useSharedValue","heightEvent","useDerivedValue","value","handler","useWorkletCallback","_height","useAnimatedReaction","_keyboardHeight","result","_previousResult","_previousKeyboardHeight","withSpring","show","runOnUI","hide","useGradualKeyboardAnimation","useReanimatedKeyboardAnimation"],"sources":["replicas.ts"],"sourcesContent":["import { useRef, useEffect, useMemo } from 'react';\nimport { Animated, Easing, Keyboard, Platform } from 'react-native';\nimport {\n runOnUI,\n useAnimatedReaction,\n useDerivedValue,\n useSharedValue,\n useWorkletCallback,\n withSpring,\n} from 'react-native-reanimated';\nimport { useReanimatedKeyboardAnimation } from './animated';\n\nimport { AndroidSoftInputModes, KeyboardController } from './native';\n\nconst availableOSEventType = Platform.OS === 'ios' ? 'Will' : 'Did';\n\n// cubic-bezier(.17,.67,.34,.94)\nexport const defaultAndroidEasing = Easing.bezier(0.4, 0.0, 0.2, 1);\ntype KeyboardAnimation = {\n progress: Animated.Value;\n height: Animated.Value;\n};\n\n/**\n * An experimental implementation of tracing keyboard appearance.\n * Switch an input mode to adjust resize mode. In this case all did* events\n * are triggering before keyboard appears, and using some approximations\n * it tries to mimicries a native transition.\n *\n * @returns {Animated.Value}\n */\nexport const useKeyboardAnimationReplica = (): KeyboardAnimation => {\n const height = useRef(new Animated.Value(0));\n const progress = useRef(new Animated.Value(0));\n const animation = useMemo(\n () => ({\n height: height.current,\n progress: progress.current,\n }),\n []\n );\n\n useEffect(() => {\n KeyboardController.setInputMode(\n AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE\n );\n\n return () => KeyboardController.setDefaultMode();\n }, []);\n useEffect(() => {\n const listener = Keyboard.addListener(\n `keyboard${availableOSEventType}Show`,\n (e) => {\n Animated.timing(height.current, {\n toValue: -e.endCoordinates.height,\n duration: e.duration !== 0 ? e.duration : 300,\n easing: Easing.bezier(0.4, 0.0, 0.2, 1),\n useNativeDriver: true,\n }).start();\n\n return () => listener.remove();\n }\n );\n }, []);\n useEffect(() => {\n const listener = Keyboard.addListener(\n `keyboard${availableOSEventType}Hide`,\n (e) => {\n Animated.timing(height.current, {\n toValue: 0,\n duration: e.duration !== 0 ? e.duration : 300,\n easing: Easing.bezier(0.4, 0.0, 0.2, 1),\n useNativeDriver: true,\n }).start();\n\n return () => listener.remove();\n }\n );\n }, []);\n\n return animation;\n};\n\nconst IOS_SPRING_CONFIG = {\n damping: 500,\n stiffness: 1000,\n mass: 3,\n overshootClamping: true,\n restDisplacementThreshold: 10,\n restSpeedThreshold: 10,\n};\n\n/**\n * A close replica to native iOS keyboard animation. The problem is that\n * iOS (unlike Android) can not fire events for each keyboard frame movement.\n * As a result we can not get gradual values (for example, for progress it always\n * will be 1 or 0). So if you want to rely on gradual values you will need to use\n * this replica.\n *\n * The transition is hardcoded and may vary from one to another OS versions. But it\n * seems like last time it has been changed in iOS 7. Since RN supports at least iOS\n * 11 it doesn't make sense to replicate iOS 7 behavior. If it changes in next OS\n * versions, then this implementation should be revisited and reflect necessary changes.\n *\n * @returns {height, progress} - animated values\n */\nexport const useReanimatedKeyboardAnimationReplica = () => {\n const height = useSharedValue(0);\n const heightEvent = useSharedValue(0);\n\n const progress = useDerivedValue(() => height.value / heightEvent.value);\n\n const handler = useWorkletCallback((_height: number) => {\n heightEvent.value = _height;\n }, []);\n\n useAnimatedReaction(\n () => ({\n _keyboardHeight: heightEvent.value,\n }),\n (result, _previousResult) => {\n const { _keyboardHeight } = result;\n const _previousKeyboardHeight = _previousResult?._keyboardHeight;\n\n if (_keyboardHeight !== _previousKeyboardHeight) {\n height.value = withSpring(_keyboardHeight, IOS_SPRING_CONFIG);\n }\n },\n []\n );\n\n useEffect(() => {\n const show = Keyboard.addListener('keyboardWillShow', (e) => {\n runOnUI(handler)(-e.endCoordinates.height);\n });\n const hide = Keyboard.addListener('keyboardWillHide', () => {\n runOnUI(handler)(0);\n });\n\n return () => {\n show.remove();\n hide.remove();\n };\n }, []);\n\n return { height, progress };\n};\n\nexport const useGradualKeyboardAnimation =\n Platform.OS === 'ios'\n ? useReanimatedKeyboardAnimationReplica\n : useReanimatedKeyboardAnimation;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"names":["React","useContext","useMemo","useRef","Animated","StyleSheet","Reanimated","useEvent","useHandler","useSharedValue","KeyboardControllerView","useResizeMode","KeyboardControllerViewAnimated","createAnimatedComponent","defaultContext","animated","progress","Value","height","reanimated","value","KeyboardContext","createContext","useKeyboardAnimation","context","useReanimatedKeyboardAnimation","useAnimatedKeyboardHandler","handlers","dependencies","doDependenciesDiffer","event","onKeyboardMove","eventName","endsWith","styles","create","container","flex","hidden","display","position","KeyboardProvider","children","statusBarTranslucent","current","progressSV","heightSV","style","transform","translateX","translateY","nativeEvent","useNativeDriver","handler"],"sources":["animated.tsx"],"sourcesContent":["import React, { useContext, useMemo, useRef } from 'react';\nimport { Animated, StyleSheet, ViewStyle } from 'react-native';\nimport Reanimated, {\n useEvent,\n useHandler,\n useSharedValue,\n} from 'react-native-reanimated';\nimport {\n EventWithName,\n KeyboardControllerProps,\n KeyboardControllerView,\n NativeEvent,\n useResizeMode,\n} from './native';\n\nconst KeyboardControllerViewAnimated = Reanimated.createAnimatedComponent(\n Animated.createAnimatedComponent(\n KeyboardControllerView\n ) as React.FC<KeyboardControllerProps>\n);\n\ntype AnimatedContext = {\n progress: Animated.Value;\n height: Animated.Value;\n};\ntype ReanimatedContext = {\n progress: Reanimated.SharedValue<number>;\n height: Reanimated.SharedValue<number>;\n};\ntype KeyboardAnimationContext = {\n animated: AnimatedContext;\n reanimated: ReanimatedContext;\n};\nconst defaultContext: KeyboardAnimationContext = {\n animated: {\n progress: new Animated.Value(0),\n height: new Animated.Value(0),\n },\n reanimated: {\n progress: { value: 0 },\n height: { value: 0 },\n },\n};\nexport const KeyboardContext = React.createContext(defaultContext);\n\nexport const useKeyboardAnimation = (): AnimatedContext => {\n useResizeMode();\n const context = useContext(KeyboardContext);\n\n return context.animated;\n};\n\nexport const useReanimatedKeyboardAnimation = (): ReanimatedContext => {\n useResizeMode();\n const context = useContext(KeyboardContext);\n\n return context.reanimated;\n};\n\nfunction useAnimatedKeyboardHandler<TContext extends Record<string, unknown>>(\n handlers: {\n onKeyboardMove?: (e: NativeEvent, context: TContext) => void;\n },\n dependencies?: ReadonlyArray<unknown>\n) {\n const { context, doDependenciesDiffer } = useHandler(handlers, dependencies);\n\n return useEvent(\n (event: EventWithName<NativeEvent>) => {\n 'worklet';\n const { onKeyboardMove } = handlers;\n\n if (onKeyboardMove && event.eventName.endsWith('onKeyboardMove')) {\n onKeyboardMove(event, context);\n }\n },\n ['onKeyboardMove'],\n doDependenciesDiffer\n );\n}\n\ntype Styles = {\n container: ViewStyle;\n hidden: ViewStyle;\n};\n\nexport const styles = StyleSheet.create<Styles>({\n container: {\n flex: 1,\n },\n hidden: {\n display: 'none',\n position: 'absolute',\n },\n});\n\ntype KeyboardProviderProps = {\n children: React.ReactNode;\n /**\n * Set the value to `true`, if you use translucent status bar on Android.\n * If you already control status bar translucency via `react-native-screens`\n * or `StatusBar` component from `react-native`, you can ignore it.\n * Defaults to `false`.\n *\n * @see https://github.com/kirillzyusko/react-native-keyboard-controller/issues/14\n * @platform android\n */\n statusBarTranslucent?: boolean;\n};\n\nexport const KeyboardProvider = ({\n children,\n statusBarTranslucent,\n}: KeyboardProviderProps) => {\n const progress = useRef(new Animated.Value(0)).current;\n const height = useRef(new Animated.Value(0)).current;\n const progressSV = useSharedValue(0);\n const heightSV = useSharedValue(0);\n const context = useMemo(\n () => ({\n animated: { progress: progress, height: height },\n reanimated: { progress: progressSV, height: heightSV },\n }),\n []\n );\n const style = useMemo(\n () => [\n styles.hidden,\n { transform: [{ translateX: height }, { translateY: progress }] },\n ],\n []\n );\n\n const onKeyboardMove = useMemo(\n () =>\n Animated.event(\n [\n {\n nativeEvent: {\n progress,\n height,\n },\n },\n ],\n { useNativeDriver: true }\n ),\n []\n );\n\n const handler = useAnimatedKeyboardHandler(\n {\n onKeyboardMove: (event: NativeEvent) => {\n 'worklet';\n progressSV.value = event.progress;\n heightSV.value = event.height;\n },\n },\n []\n );\n\n return (\n <KeyboardContext.Provider value={context}>\n <KeyboardControllerViewAnimated\n onKeyboardMoveReanimated={handler}\n onKeyboardMove={onKeyboardMove}\n statusBarTranslucent={statusBarTranslucent}\n style={styles.container}\n >\n <>\n <Animated.View\n // we are using this small hack, because if the component (where\n // animated value has been used) is unmounted, then animation will\n // stop receiving events (seems like it's react-native optimization).\n // So we need to keep a reference to the animated value, to keep it's\n // always mounted (keep a reference to an animated value).\n //\n // To test why it's needed, try to open screen which consumes Animated.Value\n // then close it and open it again (for example 'Animated transition').\n style={style}\n />\n {children}\n </>\n </KeyboardControllerViewAnimated>\n </KeyboardContext.Provider>\n );\n};\n"],"mappings":"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"}
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["import './monkey-patch';\n\nexport * from './native';\nexport * from './animated';\nexport * from './replicas';\n"],"mappings":"AAAA,OAAO,gBAAP;AAEA,cAAc,UAAd;AACA,cAAc,YAAd;AACA,cAAc,YAAd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"names":["NativeModules","Platform","NativeAndroidManager","getConstants","default","RCTStatusBarManagerCompat","StatusBarManagerCompat","OS","setColor","color","animated","setTranslucent","translucent","setStyle","statusBarStyle","setHidden","hidden"],"sources":["monkey-patch.tsx"],"sourcesContent":["import { NativeModules, Platform } from 'react-native';\n// @ts-expect-error because there is no corresponding type definition\nimport * as NativeAndroidManager from 'react-native/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid';\n\nconst getConstants = NativeAndroidManager.default.getConstants;\n\nconst RCTStatusBarManagerCompat = NativeModules.StatusBarManagerCompat;\n\n// On Android < 11 RN uses legacy API which breaks EdgeToEdge mode in RN, so\n// in order to use library on all available platforms we have to monkey patch\n// default RN implementation and use modern `WindowInsetsControllerCompat`.\nif (Platform.OS === 'android') {\n NativeAndroidManager.default = {\n getConstants,\n setColor(color: number, animated: boolean): void {\n RCTStatusBarManagerCompat.setColor(color, animated);\n },\n\n setTranslucent(translucent: boolean): void {\n RCTStatusBarManagerCompat.setTranslucent(translucent);\n },\n\n /**\n * - statusBarStyles can be:\n * - 'default'\n * - 'dark-content'\n */\n setStyle(statusBarStyle?: string): void {\n RCTStatusBarManagerCompat.setStyle(statusBarStyle);\n },\n\n setHidden(hidden: boolean): void {\n RCTStatusBarManagerCompat.setHidden(hidden);\n },\n };\n}\n"],"mappings":"AAAA,SAASA,aAAT,EAAwBC,QAAxB,QAAwC,cAAxC,C,CACA;;AACA,OAAO,KAAKC,oBAAZ,MAAsC,2EAAtC;AAEA,MAAMC,YAAY,GAAGD,oBAAoB,CAACE,OAArB,CAA6BD,YAAlD;AAEA,MAAME,yBAAyB,GAAGL,aAAa,CAACM,sBAAhD,C,CAEA;AACA;AACA;;AACA,IAAIL,QAAQ,CAACM,EAAT,KAAgB,SAApB,EAA+B;EAC7BL,oBAAoB,CAACE,OAArB,GAA+B;IAC7BD,YAD6B;;IAE7BK,QAAQ,CAACC,KAAD,EAAgBC,QAAhB,EAAyC;MAC/CL,yBAAyB,CAACG,QAA1B,CAAmCC,KAAnC,EAA0CC,QAA1C;IACD,CAJ4B;;IAM7BC,cAAc,CAACC,WAAD,EAA6B;MACzCP,yBAAyB,CAACM,cAA1B,CAAyCC,WAAzC;IACD,CAR4B;;IAU7B;AACJ;AACA;AACA;AACA;IACIC,QAAQ,CAACC,cAAD,EAAgC;MACtCT,yBAAyB,CAACQ,QAA1B,CAAmCC,cAAnC;IACD,CAjB4B;;IAmB7BC,SAAS,CAACC,MAAD,EAAwB;MAC/BX,yBAAyB,CAACU,SAA1B,CAAoCC,MAApC;IACD;;EArB4B,CAA/B;AAuBD"}
|
package/lib/module/native.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"names":["useEffect","requireNativeComponent","UIManager","Platform","NativeModules","NativeEventEmitter","LINKING_ERROR","select","ios","default","AndroidSoftInputModes","ComponentName","RCTKeyboardController","KeyboardController","eventEmitter","KeyboardEvents","addListener","name","cb","KeyboardControllerView","getViewManagerConfig","Error","useResizeMode","setInputMode","SOFT_INPUT_ADJUST_RESIZE","setDefaultMode"],"sources":["native.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport {\n requireNativeComponent,\n UIManager,\n Platform,\n NativeModules,\n NativeEventEmitter,\n NativeSyntheticEvent,\n ViewProps,\n} from 'react-native';\n\nconst LINKING_ERROR =\n `The package 'react-native-keyboard-controller' doesn't seem to be linked. Make sure: \\n\\n` +\n Platform.select({ ios: \"- You have run 'pod install'\\n\", default: '' }) +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo managed workflow\\n';\n\nexport enum AndroidSoftInputModes {\n SOFT_INPUT_ADJUST_NOTHING = 48,\n SOFT_INPUT_ADJUST_PAN = 32,\n SOFT_INPUT_ADJUST_RESIZE = 16,\n SOFT_INPUT_ADJUST_UNSPECIFIED = 0,\n}\n\nexport type NativeEvent = {\n progress: number;\n height: number;\n};\nexport type EventWithName<T> = {\n eventName: string;\n} & T;\nexport type KeyboardControllerProps = {\n onKeyboardMove: (e: NativeSyntheticEvent<EventWithName<NativeEvent>>) => void;\n // fake prop used to activate reanimated bindings\n onKeyboardMoveReanimated: (\n e: NativeSyntheticEvent<EventWithName<NativeEvent>>\n ) => void;\n statusBarTranslucent?: boolean;\n} & ViewProps;\ntype KeyboardController = {\n // android only\n setDefaultMode: () => void;\n setInputMode: (mode: AndroidSoftInputModes) => void;\n};\n\nconst ComponentName = 'KeyboardControllerView';\n\nconst RCTKeyboardController = NativeModules.KeyboardController;\nexport const KeyboardController = RCTKeyboardController as KeyboardController;\n\nconst eventEmitter = new NativeEventEmitter(RCTKeyboardController);\ntype KeyboardControllerEvents =\n | 'keyboardWillShow'\n | 'keyboardDidShow'\n | 'keyboardWillHide'\n | 'keyboardDidHide';\ntype KeyboardEvent = {\n height: number;\n};\nexport const KeyboardEvents = {\n addListener: (\n name: KeyboardControllerEvents,\n cb: (e: KeyboardEvent) => void\n ) => eventEmitter.addListener('KeyboardController::' + name, cb),\n};\nexport const KeyboardControllerView =\n UIManager.getViewManagerConfig(ComponentName) != null\n ? requireNativeComponent<KeyboardControllerProps>(ComponentName)\n : () => {\n throw new Error(LINKING_ERROR);\n };\n\nexport const useResizeMode = () => {\n useEffect(() => {\n KeyboardController.setInputMode(\n AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE\n );\n\n return () => KeyboardController.setDefaultMode();\n }, []);\n};\n"],"mappings":"AAAA,SAASA,SAAT,QAA0B,OAA1B;AACA,SACEC,sBADF,EAEEC,SAFF,EAGEC,QAHF,EAIEC,aAJF,EAKEC,kBALF,QAQO,cARP;AAUA,MAAMC,aAAa,GAChB,2FAAD,GACAH,QAAQ,CAACI,MAAT,CAAgB;EAAEC,GAAG,EAAE,gCAAP;EAAyCC,OAAO,EAAE;AAAlD,CAAhB,CADA,GAEA,sDAFA,GAGA,6CAJF;AAMA,WAAYC,qBAAZ;;WAAYA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;EAAAA,qB,CAAAA,qB;GAAAA,qB,KAAAA,qB;;AA4BZ,MAAMC,aAAa,GAAG,wBAAtB;AAEA,MAAMC,qBAAqB,GAAGR,aAAa,CAACS,kBAA5C;AACA,OAAO,MAAMA,kBAAkB,GAAGD,qBAA3B;AAEP,MAAME,YAAY,GAAG,IAAIT,kBAAJ,CAAuBO,qBAAvB,CAArB;AASA,OAAO,MAAMG,cAAc,GAAG;EAC5BC,WAAW,EAAE,CACXC,IADW,EAEXC,EAFW,KAGRJ,YAAY,CAACE,WAAb,CAAyB,yBAAyBC,IAAlD,EAAwDC,EAAxD;AAJuB,CAAvB;AAMP,OAAO,MAAMC,sBAAsB,GACjCjB,SAAS,CAACkB,oBAAV,CAA+BT,aAA/B,KAAiD,IAAjD,GACIV,sBAAsB,CAA0BU,aAA1B,CAD1B,GAEI,MAAM;EACJ,MAAM,IAAIU,KAAJ,CAAUf,aAAV,CAAN;AACD,CALA;AAOP,OAAO,MAAMgB,aAAa,GAAG,MAAM;EACjCtB,SAAS,CAAC,MAAM;IACda,kBAAkB,CAACU,YAAnB,CACEb,qBAAqB,CAACc,wBADxB;IAIA,OAAO,MAAMX,kBAAkB,CAACY,cAAnB,EAAb;EACD,CANQ,EAMN,EANM,CAAT;AAOD,CARM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"names":["useRef","useEffect","useMemo","Animated","Easing","Keyboard","Platform","runOnUI","useAnimatedReaction","useDerivedValue","useSharedValue","useWorkletCallback","withSpring","useReanimatedKeyboardAnimation","AndroidSoftInputModes","KeyboardController","availableOSEventType","OS","defaultAndroidEasing","bezier","useKeyboardAnimationReplica","height","Value","progress","animation","current","setInputMode","SOFT_INPUT_ADJUST_RESIZE","setDefaultMode","listener","addListener","e","timing","toValue","endCoordinates","duration","easing","useNativeDriver","start","remove","IOS_SPRING_CONFIG","damping","stiffness","mass","overshootClamping","restDisplacementThreshold","restSpeedThreshold","useReanimatedKeyboardAnimationReplica","heightEvent","value","handler","_height","_keyboardHeight","result","_previousResult","_previousKeyboardHeight","show","hide","useGradualKeyboardAnimation"],"sources":["replicas.ts"],"sourcesContent":["import { useRef, useEffect, useMemo } from 'react';\nimport { Animated, Easing, Keyboard, Platform } from 'react-native';\nimport {\n runOnUI,\n useAnimatedReaction,\n useDerivedValue,\n useSharedValue,\n useWorkletCallback,\n withSpring,\n} from 'react-native-reanimated';\nimport { useReanimatedKeyboardAnimation } from './animated';\n\nimport { AndroidSoftInputModes, KeyboardController } from './native';\n\nconst availableOSEventType = Platform.OS === 'ios' ? 'Will' : 'Did';\n\n// cubic-bezier(.17,.67,.34,.94)\nexport const defaultAndroidEasing = Easing.bezier(0.4, 0.0, 0.2, 1);\ntype KeyboardAnimation = {\n progress: Animated.Value;\n height: Animated.Value;\n};\n\n/**\n * An experimental implementation of tracing keyboard appearance.\n * Switch an input mode to adjust resize mode. In this case all did* events\n * are triggering before keyboard appears, and using some approximations\n * it tries to mimicries a native transition.\n *\n * @returns {Animated.Value}\n */\nexport const useKeyboardAnimationReplica = (): KeyboardAnimation => {\n const height = useRef(new Animated.Value(0));\n const progress = useRef(new Animated.Value(0));\n const animation = useMemo(\n () => ({\n height: height.current,\n progress: progress.current,\n }),\n []\n );\n\n useEffect(() => {\n KeyboardController.setInputMode(\n AndroidSoftInputModes.SOFT_INPUT_ADJUST_RESIZE\n );\n\n return () => KeyboardController.setDefaultMode();\n }, []);\n useEffect(() => {\n const listener = Keyboard.addListener(\n `keyboard${availableOSEventType}Show`,\n (e) => {\n Animated.timing(height.current, {\n toValue: -e.endCoordinates.height,\n duration: e.duration !== 0 ? e.duration : 300,\n easing: Easing.bezier(0.4, 0.0, 0.2, 1),\n useNativeDriver: true,\n }).start();\n\n return () => listener.remove();\n }\n );\n }, []);\n useEffect(() => {\n const listener = Keyboard.addListener(\n `keyboard${availableOSEventType}Hide`,\n (e) => {\n Animated.timing(height.current, {\n toValue: 0,\n duration: e.duration !== 0 ? e.duration : 300,\n easing: Easing.bezier(0.4, 0.0, 0.2, 1),\n useNativeDriver: true,\n }).start();\n\n return () => listener.remove();\n }\n );\n }, []);\n\n return animation;\n};\n\nconst IOS_SPRING_CONFIG = {\n damping: 500,\n stiffness: 1000,\n mass: 3,\n overshootClamping: true,\n restDisplacementThreshold: 10,\n restSpeedThreshold: 10,\n};\n\n/**\n * A close replica to native iOS keyboard animation. The problem is that\n * iOS (unlike Android) can not fire events for each keyboard frame movement.\n * As a result we can not get gradual values (for example, for progress it always\n * will be 1 or 0). So if you want to rely on gradual values you will need to use\n * this replica.\n *\n * The transition is hardcoded and may vary from one to another OS versions. But it\n * seems like last time it has been changed in iOS 7. Since RN supports at least iOS\n * 11 it doesn't make sense to replicate iOS 7 behavior. If it changes in next OS\n * versions, then this implementation should be revisited and reflect necessary changes.\n *\n * @returns {height, progress} - animated values\n */\nexport const useReanimatedKeyboardAnimationReplica = () => {\n const height = useSharedValue(0);\n const heightEvent = useSharedValue(0);\n\n const progress = useDerivedValue(() => height.value / heightEvent.value);\n\n const handler = useWorkletCallback((_height: number) => {\n heightEvent.value = _height;\n }, []);\n\n useAnimatedReaction(\n () => ({\n _keyboardHeight: heightEvent.value,\n }),\n (result, _previousResult) => {\n const { _keyboardHeight } = result;\n const _previousKeyboardHeight = _previousResult?._keyboardHeight;\n\n if (_keyboardHeight !== _previousKeyboardHeight) {\n height.value = withSpring(_keyboardHeight, IOS_SPRING_CONFIG);\n }\n },\n []\n );\n\n useEffect(() => {\n const show = Keyboard.addListener('keyboardWillShow', (e) => {\n runOnUI(handler)(-e.endCoordinates.height);\n });\n const hide = Keyboard.addListener('keyboardWillHide', () => {\n runOnUI(handler)(0);\n });\n\n return () => {\n show.remove();\n hide.remove();\n };\n }, []);\n\n return { height, progress };\n};\n\nexport const useGradualKeyboardAnimation =\n Platform.OS === 'ios'\n ? useReanimatedKeyboardAnimationReplica\n : useReanimatedKeyboardAnimation;\n"],"mappings":"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"}
|
|
@@ -35,11 +35,9 @@ export declare const useReanimatedKeyboardAnimationReplica: () => {
|
|
|
35
35
|
}>;
|
|
36
36
|
};
|
|
37
37
|
export declare const useGradualKeyboardAnimation: () => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
41
|
-
height: {
|
|
38
|
+
height: import("react-native-reanimated").SharedValue<number>;
|
|
39
|
+
progress: Readonly<{
|
|
42
40
|
value: number;
|
|
43
|
-
}
|
|
41
|
+
}>;
|
|
44
42
|
};
|
|
45
43
|
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-keyboard-controller",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Keyboard manager which works in identical way on both iOS and Android",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
7
7
|
"types": "lib/typescript/index.d.ts",
|
|
@@ -23,8 +23,9 @@
|
|
|
23
23
|
],
|
|
24
24
|
"scripts": {
|
|
25
25
|
"test": "jest",
|
|
26
|
-
"typescript": "tsc --noEmit",
|
|
26
|
+
"typescript": "tsc --noEmit --project tsconfig.build.json",
|
|
27
27
|
"lint": "eslint --quiet \"**/*.{js,ts,tsx}\"",
|
|
28
|
+
"lint-clang": "find ios/ -iname *.h -o -iname *.m -o -iname *.mm | grep -v -e Pods -e build | xargs clang-format -i -n --Werror",
|
|
28
29
|
"prepare": "bob build",
|
|
29
30
|
"release": "release-it",
|
|
30
31
|
"example": "yarn --cwd example",
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
"bugs": {
|
|
45
46
|
"url": "https://github.com/kirillzyusko/react-native-keyboard-controller/issues"
|
|
46
47
|
},
|
|
47
|
-
"homepage": "https://github.
|
|
48
|
+
"homepage": "https://kirillzyusko.github.io/react-native-keyboard-controller/",
|
|
48
49
|
"publishConfig": {
|
|
49
50
|
"registry": "https://registry.npmjs.org/"
|
|
50
51
|
},
|
|
@@ -53,9 +54,10 @@
|
|
|
53
54
|
"@react-native-community/eslint-config": "^2.0.0",
|
|
54
55
|
"@release-it/conventional-changelog": "^2.0.0",
|
|
55
56
|
"@types/jest": "^27.4.1",
|
|
56
|
-
"@types/react": "^
|
|
57
|
-
"@types/react-native": "0.
|
|
57
|
+
"@types/react": "^18.0.17",
|
|
58
|
+
"@types/react-native": "0.69.5",
|
|
58
59
|
"commitlint": "^11.0.0",
|
|
60
|
+
"clang-format": "^1.8.0",
|
|
59
61
|
"eslint": "^7.2.0",
|
|
60
62
|
"eslint-config-prettier": "^7.0.0",
|
|
61
63
|
"eslint-plugin-prettier": "^3.1.3",
|
|
@@ -63,10 +65,10 @@
|
|
|
63
65
|
"jest": "^27.5.1",
|
|
64
66
|
"pod-install": "^0.1.0",
|
|
65
67
|
"prettier": "^2.6.2",
|
|
66
|
-
"react": "
|
|
67
|
-
"react-native": "0.
|
|
68
|
+
"react": "18.0.0",
|
|
69
|
+
"react-native": "0.69.4",
|
|
68
70
|
"react-native-builder-bob": "^0.18.0",
|
|
69
|
-
"react-native-reanimated": "2.
|
|
71
|
+
"react-native-reanimated": "2.9.1",
|
|
70
72
|
"release-it": "^14.2.2",
|
|
71
73
|
"typescript": "^4.6.3"
|
|
72
74
|
},
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2020 The Android Open Source Project
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
-
* you may not use this file except in compliance with the License.
|
|
6
|
-
* You may obtain a copy of the License at
|
|
7
|
-
*
|
|
8
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
*
|
|
10
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
-
* See the License for the specific language governing permissions and
|
|
14
|
-
* limitations under the License.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
package com.reactnativekeyboardcontroller
|
|
18
|
-
|
|
19
|
-
import android.content.Context
|
|
20
|
-
import android.util.Log
|
|
21
|
-
import androidx.core.graphics.Insets
|
|
22
|
-
import androidx.core.view.ViewCompat
|
|
23
|
-
import androidx.core.view.WindowInsetsAnimationCompat
|
|
24
|
-
import androidx.core.view.WindowInsetsCompat
|
|
25
|
-
import com.facebook.react.bridge.Arguments
|
|
26
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
27
|
-
import com.facebook.react.bridge.WritableMap
|
|
28
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
29
|
-
import com.facebook.react.uimanager.UIManagerModule
|
|
30
|
-
import com.facebook.react.views.view.ReactViewGroup
|
|
31
|
-
import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
|
|
32
|
-
import java.util.*
|
|
33
|
-
|
|
34
|
-
fun toDp(px: Float, context: Context): Int = (px / context.resources.displayMetrics.density).toInt()
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* A [WindowInsetsAnimationCompat.Callback] which will translate/move the given view during any
|
|
38
|
-
* inset animations of the given inset type.
|
|
39
|
-
*
|
|
40
|
-
* This class works in tandem with [RootViewDeferringInsetsCallback] to support the deferring of
|
|
41
|
-
* certain [WindowInsetsCompat.Type] values during a [WindowInsetsAnimationCompat], provided in
|
|
42
|
-
* [deferredInsetTypes]. The values passed into this constructor should match those which
|
|
43
|
-
* the [RootViewDeferringInsetsCallback] is created with.
|
|
44
|
-
*
|
|
45
|
-
* @param view the view to translate from it's start to end state
|
|
46
|
-
* @param persistentInsetTypes the bitmask of any inset types which were handled as part of the
|
|
47
|
-
* layout
|
|
48
|
-
* @param deferredInsetTypes the bitmask of insets types which should be deferred until after
|
|
49
|
-
* any [WindowInsetsAnimationCompat]s have ended
|
|
50
|
-
* @param dispatchMode The dispatch mode for this callback.
|
|
51
|
-
* See [WindowInsetsAnimationCompat.Callback.getDispatchMode].
|
|
52
|
-
*/
|
|
53
|
-
class TranslateDeferringInsetsAnimationCallback(
|
|
54
|
-
val view: ReactViewGroup,
|
|
55
|
-
val persistentInsetTypes: Int,
|
|
56
|
-
val deferredInsetTypes: Int,
|
|
57
|
-
dispatchMode: Int = DISPATCH_MODE_STOP,
|
|
58
|
-
val context: ReactApplicationContext?
|
|
59
|
-
) : WindowInsetsAnimationCompat.Callback(dispatchMode) {
|
|
60
|
-
private val TAG = TranslateDeferringInsetsAnimationCallback::class.qualifiedName
|
|
61
|
-
private var persistentKeyboardHeight = 0
|
|
62
|
-
|
|
63
|
-
init {
|
|
64
|
-
require(persistentInsetTypes and deferredInsetTypes == 0) {
|
|
65
|
-
"persistentInsetTypes and deferredInsetTypes can not contain any of " +
|
|
66
|
-
" same WindowInsetsCompat.Type values"
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
override fun onStart(
|
|
71
|
-
animation: WindowInsetsAnimationCompat,
|
|
72
|
-
bounds: WindowInsetsAnimationCompat.BoundsCompat
|
|
73
|
-
): WindowInsetsAnimationCompat.BoundsCompat {
|
|
74
|
-
val keyboardHeight = getCurrentKeyboardHeight()
|
|
75
|
-
val isKeyboardVisible = isKeyboardVisible()
|
|
76
|
-
|
|
77
|
-
if (isKeyboardVisible) {
|
|
78
|
-
// do not update it on hide, since back progress will be invalid
|
|
79
|
-
this.persistentKeyboardHeight = keyboardHeight
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
val params: WritableMap = Arguments.createMap()
|
|
83
|
-
params.putInt("height", keyboardHeight)
|
|
84
|
-
context?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)?.emit("KeyboardController::" + if (!isKeyboardVisible) "keyboardWillHide" else "keyboardWillShow", params)
|
|
85
|
-
|
|
86
|
-
Log.i(TAG, "KeyboardController::" + if (!isKeyboardVisible) "keyboardWillHide" else "keyboardWillShow")
|
|
87
|
-
Log.i(TAG, "HEIGHT:: $keyboardHeight")
|
|
88
|
-
|
|
89
|
-
return super.onStart(animation, bounds)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
override fun onEnd(animation: WindowInsetsAnimationCompat) {
|
|
93
|
-
super.onEnd(animation)
|
|
94
|
-
|
|
95
|
-
val isKeyboardVisible = isKeyboardVisible()
|
|
96
|
-
|
|
97
|
-
val params: WritableMap = Arguments.createMap()
|
|
98
|
-
context?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)?.emit("KeyboardController::" + if (!isKeyboardVisible) "keyboardDidHide" else "keyboardDidShow", params)
|
|
99
|
-
|
|
100
|
-
Log.i(TAG, "KeyboardController::" + if (!isKeyboardVisible) "keyboardDidHide" else "keyboardDidShow")
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private fun isKeyboardVisible(): Boolean {
|
|
104
|
-
val insets = ViewCompat.getRootWindowInsets(view)
|
|
105
|
-
|
|
106
|
-
return insets?.isVisible(WindowInsetsCompat.Type.ime()) ?: false
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
private fun getCurrentKeyboardHeight(): Int {
|
|
110
|
-
val insets = ViewCompat.getRootWindowInsets(view)
|
|
111
|
-
val keyboardHeight = insets?.getInsets(WindowInsetsCompat.Type.ime())?.bottom ?: 0
|
|
112
|
-
val navigationBar = insets?.getInsets(WindowInsetsCompat.Type.navigationBars())?.bottom ?: 0
|
|
113
|
-
|
|
114
|
-
// on hide it will be negative value, so we are using max function
|
|
115
|
-
return Math.max(toDp((keyboardHeight - navigationBar).toFloat(), context!!), 0)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
override fun onProgress(
|
|
119
|
-
insets: WindowInsetsCompat,
|
|
120
|
-
runningAnimations: List<WindowInsetsAnimationCompat>
|
|
121
|
-
): WindowInsetsCompat {
|
|
122
|
-
// onProgress() is called when any of the running animations progress...
|
|
123
|
-
|
|
124
|
-
// First we get the insets which are potentially deferred
|
|
125
|
-
val typesInset = insets.getInsets(deferredInsetTypes)
|
|
126
|
-
// Then we get the persistent inset types which are applied as padding during layout
|
|
127
|
-
val otherInset = insets.getInsets(persistentInsetTypes)
|
|
128
|
-
|
|
129
|
-
// Now that we subtract the two insets, to calculate the difference. We also coerce
|
|
130
|
-
// the insets to be >= 0, to make sure we don't use negative insets.
|
|
131
|
-
val diff = Insets.subtract(typesInset, otherInset).let {
|
|
132
|
-
Insets.max(it, Insets.NONE)
|
|
133
|
-
}
|
|
134
|
-
val diffY = (diff.top - diff.bottom).toFloat()
|
|
135
|
-
val height = toDp(diffY, context!!)
|
|
136
|
-
|
|
137
|
-
var progress = 0.0
|
|
138
|
-
try {
|
|
139
|
-
progress = Math.abs((height.toDouble() / persistentKeyboardHeight))
|
|
140
|
-
} catch (e: ArithmeticException) {
|
|
141
|
-
// do nothing, send progress as 0
|
|
142
|
-
}
|
|
143
|
-
Log.i(TAG, "DiffY: $diffY $height")
|
|
144
|
-
|
|
145
|
-
context
|
|
146
|
-
.getNativeModule(UIManagerModule::class.java)
|
|
147
|
-
?.eventDispatcher
|
|
148
|
-
?.dispatchEvent(KeyboardTransitionEvent(view.id, height, progress))
|
|
149
|
-
|
|
150
|
-
return insets
|
|
151
|
-
}
|
|
152
|
-
}
|