Capacitor.js: az edge-to-edge kikapcsolása Android 15+ alatt

gopher —

Ha Capacitor.js-szel építesz webalkalmazást, és Android 15+-t (API 35) célzol, valószínűleg beleütközöl az edge-to-edge problémába: az alkalmazásod tartalma az állapotsor és a navigációs gombok mögé kerül. Ez a bejegyzés elmagyarázza, mi történik, és hogyan lehet megjavítani.

A probléma

Az Android 15 (és a későbbi verziók) alapértelmezésként kikényszerítik az edge-to-edge megjelenítést. Ez azt jelenti, hogy a WebView a rendszersávok mögé is kinyúlik (felül az állapotsor, alul a navigációs sáv), és az alkalmazásod fejléce és lábléce részben eltakarva végzi.

A mi esetünkben a fejléc gombjait félig takarta az állapotsor, az alsó lapozógombok pedig az Android navigációs gombjai mögé kerültek.

Ami nem működött

Több megközelítést kipróbáltam, mire találtam egyet, ami Android 14-en és 15+-on is megbízhatóan működik:

fitsSystemWindows=true a styles.xml-ben: ez az XML attribútum a témán nem jutott el a Capacitor WebView-ig.

WindowCompat.setDecorFitsSystemWindows(window, true): ez régebben működött, de az Android 15 figyelmen kívül hagyja. Az edge-to-edge kötelező.

setStatusBarColor / setNavigationBarColor: ezek az API 35-ben elavultak. Az Android 15 felülbírálja őket, és a rendszersávokat mindenképpen átlátszóvá teszi.

Ami működött

Két dolog együtt a MainActivity.java-ban:

1. Az ablak háttérszíne

Mivel az Android 15 kikényszeríti az átlátszó rendszersávokat, neked kell irányítanod, mi látszik mögöttük. Ha az ablak háttér drawable-jét az alkalmazásod fejléc-/keretszínére állítod, a rendszersávok mögötti területek nem lesznek fehérek vagy feketék.

2. WindowInsets padding listener

Egy insets listener a content view-n a rendszersávok méreteit paddingként alkalmazza, így a WebView tartalmát beljebb tolja, és semmi sem kerül a sávok mögé.

A kód

package net.dynart.bible;

import android.os.Bundle;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.View;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.graphics.Insets;
import com.getcapacitor.BridgeActivity;

public class MainActivity extends BridgeActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Az ablak hátterének beállítása, hogy az átlátszó rendszersávok mögötti
        // terület az alkalmazás fejlécszínét mutassa fehér/fekete helyett
        getWindow().setBackgroundDrawable(
            new ColorDrawable(Color.parseColor("#3b3f4a"))
        );

        // Padding a rendszersávok insetjei alapján, hogy a tartalom ne kerüljön mögéjük
        View content = findViewById(android.R.id.content);
        ViewCompat.setOnApplyWindowInsetsListener(content, (view, windowInsets) -> {
            Insets insets = windowInsets.getInsets(
                WindowInsetsCompat.Type.systemBars()
            );
            view.setPadding(insets.left, insets.top, insets.right, insets.bottom);
            return WindowInsetsCompat.CONSUMED;
        });
    }
}

A #3b3f4a-t cseréld arra a színre, ami az alkalmazásod keretéhez/fejlécéhez illik.

Opcionális: CSS safe area insetek

A jövőbeli iOS-támogatáshoz CSS safe area paddingot is hozzáadhatsz. Először frissítsd a viewport meta taget:

<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">

Aztán add hozzá a safe area inseteket a fejléchez és a lábléchez:

.app-header {
  padding: calc(12px + env(safe-area-inset-top, 0px)) 20px 12px;
}

.paging-bar {
  padding: 10px 20px calc(10px + env(safe-area-inset-bottom, 0px));
}

Androidon a Java-oldali insets listener az, ami ténylegesen megoldja a problémát. A CSS insetek ott nem csinálnak semmit, mivel a WebView már helyesen van paddingolva, de iOS-en segíteni fognak, ahol nincs natív insets listener.

Összefoglalás

Az Android 15 kikényszeríti az edge-to-edge-et, és elavulttá teszi a rendszersávok színét vezérlő régi API-kat. Capacitor.js alkalmazásoknál a megoldás:

  1. getWindow().setBackgroundDrawable(...): az átlátszó rendszersávok mögötti színt vezérli
  2. ViewCompat.setOnApplyWindowInsetsListener(...): eltolja a content view-t a rendszersávoktól

Nincs elavult API, működik Android 14-en és 15+-on, és nagyjából 10 sor Java.

#android #fejlesztés