Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug(android): overlaying status bar does not affect safe area insets #2840

Closed
1 of 4 tasks
diachedelic opened this issue Apr 28, 2020 · 20 comments
Closed
1 of 4 tasks

Comments

@diachedelic
Copy link
Contributor

diachedelic commented Apr 28, 2020

Bug Report

Capacitor Version

npx cap doctor output:

$ npx cap doctor
💊 Capacitor Doctor 💊

Latest Dependencies:

@capacitor/cli: 2.0.1

@capacitor/core: 2.0.1

@capacitor/android: 2.0.1

@capacitor/electron: 2.0.1

@capacitor/ios: 2.0.1

Installed Dependencies:

@capacitor/electron not installed

@capacitor/cli 2.0.1

@capacitor/core 2.0.1

@capacitor/android 2.0.1

@capacitor/ios 2.0.1

[success] Android looking great! 👌
Found 10 Capacitor plugins for ios:
@mauron85/cordova-plugin-background-geolocation (3.1.0)
capacitor-data-storage-sqlite (2.0.0-1)
capacitor-voice-recorder (0.0.9)
cordova-plugin-android-permissions (1.0.2)
cordova-plugin-app-version (0.1.9)
cordova-plugin-file (6.0.2)
cordova-plugin-file-transfer (1.7.1)
cordova-plugin-screen-orientation (3.0.2)
cordova-plugin-whitelist (1.3.4)
es6-promise-plugin (4.2.2)
[success] iOS looking great! 👌

Affected Platform(s)

  • Android
  • iOS
  • Electron
  • Web

Current Behavior

On iOS, I leave space for the iPhone X notch & iPhone 6 status bar using <meta name="viewport" content="viewport-fit=cover" /> along with env(safe-area-inset-top), as described in #2100 .

I would love to do the same thing in Android, however it appears that overlaying the status bar via StatusBar.setOverlaysWebView({ overlay: true }) does not affect env(safe-area-inset-top) in the CSS. env(safe-area-inset-*) has officially been supported since Chrome 69 (announcement) though how extensively I don't know.

Expected Behavior

I would expect env(safe-area-inset-top) to include the height of the status bar if it is overlaid.

Reproduction Steps

    // Display content under transparent status bar (Android only)
    StatusBar.setOverlaysWebView({
      overlay: true
    });

Other Technical Details

npm --version output: 6.14.4

node --version output: v12.16.1

Other Information

If fixing env(safe-area-inset-top) is not possible, I would be satisfied being able to access the safe area insets via a Plugin, or injected CSS variables (e.g. --android-safe-area-inset-top or similar).

@jcesarmobile
Copy link
Member

Looks like despite they implemented, it doesn't work, it always returns 0. so this is a Chromium bug, not a Capacitor bug.

For getting the safe areas, that seems to be possible on SDK 29+, so could be added in some plugin (Status Bar maybe?), so closing as feature request.

Issues tagged with feature request are closed but tracked for👍 reactions to gauge interest.

@nkCreation
Copy link

Hi there, do you have any information on this ? Thank you !

@Cyral
Copy link

Cyral commented Dec 2, 2020

Has anyone figured this out? Looking for how to overlay content behind the status bar (so the color of it matches the content), but push the content down so that it isn't actually behind the status bar. Seems like ion-toolbar needs the safe area padding on top but its always 0.

@haschu
Copy link

haschu commented Dec 21, 2020

Same issue here! @Cyral have you been successful yet?

@Cyral
Copy link

Cyral commented Dec 22, 2020

@haschu Nope. Tons of apps do this, seems very common - but still haven't found a way with Capacitor/Ionic

@haschu
Copy link

haschu commented Jan 4, 2021

@MVDeveloper1
Copy link

Nothing yet?

@c4b4d4
Copy link

c4b4d4 commented Mar 16, 2021

Is there any workaround for this issue?

@aolsx
Copy link

aolsx commented Mar 22, 2021

I had the same problem

@igorcd
Copy link

igorcd commented Mar 26, 2021

I'm developing a plugin that sends the device insets, at the moment works only on android, and send only top, its for a emergency.
https://www.npmjs.com/package/capacitor-insets-plugin

const { StatusBar, InsetsPlugin } = Plugins;

StatusBar.setOverlaysWebView({ overlay: true });
StatusBar.setStyle({ style: StatusBarStyle.Dark });

InsetsPlugin.top()
    .then((resp: { value: number }) => {
        document.documentElement.style.setProperty('--top-inset', `${resp.value}px`);
    });

