Skip to content

fix(android): implement automatic edge-to-edge and universal keyboard handling#8366

Open
fabiomartino wants to merge 7 commits intoionic-team:mainfrom
fabiomartino:fix/safe-area_edge2edge
Open

fix(android): implement automatic edge-to-edge and universal keyboard handling#8366
fabiomartino wants to merge 7 commits intoionic-team:mainfrom
fabiomartino:fix/safe-area_edge2edge

Conversation

@fabiomartino
Copy link

@fabiomartino fabiomartino commented Mar 1, 2026

Summary

This PR implements a fix for the SystemBars plugin on Android that resolves the issue where too much bottom safe area is displayed when the keyboard is visible.

Issues Addressed

  • #8329: Too much bottom safe area when keyboard is visible
  • #8181: Incorrect visualViewport/innerHeight values on Android < 15
  • #8287: System Bar safe-area-inset-x ignores Keyboard state

Key Changes

  1. Universal keyboard handling: IME visibility is now monitored on all Android versions (not just 15+)
  2. Stable top insets: Uses getInsetsIgnoringVisibility for status bar and cutout to prevent page jumping during keyboard transitions
  3. Zero bottom safe area on keyboard: For modern WebViews (>= 140), --safe-area-inset-bottom is set to 0 when keyboard is visible
  4. WebView version detection: Detects WebView version to apply appropriate handling
  5. Legacy fallback: Older WebViews (< 140) use native bottom margin adjustment

Behavior

WebView >= 140

  • CSS variables --safe-area-inset-* are injected with correct values
  • --safe-area-inset-bottom = 0 when keyboard is visible
  • No native margin applied to parent view

WebView < 140 (Legacy/Broken)

  • Native bottom margin applied to parent view
  • CSS --safe-area-inset-bottom forced to 0 to avoid double-offset with fixed footers
  • More aggressive inset handling to compensate for WebView bugs

Keyboard State

  • When keyboard is visible, bottom inset is correctly set to 0
  • This restores the stable behavior from Capacitor 8.0.1

Configuration

Default configuration works automatically:

plugins: {
  SystemBars: {
    insetsHandling: 'css',  // 'css' | 'disable'
    style: 'DARK',          // 'DARK' | 'LIGHT' | 'DEFAULT'
  },
}

Technical Details

  • Minimum Android SDK: API 21 (Android 5.0 Lollipop)
  • Compatible with Capacitor 7 and 8
  • Uses reflection to gracefully handle cases where EdgeToEdge class is not available

Testing

Tested on:

  • Android 14 (API 34)
  • Android 13 (API 33)
  • Android 12 (API 31)
  • Android 11 (API 30)
  • WebView >= 140 - CSS safe-area approach
  • WebView < 140 - native margin fallback

Breaking Changes

None. This is a bug fix that maintains existing behavior while fixing the keyboard bottom area issue.

Migration

No migration required. Existing configurations continue to work.

@derWebdesigner
Copy link

@fabiomartino Thank you so much Fabio. This is such a crucial fix I'm waiting for. 🙏

@theproducer theproducer self-assigned this Mar 2, 2026
@aeharding
Copy link

This does not appear to solve #8329. Reproduction: https://github.com/aeharding/cap-kb-blank-space/tree/fabio

@fabiomartino
Copy link
Author

fabiomartino commented Mar 8, 2026

This does not appear to solve #8329. Reproduction: https://github.com/aeharding/cap-kb-blank-space/tree/fabio

Hi @aeharding give it a try...

// REMOVED

@aeharding
Copy link

Unfortunately it is the same problem for me. Have you tried with my reproduction?

@fabiomartino
Copy link
Author

fabiomartino commented Mar 8, 2026

Hi @aeharding, thank you for the feedback and for providing the reproduction repo.

While we couldn't replicate the exact "blank space" behavior in our specific local environment, we performed a deep dive into the logic changes between Capacitor 8.0.1 and 8.0.2. We identified that the 8.0.2
regression introduced a safe-area calculation that incorrectly includes system bar insets even when the keyboard (IME) is visible. On modern WebViews (v140+), this results in "double padding" because the WebView
viewport already resizes to account for the keyboard.

We have refined the SystemBars.java implementation with the following improvements:

  1. Stable Top Insets: We now use getInsetsIgnoringVisibility for the status bar and cutout. This prevents the top of the page from "sliding" or jumping under the status bar during keyboard transitions.
  2. Zero Bottom Safe Area on Keyboard: For modern WebViews (>= 140), we force --safe-area-inset-bottom to 0px when the keyboard is visible, effectively restoring the stable behavior from v8.0.1 while maintaining
    Edge-to-Edge support.
  3. Legacy Fallback: We kept the native bottomMargin adjustment specifically for older WebViews (< 140) that cannot handle Edge-to-Edge keyboard resizing via CSS alone.
  4. Universal API Support: Maintained automatic EdgeToEdge activation via reflection for Android 5.0+ (API 21).

Could you please try testing with this updated version of SystemBars.java?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants