diff --git a/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt b/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt index 6276b1b9ff..1cf0afba22 100644 --- a/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +++ b/android/src/fabric/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt @@ -18,17 +18,27 @@ class KeyboardControllerViewManager( private val manager = KeyboardControllerViewManagerImpl(mReactContext) private val mDelegate = KeyboardControllerViewManagerDelegate(this) - override fun getDelegate(): ViewManagerDelegate = mDelegate - - override fun getName(): String = KeyboardControllerViewManagerImpl.NAME + override fun createViewInstance(context: ThemedReactContext): ReactViewGroup { + return manager.createViewInstance(context) + } - override fun createViewInstance(context: ThemedReactContext): ReactViewGroup = manager.createViewInstance(context) + override fun invalidate() { + super.invalidate() + manager.invalidate() + } override fun onAfterUpdateTransaction(view: ReactViewGroup) { super.onAfterUpdateTransaction(view) manager.setEdgeToEdge(view as EdgeToEdgeReactViewGroup) } + override fun onDropViewInstance(view: ReactViewGroup) { + super.onDropViewInstance(view) + manager.onDropViewInstance(view as EdgeToEdgeReactViewGroup) + } + // endregion + + // region Props setters @ReactProp(name = "statusBarTranslucent") override fun setStatusBarTranslucent( view: ReactViewGroup, @@ -52,7 +62,14 @@ class KeyboardControllerViewManager( view: ReactViewGroup, value: Boolean, ) = manager.setEnabled(view as EdgeToEdgeReactViewGroup, value) + // endregion + // region Getters override fun getExportedCustomDirectEventTypeConstants(): MutableMap = manager.getExportedCustomDirectEventTypeConstants() + + override fun getDelegate(): ViewManagerDelegate = mDelegate + + override fun getName(): String = KeyboardControllerViewManagerImpl.NAME + // endregion } diff --git a/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt b/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt index 0155d1fa1b..700a115a74 100644 --- a/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt +++ b/android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt @@ -10,13 +10,8 @@ import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.UIManagerHelper import com.facebook.react.uimanager.events.Event import com.facebook.react.uimanager.events.EventDispatcher -import com.reactnativekeyboardcontroller.listeners.WindowDimensionListener import com.reactnativekeyboardcontroller.log.Logger -fun ThemedReactContext.setupWindowDimensionsListener() { - WindowDimensionListener(this) -} - fun ThemedReactContext?.dispatchEvent( viewId: Int, event: Event<*>, diff --git a/android/src/main/java/com/reactnativekeyboardcontroller/listeners/WindowDimensionListener.kt b/android/src/main/java/com/reactnativekeyboardcontroller/listeners/WindowDimensionListener.kt index 982c960d98..beee8e81b7 100644 --- a/android/src/main/java/com/reactnativekeyboardcontroller/listeners/WindowDimensionListener.kt +++ b/android/src/main/java/com/reactnativekeyboardcontroller/listeners/WindowDimensionListener.kt @@ -1,6 +1,7 @@ package com.reactnativekeyboardcontroller.listeners import android.view.ViewGroup +import android.view.ViewTreeObserver import com.facebook.react.bridge.Arguments import com.facebook.react.uimanager.ThemedReactContext import com.reactnativekeyboardcontroller.extensions.content @@ -16,8 +17,9 @@ class WindowDimensionListener( private val context: ThemedReactContext?, ) { private var lastDispatchedDimensions = Dimensions(0.0, 0.0) + private var layoutListener: ViewTreeObserver.OnGlobalLayoutListener? = null - init { + public fun attachListener() { // attach to content view only once per app instance if (context != null && listenerID != context.hashCode()) { listenerID = context.hashCode() @@ -26,12 +28,19 @@ class WindowDimensionListener( updateWindowDimensions(content) - content?.viewTreeObserver?.addOnGlobalLayoutListener { - updateWindowDimensions(content) - } + layoutListener = + ViewTreeObserver.OnGlobalLayoutListener { + updateWindowDimensions(content) + } + + content?.viewTreeObserver?.addOnGlobalLayoutListener(layoutListener) } } + public fun detachListener() { + context?.content?.viewTreeObserver?.removeOnGlobalLayoutListener(layoutListener) + } + private fun updateWindowDimensions(content: ViewGroup?) { if (content == null) { return diff --git a/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt b/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt index c1d6656720..c138fcfb52 100644 --- a/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt +++ b/android/src/main/java/com/reactnativekeyboardcontroller/managers/KeyboardControllerViewManagerImpl.kt @@ -7,14 +7,27 @@ import com.reactnativekeyboardcontroller.events.FocusedInputLayoutChangedEvent import com.reactnativekeyboardcontroller.events.FocusedInputSelectionChangedEvent import com.reactnativekeyboardcontroller.events.FocusedInputTextChangedEvent import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent +import com.reactnativekeyboardcontroller.listeners.WindowDimensionListener import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup @Suppress("detekt:UnusedPrivateProperty") class KeyboardControllerViewManagerImpl( mReactContext: ReactApplicationContext, ) { - fun createViewInstance(reactContext: ThemedReactContext): EdgeToEdgeReactViewGroup = - EdgeToEdgeReactViewGroup(reactContext) + + private var listener : WindowDimensionListener? = null + + fun createViewInstance(reactContext: ThemedReactContext): EdgeToEdgeReactViewGroup { + if (listener == null) { + listener = WindowDimensionListener(reactContext) + listener?.attachListener() + } + return EdgeToEdgeReactViewGroup(reactContext) + } + + fun invalidate() { + listener?.detachListener() + } fun setEnabled( view: EdgeToEdgeReactViewGroup, @@ -70,6 +83,11 @@ class KeyboardControllerViewManagerImpl( return map } + fun onDropViewInstance(view: EdgeToEdgeReactViewGroup) { + view.setActive(false) + view.removeWindowInsetsListener() + } + companion object { const val NAME = "KeyboardControllerView" } diff --git a/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt b/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt index 2374868a41..b0dfc9fbdb 100644 --- a/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt +++ b/android/src/main/java/com/reactnativekeyboardcontroller/views/EdgeToEdgeReactViewGroup.kt @@ -15,7 +15,6 @@ import com.reactnativekeyboardcontroller.extensions.content import com.reactnativekeyboardcontroller.extensions.removeSelf import com.reactnativekeyboardcontroller.extensions.requestApplyInsetsWhenAttached import com.reactnativekeyboardcontroller.extensions.rootView -import com.reactnativekeyboardcontroller.extensions.setupWindowDimensionsListener import com.reactnativekeyboardcontroller.listeners.KeyboardAnimationCallback import com.reactnativekeyboardcontroller.listeners.KeyboardAnimationCallbackConfig import com.reactnativekeyboardcontroller.log.Logger @@ -51,7 +50,6 @@ class EdgeToEdgeReactViewGroup( private val modalAttachedWatcher = ModalAttachedWatcher(this, reactContext, config, ::getKeyboardCallback) init { - reactContext.setupWindowDimensionsListener() tag = VIEW_TAG } @@ -124,6 +122,13 @@ class EdgeToEdgeReactViewGroup( } } + fun removeWindowInsetsListener() { + val rootView = reactContext.rootView + if (rootView != null) { + ViewCompat.setOnApplyWindowInsetsListener(rootView, null) + } + } + fun setEdgeToEdge() { val nextValue = active || isPreservingEdgeToEdge diff --git a/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt b/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt index 4352cf7f2a..4e89be20ae 100644 --- a/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt +++ b/android/src/paper/java/com/reactnativekeyboardcontroller/KeyboardControllerViewManager.kt @@ -5,6 +5,7 @@ import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.annotations.ReactProp import com.facebook.react.views.view.ReactViewGroup import com.facebook.react.views.view.ReactViewManager +import com.reactnativekeyboardcontroller.listeners.WindowDimensionListener import com.reactnativekeyboardcontroller.managers.KeyboardControllerViewManagerImpl import com.reactnativekeyboardcontroller.views.EdgeToEdgeReactViewGroup @@ -13,16 +14,28 @@ class KeyboardControllerViewManager( ) : ReactViewManager() { private val manager = KeyboardControllerViewManagerImpl(mReactContext) - override fun getName(): String = KeyboardControllerViewManagerImpl.NAME + // region Lifecycle + override fun createViewInstance(context: ThemedReactContext): ReactViewGroup { + return manager.createViewInstance(context) + } - override fun createViewInstance(reactContext: ThemedReactContext): EdgeToEdgeReactViewGroup = - manager.createViewInstance(reactContext) + override fun invalidate() { + super.invalidate() + manager.invalidate() + } override fun onAfterUpdateTransaction(view: ReactViewGroup) { super.onAfterUpdateTransaction(view) manager.setEdgeToEdge(view as EdgeToEdgeReactViewGroup) } + override fun onDropViewInstance(view: ReactViewGroup) { + super.onDropViewInstance(view) + manager.onDropViewInstance(view as EdgeToEdgeReactViewGroup) + } + // endregion + + // region Props setters @ReactProp(name = "enabled") fun setEnabled( view: EdgeToEdgeReactViewGroup, @@ -54,7 +67,12 @@ class KeyboardControllerViewManager( ) { manager.setPreserveEdgeToEdge(view, isPreservingEdgeToEdge) } + // endregion + // region Getters override fun getExportedCustomDirectEventTypeConstants(): MutableMap = manager.getExportedCustomDirectEventTypeConstants() + + override fun getName(): String = KeyboardControllerViewManagerImpl.NAME + // endregion }