Ionic & Capacitor - Android Splash Screen Responsiveness
Asked Answered
H

5

14

Context

This is related to the splash screen images responsiveness and according to my research it just happens because there is missing documentation at Capacitor Docs - Splash Screen.

Problem

The problem starts when implementing the splash screen plugin of capacitor. Normally this implementation is made from scratch when you create the whole project. However it doesn't/didn't worked well on devices that have a stretched aspect ratio (for example Google Pixel 2 XL) or devices that have fat aspect ratio (for example iPad Pro). There are even some scenarios in which the splash screen image moves around or shrinks/expands (while loading).

Visual Explanation

In other words the native implementation is causing the splash screen images to be just like in the image below. If the devices are stretched or fat the images aspect ratio aren't preserved.

enter image description here

Hooknose answered 19/2, 2021 at 21:54 Comment(7)
Thank you friend for sharing this with the community. You saved my day, I spent a lot of time trying to fix two problems with the splashscreen on my app, one was that the status bar color was temporarily going black and the second one was the logo that in somehow shifts upward. But your recommendations despite for other purposes solved my problems. Thank you!Sluggard
I found a similar issue with Capacitor 3 where the splash screen showed a distorted image only for a fraction of a second until it was shown correctly. I posted the workaround here: #66966953Arellano
@KlemensZleptnig thank you for the comment :) If I am not mistaken this question/answer also addresses and fixes the problem you just described. However the workaround you found for it (@null) is quite interesting!Hooknose
Yes, your solution will probably fix the issue I described as well (haven't tested it). Or put in other words: If one implements your workaround, then the issue I described won't happen in the first place. So it's kind of overlapping. I extended my post now to show the configuration I use and that I don't call SplashScreen.show() as well.Arellano
With this fix I get a distorted image for a second then I get the right aspect ratio.Bicyclic
@Mirko all the code on this post specifically solves the issue you just said. Don't get me wrong, but please double check all the frameworks, code and instructions, run a a new sync and even run a cleanup on the android project. I hope this post helps you!Hooknose
It shows 'Plugins' is deprecated.ts, but I see no other way to import this. :( "@deprecated Provided for backwards compatibility for Capacitor v2 plugins. Capacitor v3 plugins should import the plugin directly. This "Plugins" export is deprecated in v3, and will be removed in v4."Congenial
H
9

So the goal is to not make this images to be stretched or fattened. To preserve the image like in the standard aspect ratio image. To solve this issue and make the splash images become responsive to the astronomic variety of a screen devices and aspect ratios you will have to manipulate:

  • capacitor.config.json (Ionic Project)
  • app.component.ts (Ionic Project)
  • styles.xml (Android Project)

#1 Capacitor Config JSON (Ionic Project)

{
 ...

    "plugins": {
        "SplashScreen": {
            "launchAutoHide": false,
            "androidScaleType": "CENTER_CROP",
            "splashFullScreen": true,
            "splashImmersive": false,
            "backgroundColor": "#ffffff" // YOUR SPLASH SCREEN MAIN COLOR
        }
    }

...
}

#2 App Component TS (Ionic Project)

import { Plugins } from '@capacitor/core'
const { SplashScreen } = Plugins;
...

export class AppComponent implements OnInit {
    ...

    // DON'T USE SPLASHSCREEN SHOW METHOD ANYWHERE
    // SplashScreen.show(); 

    initializeApp() {
        this.platform.ready().then(async () => {
            SplashScreen.hide();
        });
    }
}

#3 Styles.xml (Android Project)

<?xml version="1.0" encoding="utf-8"?>
<resources>
...

    <style name="AppTheme.NoActionBarLaunch" parent="AppTheme.NoActionBar">
        <item name="android:background">@drawable/splash</item>
        <item name="android:windowNoTitle">false</item>
        <item name="android:windowActionBar">false</item>
        <item name="android:windowFullscreen">false</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowIsTranslucent">true</item>
    </style>
<resources>

And that's it! All the images are now with the aspect ratio preserved and they will always be responsive for all devices.

References

Hooknose answered 21/10, 2021 at 9:51 Comment(3)
This was working up to Capacitor 3, now with Capacitor 4 the splash screen gets stretched againBicyclic
I tested some days again. Yes, it happens on Capacitor 4. But only on the android emulators. Build an APK and check if it still happens on a real device.Hooknose
It does, at least on the devices I tested. They changed the API, so I am going to use the 9 patch images, it looks like the most future-proof solution.Bicyclic
R
3

Solutions suggested in other posts may work for you if you use a plain color as the background of your splash screen, but if you use a complex image (like a gradient), here is what you need to know:

If you want a seamless transition between your splashscreen and your app, you need to install @capacitor/splash-screen as the Android <item name="android:background">@drawable/splash</item> will not allow you to fade out the splash screen, furthermore when the Android splash screen is replaced by your Ionic App, you will experience a brief empty screen while the WebView is rendered.

The @capacitor/splash-screen allows you to mitigate this by choosing yourself when the splash-screen should be hidden and how long the fade out should take.

@capacitor/splash-screen does NOT replace the native Android splash screen <item name="android:background">@drawable/splash</item>, instead it create an Android ImageView as soon as the Ionic App is open (after the native Splash Screen) and then fades out to the WebView.

You could hide the native Android splash screen to just use the @capacitor/splash-screen one by setting <item name="android:background">@null</item> for the native splash screen, but this is considered as a bad practice as it will give the illusion of hanging out for a few moment each time you launch your app (the time required for the Ionic App to be created and displayed on screen).

Finally, if you want the native Android splash screen to cover the entire screen and keep its aspect ratio, this is simply not possible (at least with Android 11 and earlier), you can only do this with an ImageView after the app as already booted.

So... Here is what you can do to mitigate this :

First, make sure the config for the native Android splash screen and the splash screen created by @capacitor/splash-screen are the same, so you don't get a "resize" when it goes from the first one to the second one.

Then, you'll have to split you splash screen in 2 layers, one for the background (that can be stretched to fill the viewport without keeping its aspect ratio), and one for your logo (or other element that sould be centered and keep its aspect ratio).

Then, create a custom drawable for your splash screen (i.e. drawable/launch_splash.xml), that will allow you to create a splash screen with as many layers as you want (in our case 2, one for the background, one for the logo).

And finally, use this custom drawable in place of the original splash screen.

Here is a full example of what I did:

capacitor.config.ts

const config: CapacitorConfig = {
  // ...
  plugins: {
    // ...
    SplashScreen: {
      launchAutoHide: false,
      androidSplashResourceName: 'launch_splash',
    },
  },
};

(Make sure you rebuild your app after you make any changes to the capacitor.config.ts or report the changes yourself to the capacitor.config.json file).

android/app/src/main/assets/capacitor.config.json

{
  // ...
  "plugins": {
    // ...
    "SplashScreen": {
      "launchAutoHide": false,
      "androidSplashResourceName": "launch_splash"
    }
  }
}

android/app/src/main/res/values/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

  <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
  </style>

  <style name="AppTheme.NoActionBar" parent="Theme.AppCompat.NoActionBar">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <item name="android:background">@null</item>
  </style>

  <style name="AppTheme.NoActionBarLaunch" parent="AppTheme.NoActionBar">
    <item name="android:background">@drawable/launch_splash</item> <!-- launch_splash -->
  </style>

</resources>

android/app/src/main/res/drawable/launch_splash.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <!-- You can add as many layer as you want as long as they are drawable bitmaps or vectors -->
  <item android:drawable="@drawable/ic_launcher_background"/> <!-- will stretch to exactly match the viewport size -->
  <item android:drawable="@drawable/ic_launcher_foreground" android:gravity="center"/> <!-- will be centered in the viewport without stretching -->
</layer-list>

src/app/tabs/tabs.page.ts

export class TabsPage implements AfterViewInit {

  // ...

  public ngAfterViewInit(): void {
    // Do this in your app landing page
    // You may adjust the timing and wait for any promises or data required by your app,
    // so its fully ready before hiding the splash screen
    // I just added a 100ms delay to help the transition be smooth as it can be quite laggy when your app just finished being rendered
    setTimeout(() => {
      SplashScreen.hide({fadeOutDuration: 300});
    }, 100);
  }

}

Rugose answered 13/10, 2021 at 22:46 Comment(0)
P
2

if you getting splash screen two times (Blinking) try this in style.xml (android)

<item name="android:background">@drawable/splash</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
Pyroconductivity answered 10/6, 2021 at 10:59 Comment(0)
M
2

When I upgraded my app from Capacitor v3 to Capacitor v4 on Android devices the splashscreen got distorted again. What I had to do was creating 9-patch-png files in the drawable-folders (where the image for the splash screen is) instead of the regular png files.

I followed this guide on how to create those files: https://www.joshmorony.com/creating-a-dynamic-universal-splash-screen-for-capacitor-android/

Mcafee answered 13/10, 2022 at 9:47 Comment(0)
F
0

I support Dominik's answer. You just need to create 9-patch-png files and delete your current PNG files.

I used this as reference https://www.joshmorony.com/creating-a-dynamic-universal-splash-screen-for-capacitor-android/

The last part is outdated. You don't need to edit anything else. Just make sure you're using @drawable/splash in your styles.xml.

To easily set the stretchable areas, tick the Show patches box then use the top and left areas outside your image to drag and set the areas to your liking. You should be able to see green and pink areas around your logo but no overlay color on your actual logo.

The top and left areas is used to set the stretchable areas while the bottom and right areas is to set where the content should be contained. You just want to aim for the top and left black borders for this use case.

Florance answered 5/1, 2023 at 6:21 Comment(2)
Feedback: I would have upvoted if this if it was not for the spelling. We are aiming for reference quality material here - please run your posts through a spelling checker if you can.Ahq
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewDissonancy

© 2022 - 2024 — McMap. All rights reserved.