ionic-team / capacitor

Build cross-platform Native Progressive Web Apps for iOS, Android, and the Web ⚡️
https://capacitorjs.com
MIT License
12.28k stars 1.01k forks source link

White screen after splash screen #960

Closed oliverandersencox closed 6 years ago

oliverandersencox commented 6 years ago

Capacitor displays my custom splash screen as normal, however it will always display a white screen next, before finally navigating to the first route page. Routing module: const routes: Routes = [ { path: '', redirectTo: '/welcome', pathMatch: 'full' }, { path: 'app', loadChildren: './pages/tabs/tabs.module#TabsPageModule', canActivate: [AuthGuardService] }, { path: 'welcome', loadChildren: './pages/welcome/welcome.module#WelcomePageModule' }, ]

init function from app.ts

`async initializeApp() {

    this.platform.ready().then(async () => {

      try {

        this.statusBarService.setStatusBar('light');

        SplashScreen.hide();

        console.log('App is ready to go!');

      } catch (error) {
        console.log('Capacitor Warn: Some plugins do not yet have web support');
      }
    });
  }`

It is not a nice look for the app. Is there a particular reason it does this? Maybe something to do with the lazy loading?

jcesarmobile commented 6 years ago

The splash screen is configured to dismiss after 3 seconds, so it will disappear and show the webview, which might be white depending on the app.

In next release there will be a new configuration option launchAutoHide that you can set to false to not autohide, so you can manually hide it as in your code https://github.com/ionic-team/capacitor/pull/956

oliverandersencox commented 4 years ago

@jcesarmobile I am still having this issue. My app has this config, yet the white webview always blinks before rendering my initial page. I have created a splash screen page with animation and so this blinking white really ruins the affect!

`{
  "appId": "com.app.ping",
  "appName": "Ping",
  "bundledWebRuntime": false,
  "webDir": "www",
  "server": {
    "allowNavigation": [
      "capacitor://localhost",
      "ionic://localhost",
      "http://localhost",
      "http://localhost:8080",
      "http://localhost:8100"
    ]
  },
  "plugins": {
    "SplashScreen": {
      "launchAutoHide": false,
      "showSpinner": true,
      "androidSplashResourceName": "splash",
      "androidScaleType": "CENTER_CROP",
      "androidSpinnerStyle": "small",
      "iosSpinnerStyle": "small",
      "spinnerColor": "#ffffff",
      "backgroundColor": "#34ace0"
    },
    "PushNotifications": {
      "presentationOptions": [
        "sound"
      ]
    }
  },
  "npmClient": "npm"
}
`
cepages commented 4 years ago

@oliverandersencox did you fix this problem?

laumair commented 4 years ago

Facing the same issue.

oliverandersencox commented 4 years ago

adding "launchShowDuration": 3000 fixed my issue

ulver2812 commented 4 years ago

I had this issue, I tried several configuration with no result. At the end I used this workaround in app.component.ts to avoid the white screen:

this.platform.ready().then(() => {
      setTimeout(() => {
        SplashScreen.hide();
      }, 2000);
}
oliverandersencox commented 4 years ago

@ulver2812 I also ended up going with this solution but 500ms works well

curiouscod3 commented 4 years ago

Doesn't work. still having this issue after splash screen.

nikunjkakadiya3008 commented 4 years ago

still the same issue!! No solution yet?

ShawinMendis commented 4 years ago

Any updates on this. Still the same issue tried all above solutions :)

ccasallas commented 4 years ago

I confirm the same issue on vuejs mobile web app.

JaydipKalkani commented 4 years ago

inside capacitor.config.json file, i changed launchShowDuration property value from 0 to 2000 and FadeSplashScreen property value from 'true' to 'false' and it worked. Below is the complete config file.

{
  "appId": "com.your_app",
  "appName": "Your App name",
  "bundledWebRuntime": false,
  "npmClient": "npm",
  "webDir": "www",
  "plugins": {
    "SplashScreen": {
      "launchShowDuration": 2000
    }
  },
  "cordova": {
    "preferences": {
      "AutoHideSplashScreen": "false",
      "ShowSplashScreen": "true",
      "ShowSplashScreenSpinner": "false",
      "ScrollEnabled": "false",
      "android-minSdkVersion": "19",
      "BackupWebStorage": "none",
      "SplashMaintainAspectRatio": "true",
      "FadeSplashScreenDuration": "300",
      "SplashShowOnlyFirstTime": "false",
      "SplashScreen": "screen",
      "SplashScreenDelay": "3000",
      "FadeSplashScreen": "false",
      "AndroidPersistentFileLocation": "Compatibility"
    }
  }
}
distante commented 4 years ago

Is there an official recommendation for this? I just spend 3 hours trying to fix thinking it was an optimization problem on the angular part but no, everything load in the background but after I call hide() a white screen there before the web view is visible.

tafelnl commented 4 years ago

