From 8cf162fe0f172e62066192f6d2b307b50174603c Mon Sep 17 00:00:00 2001 From: Marco Birchler Date: Wed, 16 Sep 2026 13:52:14 +0200 Subject: [PATCH] fix(android): do not pad the WebView for the IME below API 30 On API 29 the window is already resized by the system when the keyboard opens (windowSoftInputMode="adjustResize"), and WindowInsetsCompat can only approximate the ime() inset there. SystemBars additionally applied that approximated height as bottom padding, so the WebView was shrunk twice and collapsed to a few hundred pixels whenever WebView >= 140 and viewport-fit=cover were in use. After a rotation with the keyboard open the stale padding stuck until the app was restarted. Only apply the IME padding on API 30+, where ime() reports the real overlap. Verified on a Huawei MAR-LX1A (Android 10, WebView 152): window.innerHeight with the keyboard open is now 442 instead of 141 CSS px, and rotating with the keyboard open no longer leaves the WebView stuck. Behaviour on API 30+ is unchanged. Fixes #8601 Co-Authored-By: Claude Fable 5.1 --- .../main/java/com/getcapacitor/plugin/SystemBars.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java b/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java index 8b9de8849..208d6f1b7 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java +++ b/android/capacitor/src/main/java/com/getcapacitor/plugin/SystemBars.java @@ -4,6 +4,7 @@ import android.content.pm.PackageInfo; import android.content.res.Configuration; import android.content.res.Resources; +import android.os.Build; import android.util.TypedValue; import android.view.View; import android.view.Window; @@ -196,10 +197,14 @@ private void initWindowInsetsListener() { Insets systemBarsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout()); Insets imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime()); boolean keyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); + // Below API 30 the window is already resized by the system for the IME (adjustResize) and + // WindowInsetsCompat can only approximate the IME inset, so padding for it as well would + // shrink the WebView twice. See https://github.com/ionic-team/capacitor/issues/8601 + boolean padForIme = keyboardVisible && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R; if (shouldPassthroughInsets) { // We need to correct for a possible shown IME - v.setPadding(0, 0, 0, keyboardVisible ? imeInsets.bottom : 0); + v.setPadding(0, 0, 0, padForIme ? imeInsets.bottom : 0); WindowInsetsCompat newInsets = new WindowInsetsCompat.Builder(insets) .setInsets( @@ -223,7 +228,7 @@ private void initWindowInsetsListener() { systemBarsInsets.left, systemBarsInsets.top, systemBarsInsets.right, - keyboardVisible ? imeInsets.bottom : systemBarsInsets.bottom + padForIme ? imeInsets.bottom : systemBarsInsets.bottom ); // Returning `WindowInsetsCompat.CONSUMED` breaks recalculation of safe area insets