ionic-team / capacitor-plugins

Official plugins for Capacitor ⚡️
532 stars 598 forks source link

`StatusBar.setOverlaysWebView({ overlay: true })` alongside SplashScreen glitches on Android API 33 (Android 13) #1160

Open jbouchard24 opened 2 years ago

jbouchard24 commented 2 years ago

Bug Report

Plugin(s)

Capacitor Version

   Capacitor Doctor   

Latest Dependencies:

  @capacitor/cli: 4.1.0
  @capacitor/core: 4.1.0
  @capacitor/android: 4.1.0
  @capacitor/ios: 4.1.0

Installed Dependencies:

  @capacitor/ios: not installed
  @capacitor/cli: 4.1.0
  @capacitor/android: 4.1.0
  @capacitor/core: 4.1.0

[success] Android looking great! 👌

Platform(s)

Current Behavior

I have an app that uses the StatusBar.setOverlaysWebView({ overlay: true }) feature from the StatusBar plugin, alongside the SplashScreen plugin. When opening the app on Android API 33 (Android 13) from home screen or app drawer, the status bar is opaque and the webview stretches underneath the navigation/gesture bar. That is not the case on Android API 31 (Android 12) or earlier, or when opening the app from settings > Apps or long-pressing the app icon > App Info > Open. (See Additional context for more info)

Current behavior on Android API 33 (Android 13):

image

Expected Behavior

I expect a behavior like Android API 31 (Android 12) and earlier, where the app is using the space underneath a transparent status bar and the bottom doesn't stretch past the gesture bar when calling StatusBar.setOverlaysWebView({ overlay: true }):

image

Code Reproduction

Example repo

Additional Context

Here some of the tests I made. Hopefully it helps isolate the issue.

Working: ✅

Not working: ❌

Ionitron commented 2 years ago

This issue may need more information before it can be addressed. In particular, it will need a reliable Code Reproduction that demonstrates the issue.

Please see the Contributing Guide for how to create a Code Reproduction.

Thanks! Ionitron 💙

jbouchard24 commented 2 years ago

Code Repro has been updated from a list of steps to an example repo

nikitalpopov commented 2 years ago

@jbouchard24 I've got the same issue and this fix seems to work in this case. This part in particular:

MainActivity.kt:

import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen

class MainActivity : BridgeActivity() {
  public override fun onCreate(savedInstanceState: Bundle?) {
    registerPlugins(
      // ...
    )
    super.onCreate(savedInstanceState)
    // This line fixes the issue:
    val splashScreen = installSplashScreen()
  }
}
jbouchard24 commented 2 years ago

@nikitalpopov Thanks for the reply, but it's not working in my project.

I have been suggested to make changes to the status bar in a setTimeout after hiding the splash screen. I don't like the fix, but at least it's working in my case:

await SplashScreen.hide();
setTimeout(async () => {
    await StatusBar.setOverlaysWebView({ overlay: true });
}, 500);
mpmua commented 1 year ago

setTimeout(async () => { await StatusBar.setOverlaysWebView({ overlay: true }); }, 500);

Yes after a ton of googling and whatnot this is what i've had to resort to aswell, my issue was with StatusBar.setBackgroundColor not setting the correct statusbar color on app launch (the statusbar background is supposed to be white or black depending on whether the user last chose dark or light theme for the app, and when the user toggles themes in the app the statusbar background color changes between white and black just fine), putting a settimeout to occur 250ms after the splashscreen is hidden did the trick, feels a bit hacky and i was still looking for a proper fix but it doesn't look like there is one so this will have to do.

sam-higgs commented 1 year ago

Still an issue for me with version 5.0.6

aacassandra commented 10 months ago

tested on ionic/vue very clean

  onMounted(() => {
    Device.getInfo().then((info) => {
      if (info.platform !== 'web') {
        SplashScreen.hide().then(() => {
          setTimeout(() => {
            StatusBar.setOverlaysWebView({ overlay: true })
          }, 100)
        })
      }
    })
  })

with capacitor.config.ts

  import { CapacitorConfig } from '@capacitor/cli'

const config: CapacitorConfig = {
  appId: 'io.ionic.starter',
  appName: 'E-Kampoeng',
  webDir: 'dist',
  server: {
    androidScheme: 'https',
  },
  plugins: {
    SplashScreen: {
      launchShowDuration: 30000,
      // launchAutoHide: true,
      launchFadeOutDuration: 900,
      backgroundColor: '#ffffffff',
      // androidSplashResourceName: 'splash',
      // androidScaleType: 'CENTER_CROP',
      showSpinner: false,
      androidSpinnerStyle: 'small',
      iosSpinnerStyle: 'small',
      spinnerColor: '#999999',
      splashFullScreen: true,
      splashImmersive: true,
      layoutName: 'launch_screen',
      // useDialog: true,
    },
  },
}

export default config
haily2706 commented 10 months ago

Still an issue for me with version 5.0.6, react/ionic - I tried all proposed approach above? it did not work with my project. Has anyone solved this issue? please give me a hint to overcome it or when this issue will be fixed. Thank you!

prdjed commented 9 months ago

Using Angular here, best solution I found is to set splashscreen duration to some reasonable time:

SplashScreen:{    
      launchShowDuration:2300
  },

and in my app.component.ts:

this.platform.ready().then(()=>{     
     setTimeout(async()=>{
      await StatusBar.setOverlaysWebView({ overlay: true });
    },2300)
    })

it works every time. And it is better than doing it with this approach:

await SplashScreen.hide();
   setTimeout(async () => {
   await StatusBar.setOverlaysWebView({ overlay: true });
}, 500);

,because this way you will have blank white screen for short amount of time between splashscreen and app home screen.

Dayonel commented 9 months ago

@nikitalpopov Thanks for the reply, but it's not working in my project.

I have been suggested to make changes to the status bar in a setTimeout after hiding the splash screen. I don't like the fix, but at least it's working in my case:

await SplashScreen.hide();
setTimeout(async () => {
    await StatusBar.setOverlaysWebView({ overlay: true });
}, 500);

thank you so much!!

mleister97 commented 6 months ago

The issue still does exist, all methods of StatusBar are affected.

The following solution is working for me:

capacitor.config.ts

/// <reference types="@capacitor/splash-screen" />

import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  ...
  plugins: {
    SplashScreen: {
      launchShowDuration: 1000,
    }
  }

Call any methods of StatusBar after the specified launchShowDuration:

setTimeout(() => {
  if (Capacitor.isPluginAvailable('StatusBar')) {
    StatusBar.setBackgroundColor({ color: '#001358'}).then().catch()
    StatusBar.setStyle({ style: Style.Dark }).then().catch()
  }
}, 1000)

I am using `"@capacitor/status-bar": "^5.0.6",

dimeloper commented 5 months ago

Just FYI the issue still exists on "@capacitor/status-bar": "6.0.0". It took me 2 days to find this github issue and try out the suggested timeout, equal to the launchShowDuration that finally makes it work for me too. Maybe until a proper fix is introduced this "workaround" should also be included in the documentation of the status-bar plugin.

Mimateam commented 2 months ago

The issue still exists. Currently, the only solution is to use setTimeout. I am using "@capacitor/status-bar": "^5.0.8".

Timeswitch commented 16 hours ago

Same issue, struggled to get the Splashscreen only to deal with this :)