From d7fe670e893bca8b417cccf840ca7fc83a5ecf25 Mon Sep 17 00:00:00 2001 From: Jon Hieb Date: Thu, 19 Mar 2026 22:07:42 -0500 Subject: [PATCH 1/2] fix(android): reset WebView height when keyboard hides without animation The setOnApplyWindowInsetsListener only called possiblyResizeChildOfContent(true) when the keyboard was showing, but never called possiblyResizeChildOfContent(false) to reset. This meant the WebView height reset relied entirely on WindowInsetsAnimationCompat.Callback.onStart(), which requires an animation. When switching from an app with the keyboard open back to a Capacitor app, Android dismisses the keyboard without an animation. The insets listener detected the keyboard as visible (briefly, from the previous app's IME state) and shrunk the WebView, but the subsequent keyboard dismissal never triggered a reset because no animation fired. This fix passes the actual showingKeyboard state to possiblyResizeChildOfContent() so the insets listener handles both show and hide, matching the behavior already present in the animation callback's onStart(). Fixes #30 --- .../main/java/com/capacitorjs/plugins/keyboard/Keyboard.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/capacitorjs/plugins/keyboard/Keyboard.java b/android/src/main/java/com/capacitorjs/plugins/keyboard/Keyboard.java index e1a2ce5..5c64d51 100644 --- a/android/src/main/java/com/capacitorjs/plugins/keyboard/Keyboard.java +++ b/android/src/main/java/com/capacitorjs/plugins/keyboard/Keyboard.java @@ -60,8 +60,8 @@ public Keyboard(AppCompatActivity activity, boolean resizeOnFullScreen) { ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> { boolean showingKeyboard = ViewCompat.getRootWindowInsets(rootView).isVisible(WindowInsetsCompat.Type.ime()); - if (showingKeyboard && resizeOnFullScreen) { - possiblyResizeChildOfContent(true); + if (resizeOnFullScreen) { + possiblyResizeChildOfContent(showingKeyboard); } return insets; From c0311c497bbd4437d2b442085aa0190cba9a591d Mon Sep 17 00:00:00 2001 From: Jon Hieb Date: Thu, 19 Mar 2026 22:14:17 -0500 Subject: [PATCH 2/2] fix(android): guard against null WindowInsets during teardown ViewCompat.getRootWindowInsets() can return null when the root view is being detached (e.g. during activity destruction). All three call sites in the insets listener and animation callbacks now null-check before calling isVisible(), preventing a NullPointerException. Fixes #51 --- .../com/capacitorjs/plugins/keyboard/Keyboard.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/android/src/main/java/com/capacitorjs/plugins/keyboard/Keyboard.java b/android/src/main/java/com/capacitorjs/plugins/keyboard/Keyboard.java index 5c64d51..7bb39e3 100644 --- a/android/src/main/java/com/capacitorjs/plugins/keyboard/Keyboard.java +++ b/android/src/main/java/com/capacitorjs/plugins/keyboard/Keyboard.java @@ -58,7 +58,9 @@ public Keyboard(AppCompatActivity activity, boolean resizeOnFullScreen) { rootView = content.getRootView(); ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> { - boolean showingKeyboard = ViewCompat.getRootWindowInsets(rootView).isVisible(WindowInsetsCompat.Type.ime()); + WindowInsetsCompat rootInsets = ViewCompat.getRootWindowInsets(rootView); + if (rootInsets == null) return insets; + boolean showingKeyboard = rootInsets.isVisible(WindowInsetsCompat.Type.ime()); if (resizeOnFullScreen) { possiblyResizeChildOfContent(showingKeyboard); @@ -85,8 +87,9 @@ public WindowInsetsAnimationCompat.BoundsCompat onStart( @NonNull WindowInsetsAnimationCompat animation, @NonNull WindowInsetsAnimationCompat.BoundsCompat bounds ) { - boolean showingKeyboard = ViewCompat.getRootWindowInsets(rootView).isVisible(WindowInsetsCompat.Type.ime()); WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(rootView); + if (insets == null) return super.onStart(animation, bounds); + boolean showingKeyboard = insets.isVisible(WindowInsetsCompat.Type.ime()); int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom; DisplayMetrics dm = activity.getResources().getDisplayMetrics(); final float density = dm.density; @@ -106,8 +109,9 @@ public WindowInsetsAnimationCompat.BoundsCompat onStart( @Override public void onEnd(@NonNull WindowInsetsAnimationCompat animation) { super.onEnd(animation); - boolean showingKeyboard = ViewCompat.getRootWindowInsets(rootView).isVisible(WindowInsetsCompat.Type.ime()); WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(rootView); + if (insets == null) return; + boolean showingKeyboard = insets.isVisible(WindowInsetsCompat.Type.ime()); int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom; DisplayMetrics dm = activity.getResources().getDisplayMetrics(); final float density = dm.density;