react-native-keyboard-controller 1.5.1 → 1.5.3

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.
@@ -42,7 +42,7 @@ if (isNewArchitectureEnabled()) {
42
42
  android {
43
43
  compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
44
44
  defaultConfig {
45
- minSdkVersion 16
45
+ minSdkVersion getExtOrIntegerDefault('minSdkVersion')
46
46
  targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
47
47
  versionCode 1
48
48
  versionName "1.0"
@@ -1,5 +1,6 @@
1
1
  KeyboardController_kotlinVersion=1.6.21
2
2
  KeyboardController_compileSdkVersion=33
3
3
  KeyboardController_targetSdkVersion=33
4
+ KeyboardController_minSdkVersion=16
4
5
 
5
6
  android.useAndroidX=true
@@ -9,6 +9,7 @@ import com.facebook.react.viewmanagers.KeyboardControllerViewManagerInterface
9
9
  import com.facebook.react.views.view.ReactViewGroup
10
10
  import com.facebook.react.views.view.ReactViewManager
11
11
  import com.reactnativekeyboardcontroller.managers.KeyboardControllerViewManagerImpl
12
+ import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup
12
13
 
13
14
  class KeyboardControllerViewManager(mReactContext: ReactApplicationContext) : ReactViewManager(), KeyboardControllerViewManagerInterface<ReactViewGroup> {
14
15
  private val manager = KeyboardControllerViewManagerImpl(mReactContext)
@@ -26,12 +27,12 @@ class KeyboardControllerViewManager(mReactContext: ReactApplicationContext) : Re
26
27
 
27
28
  @ReactProp(name = "statusBarTranslucent")
28
29
  override fun setStatusBarTranslucent(view: ReactViewGroup, value: Boolean) {
29
- return manager.setStatusBarTranslucent(view, value)
30
+ return manager.setStatusBarTranslucent(view as EdgeToEdgeReactViewGroup, value)
30
31
  }
31
32
 
32
33
  @ReactProp(name = "navigationBarTranslucent")
33
34
  override fun setNavigationBarTranslucent(view: ReactViewGroup, value: Boolean) {
34
- return manager.setNavigationBarTranslucent(view, value)
35
+ return manager.setNavigationBarTranslucent(view as EdgeToEdgeReactViewGroup, value)
35
36
  }
36
37
 
37
38
  override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
@@ -156,7 +156,7 @@ class KeyboardAnimationCallback(
156
156
  // then we need to reset the state
157
157
  InteractiveKeyboardProvider.shown = false
158
158
  }
159
- val isKeyboardVisible = isKeyboardVisible || isKeyboardShown
159
+ isKeyboardVisible = isKeyboardVisible || isKeyboardShown
160
160
 
161
161
  this.emitEvent("KeyboardController::" + if (!isKeyboardVisible) "keyboardDidHide" else "keyboardDidShow", getEventParams(this.persistentKeyboardHeight))
162
162
  this.sendEventToJS(KeyboardTransitionEvent(view.id, "topKeyboardMoveEnd", this.persistentKeyboardHeight, if (!isKeyboardVisible) 0.0 else 1.0))
@@ -1,69 +1,21 @@
1
1
  package com.reactnativekeyboardcontroller.managers
2
2
 
3
- import android.util.Log
4
- import androidx.appcompat.widget.FitWindowsLinearLayout
5
- import androidx.core.view.ViewCompat
6
- import androidx.core.view.WindowInsetsAnimationCompat
7
- import androidx.core.view.WindowInsetsCompat
8
3
  import com.facebook.react.bridge.ReactApplicationContext
9
4
  import com.facebook.react.common.MapBuilder
10
5
  import com.facebook.react.uimanager.ThemedReactContext
11
- import com.facebook.react.views.view.ReactViewGroup
12
- import com.reactnativekeyboardcontroller.KeyboardAnimationCallback
13
- import com.reactnativekeyboardcontroller.R
14
- import com.reactnativekeyboardcontroller.extensions.requestApplyInsetsWhenAttached
15
6
  import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup
16
7
 
17
8
  class KeyboardControllerViewManagerImpl(private val mReactContext: ReactApplicationContext) {
18
- private val TAG = KeyboardControllerViewManagerImpl::class.qualifiedName
19
- private var isStatusBarTranslucent = false
20
- private var isNavigationBarTranslucent = false
21
-
22
- fun createViewInstance(reactContext: ThemedReactContext): ReactViewGroup {
23
- val view = EdgeToEdgeReactViewGroup(reactContext)
24
- val activity = reactContext.currentActivity
25
-
26
- if (activity == null) {
27
- Log.w(TAG, "Can not setup keyboard animation listener, since `currentActivity` is null")
28
- return view
29
- }
30
-
31
- val callback = KeyboardAnimationCallback(
32
- view = view,
33
- persistentInsetTypes = WindowInsetsCompat.Type.systemBars(),
34
- deferredInsetTypes = WindowInsetsCompat.Type.ime(),
35
- // We explicitly allow dispatch to continue down to binding.messageHolder's
36
- // child views, so that step 2.5 below receives the call
37
- dispatchMode = WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE,
38
- context = reactContext,
39
- onApplyWindowInsetsListener = { v, insets ->
40
- val content =
41
- reactContext.currentActivity?.window?.decorView?.rootView?.findViewById<FitWindowsLinearLayout>(
42
- R.id.action_bar_root,
43
- )
44
- content?.setPadding(
45
- 0,
46
- if (this.isStatusBarTranslucent) 0 else insets?.getInsets(WindowInsetsCompat.Type.systemBars())?.top ?: 0,
47
- 0,
48
- if (this.isNavigationBarTranslucent) 0 else insets?.getInsets(WindowInsetsCompat.Type.navigationBars())?.bottom ?: 0,
49
- )
50
-
51
- insets
52
- },
53
- )
54
- ViewCompat.setWindowInsetsAnimationCallback(view, callback)
55
- ViewCompat.setOnApplyWindowInsetsListener(view, callback)
56
- view.requestApplyInsetsWhenAttached()
57
-
58
- return view
9
+ fun createViewInstance(reactContext: ThemedReactContext): EdgeToEdgeReactViewGroup {
10
+ return EdgeToEdgeReactViewGroup(reactContext)
59
11
  }
60
12
 
61
- fun setStatusBarTranslucent(view: ReactViewGroup, isStatusBarTranslucent: Boolean) {
62
- this.isStatusBarTranslucent = isStatusBarTranslucent
13
+ fun setStatusBarTranslucent(view: EdgeToEdgeReactViewGroup, isStatusBarTranslucent: Boolean) {
14
+ view.setStatusBarTranslucent(isStatusBarTranslucent)
63
15
  }
64
16
 
65
- fun setNavigationBarTranslucent(view: ReactViewGroup, isNavigationBarTranslucent: Boolean) {
66
- this.isNavigationBarTranslucent = isNavigationBarTranslucent
17
+ fun setNavigationBarTranslucent(view: EdgeToEdgeReactViewGroup, isNavigationBarTranslucent: Boolean) {
18
+ view.setNavigationBarTranslucent(isNavigationBarTranslucent)
67
19
  }
68
20
 
69
21
  fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
@@ -1,12 +1,70 @@
1
1
  package com.reactnativekeyboardcontroller.views
2
2
 
3
3
  import android.annotation.SuppressLint
4
+ import android.util.Log
5
+ import androidx.appcompat.widget.FitWindowsLinearLayout
6
+ import androidx.core.view.ViewCompat
4
7
  import androidx.core.view.WindowCompat
8
+ import androidx.core.view.WindowInsetsAnimationCompat
9
+ import androidx.core.view.WindowInsetsCompat
5
10
  import com.facebook.react.uimanager.ThemedReactContext
6
11
  import com.facebook.react.views.view.ReactViewGroup
12
+ import com.reactnativekeyboardcontroller.KeyboardAnimationCallback
13
+ import com.reactnativekeyboardcontroller.R
14
+ import com.reactnativekeyboardcontroller.extensions.requestApplyInsetsWhenAttached
7
15
 
8
16
  @SuppressLint("ViewConstructor")
9
17
  class EdgeToEdgeReactViewGroup(private val reactContext: ThemedReactContext) : ReactViewGroup(reactContext) {
18
+ private val TAG = EdgeToEdgeReactViewGroup::class.qualifiedName
19
+ private var isStatusBarTranslucent = false
20
+ private var isNavigationBarTranslucent = false
21
+
22
+ init {
23
+ val activity = reactContext.currentActivity
24
+
25
+ if (activity != null) {
26
+
27
+ val callback = KeyboardAnimationCallback(
28
+ view = this,
29
+ persistentInsetTypes = WindowInsetsCompat.Type.systemBars(),
30
+ deferredInsetTypes = WindowInsetsCompat.Type.ime(),
31
+ // We explicitly allow dispatch to continue down to binding.messageHolder's
32
+ // child views, so that step 2.5 below receives the call
33
+ dispatchMode = WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE,
34
+ context = reactContext,
35
+ onApplyWindowInsetsListener = { v, insets ->
36
+ val content =
37
+ reactContext.currentActivity?.window?.decorView?.rootView?.findViewById<FitWindowsLinearLayout>(
38
+ R.id.action_bar_root,
39
+ )
40
+ content?.setPadding(
41
+ 0,
42
+ if (this.isStatusBarTranslucent) {
43
+ 0
44
+ } else {
45
+ insets?.getInsets(WindowInsetsCompat.Type.systemBars())?.top
46
+ ?: 0
47
+ },
48
+ 0,
49
+ if (this.isNavigationBarTranslucent) {
50
+ 0
51
+ } else {
52
+ insets?.getInsets(WindowInsetsCompat.Type.navigationBars())?.bottom
53
+ ?: 0
54
+ },
55
+ )
56
+
57
+ insets
58
+ },
59
+ )
60
+ ViewCompat.setWindowInsetsAnimationCallback(this, callback)
61
+ ViewCompat.setOnApplyWindowInsetsListener(this, callback)
62
+ this.requestApplyInsetsWhenAttached()
63
+ } else {
64
+ Log.w(TAG, "Can not setup keyboard animation listener, since `currentActivity` is null")
65
+ }
66
+ }
67
+
10
68
  override fun onAttachedToWindow() {
11
69
  super.onAttachedToWindow()
12
70
 
@@ -17,4 +75,12 @@ class EdgeToEdgeReactViewGroup(private val reactContext: ThemedReactContext) : R
17
75
  )
18
76
  }
19
77
  }
78
+
79
+ fun setStatusBarTranslucent(isStatusBarTranslucent: Boolean) {
80
+ this.isStatusBarTranslucent = isStatusBarTranslucent
81
+ }
82
+
83
+ fun setNavigationBarTranslucent(isNavigationBarTranslucent: Boolean) {
84
+ this.isNavigationBarTranslucent = isNavigationBarTranslucent
85
+ }
20
86
  }
@@ -3,26 +3,26 @@ package com.reactnativekeyboardcontroller
3
3
  import com.facebook.react.bridge.ReactApplicationContext
4
4
  import com.facebook.react.uimanager.ThemedReactContext
5
5
  import com.facebook.react.uimanager.annotations.ReactProp
6
- import com.facebook.react.views.view.ReactViewGroup
7
6
  import com.facebook.react.views.view.ReactViewManager
8
7
  import com.reactnativekeyboardcontroller.managers.KeyboardControllerViewManagerImpl
8
+ import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup
9
9
 
10
10
  class KeyboardControllerViewManager(mReactContext: ReactApplicationContext) : ReactViewManager() {
11
11
  private val manager = KeyboardControllerViewManagerImpl(mReactContext)
12
12
 
13
13
  override fun getName(): String = KeyboardControllerViewManagerImpl.NAME
14
14
 
15
- override fun createViewInstance(reactContext: ThemedReactContext): ReactViewGroup {
15
+ override fun createViewInstance(reactContext: ThemedReactContext): EdgeToEdgeReactViewGroup {
16
16
  return manager.createViewInstance(reactContext)
17
17
  }
18
18
 
19
19
  @ReactProp(name = "statusBarTranslucent")
20
- fun setStatusBarTranslucent(view: ReactViewGroup, isStatusBarTranslucent: Boolean) {
20
+ fun setStatusBarTranslucent(view: EdgeToEdgeReactViewGroup, isStatusBarTranslucent: Boolean) {
21
21
  manager.setStatusBarTranslucent(view, isStatusBarTranslucent)
22
22
  }
23
23
 
24
24
  @ReactProp(name = "navigationBarTranslucent")
25
- fun setNavigationBarTranslucent(view: ReactViewGroup, isNavigationBarTranslucent: Boolean) {
25
+ fun setNavigationBarTranslucent(view: EdgeToEdgeReactViewGroup, isNavigationBarTranslucent: Boolean) {
26
26
  manager.setNavigationBarTranslucent(view, isNavigationBarTranslucent)
27
27
  }
28
28
 
@@ -42,6 +42,7 @@ public class KeyboardMovementObserver: NSObject {
42
42
  private var prevKeyboardPosition = 0.0
43
43
  private var displayLink: CADisplayLink?
44
44
  private var keyboardHeight: CGFloat = 0.0
45
+ private var hasKVObserver = false
45
46
 
46
47
  @objc public init(
47
48
  handler: @escaping (NSString, NSNumber, NSNumber) -> Void,
@@ -82,18 +83,40 @@ public class KeyboardMovementObserver: NSObject {
82
83
  name: UIWindow.didBecomeVisibleNotification,
83
84
  object: nil
84
85
  )
86
+ NotificationCenter.default.addObserver(
87
+ self,
88
+ selector: #selector(windowDidBecomeHidden),
89
+ name: UIWindow.didBecomeHiddenNotification,
90
+ object: nil
91
+ )
92
+ }
93
+
94
+ @objc func windowDidBecomeHidden(_: Notification) {
95
+ removeKVObserver()
85
96
  }
86
97
 
87
98
  @objc func windowDidBecomeVisible(_: Notification) {
88
- let keyboardView = findKeyboardView()
99
+ setupKVObserver()
100
+ }
89
101
 
90
- if keyboardView == _keyboardView {
102
+ private func setupKVObserver() {
103
+ if hasKVObserver {
91
104
  return
92
105
  }
93
106
 
94
- _keyboardView = keyboardView
107
+ if keyboardView != nil {
108
+ hasKVObserver = true
109
+ keyboardView?.addObserver(self, forKeyPath: "center", options: .new, context: nil)
110
+ }
111
+ }
112
+
113
+ private func removeKVObserver() {
114
+ if !hasKVObserver {
115
+ return
116
+ }
95
117
 
96
- keyboardView?.addObserver(self, forKeyPath: "center", options: .new, context: nil)
118
+ hasKVObserver = false
119
+ keyboardView?.removeObserver(self, forKeyPath: "center", context: nil)
97
120
  }
98
121
 
99
122
  // swiftlint:disable:next block_based_kvo
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-keyboard-controller",
3
- "version": "1.5.1",
3
+ "version": "1.5.3",
4
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",