You could at a background to html like this:

html {
  background: #000; /* or any other color */
}

Try to pick a color that is the same as (or close to) your final background color.

This is more of a workaround than a real fix, but at least it is a little better than a bright white flash in my opinion.

curiouscod3 commented 4 years ago

Is there an official recommendation for this? I just spend 3 hours trying to fix thinking it was an optimization problem on the angular part but no, everything load in the background but after I call hide() a white screen there before the web view is visible.

@distante I had spent more than 24 hours for this. Just gave up.. This must be fixed by the core team !!!

curiouscod3 commented 4 years ago

@jcesarmobile That options don't work for me. I should try 'FadeSplashScreen' option again!

aparajita commented 4 years ago

What's happening is this:

If you call hide when your app is mounted, at that point the web view is fully loaded, but it has not yet performed the first paint. This can take 100 milliseconds or so, so you end up seeing a blank web view briefly.

The solution to add a short delay (200 milliseconds or so) before actually calling SplashScreen.hide().

// At the point at which your app is fully mounted
setTimeout(() => { Splash.hide(); }, 150);
distante commented 4 years ago

What's happening is this:

If you call hide when your app is mounted, at that point the web view is fully loaded, but it has not yet performed the first paint. This can take 100 milliseconds or so, so you end up seeing a blank web view briefly.

The solution to add a short delay (200 milliseconds or so) before actually calling SplashScreen.hide().

// At the point at which your app is fully mounted
setTimeout(() => { Splash.hide(); }, 150);

Uhmm, so using like window.load events could help be more precise if the paint takes too long?

aparajita commented 4 years ago

Good idea! Put this in the main .js file.

document.addEventListener('DOMContentLoaded', async () => {
    const splashscreen = Plugins.SplashScreen as SplashScreenPluginWeb;
    await splashscreen.hide();
});
aparajita commented 4 years ago

Thanks for the tip @distante, I have added hideOnAppLoaded() to my upcoming splash screen plugin, it does this for you.

tafelnl commented 4 years ago

Only using DOMContentLoaded is still not foolproof and could still result in problems.

The most foolproof way would be the following:

  1. Change the background-color of <html>. See: https://github.com/ionic-team/capacitor/issues/960#issuecomment-709215809

  2. Listen to DOMContentLoaded as @aparajita suggested.

  3. Now check if this prevents your app from flickering.

  4. If it does? Nice, you're done. If it does not, you probably have a somewhat heavy app. Read on.

  5. Within the DOMContentLoaded eventlistener, add a setTimeout and just experiment with it, to find a duration that works for you. (Be a little generous. If for example 250ms is perfect for you, use 350ms or so to support low-end devices also)

So in the end you will end up with something like this:

html {
  background: #000; /* or any other color */
}
window.addEventListener('DOMContentLoaded', () => {
  setTimeout(() => {
    SplashScreen.hide({
      fadeOutDuration: 250,
    });
  }, 250); // this could range from 0 to probably no more than 2000, just experiment a little
});
distante commented 4 years ago

What I did was to set an observable in my home page that emits each time my home is checked by angular:

Home Page:

  private componentChecked$$ = new Subject<void>();

  public ngAfterViewChecked(): void {
    this.componentChecked$$.next();
  }

then, I subscribe to it and I wait until it does not emit anything in 100ms (so when it is stable)

  private subscribeToFistEndComponentChecked(): void {
    this.componentChecked$$.pipe(debounceTime(100), first()).subscribe(() => {
      this.globalEvents.emitHomeFinishLoading();
      this.logger.log('End Loading!');
    });
  }

I just hide the splashscreen the first time emitHomeFinishLoading is called. It is not pretty but works all the time. It always wait until the home page is rendered in prod and developer builds for example (with different durations).

As an extra info, I use all my components with changeDetection: ChangeDetectionStrategy.OnPush

aparajita commented 4 years ago

@tafelnl I went back and read the documentation on the DOMContentLoaded event, it turns out the window 'load' event is a better choice, because that is not fire until all dependent resources have been loaded (e.g. stylesheets and images), whereas DOMContentLoaded is fired when only the DOM has been loaded.

hyfydistro commented 2 years ago

You can change the color in capacitor.config with backgroundColor.

{
    "appId": "io.ionic.starter",
    "appName": "app",
    "webDir": "build",
    "bundledWebRuntime": false,
    "backgroundColor": "#ff0000" // <-- here
}

You don't need download the extra package "@capacitor/SplashScreen" lol.

Disclaimers: I'm speaking for Capacitor v3 and Ionic v5

kishan-getstarted commented 2 years ago

I have tried everything its still appears as a white screen can anyone help ?

stylianosnicoletti commented 2 years ago

Same here using ionic 6, capacitor 3.5.1. Large loading time in white screen on Android after splash screen

ionitron-bot[bot] commented 2 years ago

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.