cordova-android icon indicating copy to clipboard operation
cordova-android copied to clipboard

When using android:windowSoftInputMode="adjustResize" and env(safe-area-inset-top) in a Cordova app targeting targetSdkVersion 35, the app should behave as before

Open PedroRF123154 opened this issue 7 months ago • 3 comments

Bug Report

Problem

What is expected to happen?

When using android:windowSoftInputMode="adjustResize" and env(safe-area-inset-top) in a Cordova app targeting targetSdkVersion 35, the app should behave as before:

The keyboard should resize the WebView content properly.

The env(safe-area-inset-top) variable should apply correct top padding to accommodate notches/status bar.

What does actually happen?

When targeting SDK 35 (Android 15):

The keyboard behavior (adjustResize) no longer works correctly without applying manual WindowInsets handling.

The CSS variable env(safe-area-inset-top) returns 0px or is ignored in Android WebView, resulting in headers and content being overlapped by the status bar or notch.

A manual workaround using ViewTreeObserver and JavaScript is required to restore proper layout and safe-area behavior.

Information

When targeting SDK 35 (Android 15):

The keyboard behavior (adjustResize) no longer works correctly without applying manual WindowInsets handling.

The CSS variable env(safe-area-inset-top) returns 0px or is ignored in Android WebView, resulting in headers and content being overlapped by the status bar or notch.

A manual workaround using ViewTreeObserver and JavaScript is required to restore proper layout and safe-area behavior.

Command or Code

<activity android:name=".MainActivity" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.AppCompat.Light.NoActionBar">

Environment, Platform, Device

Environment: Cordova + Android

Platform: Android 15 (API 35)

Devices: Multiple (Pixel, Samsung, Xiaomi)

Emulator and physical devices tested

Version information

Solution

  1. Add this Java class to your project: SoftInputAssist.java

This helper listens for keyboard changes and manually adjusts the layout:

** Open SoftInputAssist.java **
package mi.app.cordova;

import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;

public class SoftInputAssist {
    private final View rootView;
    private final View contentView;
    private int previousHeight;

    public SoftInputAssist(Activity activity) {
        rootView = activity.getWindow().getDecorView();
        contentView = activity.findViewById(android.R.id.content);

        rootView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
            Rect r = new Rect();
            rootView.getWindowVisibleDisplayFrame(r);
            int heightDiff = rootView.getHeight() - (r.bottom - r.top);

            if (previousHeight != heightDiff) {
                previousHeight = heightDiff;
                contentView.setPadding(0, 0, 0, heightDiff);
            }
        });
    }
}
** Close SoftInputAssist.java **

2. Call SoftInputAssist from MainActivity.java

Modify your MainActivity like this:
```java
** Open MainActivity.java **
package mi.app.cordova;

import android.os.Bundle;
import org.apache.cordova.*;

public class MainActivity extends CordovaActivity {
    private SoftInputAssist softInputAssist;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // enable Cordova apps to be started in the background
        Bundle extras = getIntent().getExtras();
        if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
            moveTaskToBack(true);
        }

        // Carga el contenido principal de Cordova
        loadUrl(launchUrl);

        // Inicializa el listener para el teclado
        softInputAssist = new SoftInputAssist(this);
    }
}
** Close MainActivity.java **
## Checklist
<!-- Please check the boxes by putting an x in the [ ] like so: [x] -->

- [x] I searched for existing GitHub issues
- [ x] I updated all Cordova tooling to most recent version
- [ x] I included all the necessary information above

PedroRF123154 avatar May 15 '25 11:05 PedroRF123154

The env(safe-area-inset-top) variable should apply correct top padding to accommodate notches/status bar.

The android webview has never correctly handled safe area inset information, even before API 35. (And yes now they are forcing E2E even though it's broken in webviews).

I'd recommend following and +1 https://issues.chromium.org/issues/396827865 so that the chromium/android webview team and properly prioritize the issue and hopefully get an upstream fix sooner than later. This isn't something that Apache Cordova can really resolve.

There are workarounds such as the one that you've suggested, but it looks like it requires manual manipulation of the app template.

I have a plugin that offers a similar workaround: https://github.com/totalpaveinc/cordova-plugin-insets

It however remains un-opinionated, it just provides a way to listen for inset changes in JS. You can use it directly in JS, or map them to custom CSS variables, whatever works best for your application.

Regarding the adjustResize issue, that might be a completely separate issue to the safe area inset issue.

breautek avatar May 15 '25 20:05 breautek

Thanks breautek, I’ve already given a +1 to https://issues.chromium.org/issues/396827865. For now, with this workaround I’ve been able to solve the keyboard issue, but I had to manually fix the header. Thanks again!

PedroRF123154 avatar May 15 '25 20:05 PedroRF123154

Just want to chime in and say

  1. This is a very major issue now that mandatory Edge to Edge is almost upon us. Without some way to access the safe insets it's going to be impossible to ship an acceptable Android app for most use cases.
  2. For now, breautek's plugin is a life-saver (thank you!!!). It was very easy to use it to populate CSS variables for handling the insets appropriately.

jwatmuff avatar Oct 01 '25 06:10 jwatmuff