@aolsx
Copy link

aolsx commented Apr 28, 2021

It's not settled yet?

@jurij
Copy link

jurij commented May 10, 2021

coming back to this issue after a year. any idea what the recommended way to handle this issue is?

@Cyral
Copy link

Cyral commented May 10, 2021

Apparently it's actually an issue on the Android webview side. Tracking it here: https://bugs.chromium.org/p/chromium/issues/detail?id=1094366 Of course whenever this does get fixed there will be a ton of devices no longer receiving manufacturer updates that will never get it.

@shajidhasan
Copy link

No workaround yet?

@Cyral
Copy link

Cyral commented Aug 2, 2021

I ended up making my own workaround but it's hacky and somewhat complicated.

In onCreate in your MainActivity, make the app draw behind the system status bar and nav bar: (and make them transparent)

    // Use a transparent status bar and nav bar, and place the window behind the status bar
    // and nav bar. Due to a chromium bug, we need to get the height of both bars
    // and add it to the safe area insets. The native plugin is used to get this info.
    // See https://bugs.chromium.org/p/chromium/issues/detail?id=1094366
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
      getWindow().setDecorFitsSystemWindows(false);
      getWindow().setStatusBarColor(0);
      getWindow().setNavigationBarColor(0);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
      // On older versions of android setDecorFitsSystemWindows doesn't exist yet, but it can
      // be emulated with flags.
      // It still must be P or greater, as that is the min version for getting the insets
      // through the native plugin.
      getWindow().getDecorView().setSystemUiVisibility(
              View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
                      View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
                      View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
      getWindow().setStatusBarColor(0);
      getWindow().setNavigationBarColor(0);
    }

Then I use a plugin to get the display insets:

    @PluginMethod
    public void getDisplayInsets(PluginCall call) {
        Activity activity = getBridge().getActivity();
        Window window = activity.getWindow();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            // See https://bugs.chromium.org/p/chromium/issues/detail?id=1094366, which is
            // the bug that makes getting the display inset necessary.
            final WindowInsets cutout = window.getDecorView().getRootWindowInsets();
            final float density = activity.getResources().getDisplayMetrics().density;

            JSObject ret = new JSObject();
            ret.put("top", cutout.getStableInsetTop() / density);
            ret.put("bottom", cutout.getStableInsetBottom() / density);
            call.resolve(ret);
        }
    }

And set the safe area to the insets upon startup in index.tsx: (Native is the name of the plugin I created for this)

    if (isPlatform('android')) {
        Native.getDisplayInsets().then(i => {
            const style = document.documentElement.style;
            style.setProperty('--ion-safe-area-top', i.top + 'px');
            style.setProperty('--ion-safe-area-bottom', i.bottom + 'px');
        });
    }

Lastly, ion-modals (without a top header) don't seem to respect the safe area, so I had to add the following to my CSS:

ion-modal {
  --ion-content-scroll-safe-area: var(--ion-safe-area-bottom, 0);
}

ion-content::part(scroll) {
  margin-bottom: calc(var(--ion-content-scroll-safe-area, 0));
}

Once the Chromium bug is fixed, only the CSS part should be needed. That part appears to be a bug in ionic.

@lincolnthree
Copy link

lincolnthree commented Oct 31, 2021

I believe this also results in keyboard height getting calculated incorrectly on Android devices with a top notch.

@Cyral any chance you could share your plugin? (Edit: I found this plugin which seems to do what's required - https://github.com/capacitor-community/safe-area)

@antonioberetini
Copy link

This has nothing to do with Safe Area, this should be handled with Android default behavior for as you can find here: https://github.com/razir/MoviesInsetsDemo. Safe area should be used only for the web, where a native approach should be used inside of the WebView. Both navigation and the status bar should use this Android API since Android manufacturers handle notches and navigation bars differently and they all use this Android standardized approach. Our team will contribute to Capacitor with this fix please feel free to review and merge.

@F0rsaken
Copy link

I published a plugin, based on other peoples repos, to get the value of status bar, regardless if it's ionic bug or chromium.

https://github.com/owlsdepartment/capacitor-plugin-android-insets

@heliomarpm
Copy link

this problem is easily solved by adding in app.module imports.

IonicModule.forRoot({_forceStatusbarPadding: true})

A demo in Cordova to be seen here

@ionitron-bot
Copy link

ionitron-bot bot commented Nov 19, 2022

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Capacitor, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Nov 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests