【问题标题】:Ionic & Capacitor - Android Splash Screen ResponsivenessIonic & Capacitor - Android 闪屏响应
【发布时间】:2023-03-14 06:24:01
【问题描述】:

上下文

这与闪屏图像的响应性有关,根据我的研究,它只是因为Capacitor Docs - Splash Screen 缺少文档而发生。

问题

在实现电容器的闪屏插件时出现问题。通常,当您创建整个项目时,此实现是从头开始的。但是,它在具有拉伸纵横比的设备(例如 Google Pixel 2 XL)或具有纵横比的设备(例如例如 iPad Pro)。甚至在某些情况下,初始屏幕图像会四处移动或缩小/展开(在加载时)。

视觉解释

换句话说,本机实现导致启动屏幕图像就像下图一样。如果设备被拉伸或变胖,则不会保留图像纵横比。

【问题讨论】:

  • 感谢您与社区分享此内容的朋友。你拯救了我的一天,我花了很多时间试图解决我的应用程序启动画面的两个问题,一个是状态栏颜色暂时变黑,第二个是徽标以某种方式向上移动。但是,尽管出于其他目的,您的建议解决了我的问题。谢谢!
  • 我在 Capacitor 3 上发现了一个类似的问题,即启动画面仅在几分之一秒内显示扭曲的图像,直到正确显示。我在这里发布了解决方法:*.com/questions/66966453/…
  • @KlemensZleptnig 感谢您的评论 :) 如果我没记错的话,这个问题/答案也解决并解决了您刚才描述的问题。但是,您找到的解决方法 (@null) 非常有趣!
  • 是的,您的解决方案可能也可以解决我描述的问题(尚未测试)。或者换句话说:如果有人实施了您的解决方法,那么我描述的问题一开始就不会发生。所以有点重叠。我现在扩展了我的帖子以显示我使用的配置,并且我也没有调用SplashScreen.show()
  • 它显示 'Plugins' 已弃用.ts,但我看不出有其他方法可以导入它。 :( "@deprecated 为 Capacitor v2 插件提供向后兼容性。Capacitor v3 插件应直接导入插件。此“插件”导出在 v3 中已弃用,将在 v4 中删除。"

标签: android angular ionic-framework splash-screen capacitor


【解决方案1】:

如果您出现两次启动画面(闪烁),请在 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>

【讨论】:

    【解决方案2】:

    如果您使用纯色作为初始屏幕的背景,其他帖子中建议的解决方案可能对您有用,但如果您使用复杂图像(如渐变),则需要了解以下内容:

    如果您想要在您的启动画面和您的应用程序之间无缝过渡,您需要安装@capacitor/splash-screen,因为 Android 的&lt;item name="android:background"&gt;@drawable/splash&lt;/item&gt; 不允许您淡出启动画面,而且当 Android 启动画面被您的Ionic App,在呈现 WebView 时,您将体验到短暂的空白屏幕。

    @capacitor/splash-screen 允许您通过选择自己何时应该隐藏初始屏幕以及淡出应该花费多长时间来缓解这种情况。

    @capacitor/splash-screen 不会替换原生 Android 启动屏幕 &lt;item name="android:background"&gt;@drawable/splash&lt;/item&gt;,而是会在 Ionic 应用打开后(在原生启动屏幕之后)创建一个 Android ImageView,然后淡出到 WebView。

    您可以通过将&lt;item name="android:background"&gt;@null&lt;/item&gt; 设置为原生启动屏幕来隐藏原生Android 启动屏幕以仅使用@capacitor/splash-screen 之一,但这被认为是一种不好的做法,因为它会产生闲逛几个人的错觉每次启动应用的时刻(创建 Ionic 应用并在屏幕上显示所需的时间)。

    最后,如果您希望原生 Android 启动画面覆盖整个屏幕并保持其纵横比,这根本是不可能的(至少对于 Android 11 及更早版本),您只能在后面加上 ImageView该应用程序已启动。

    所以...您可以采取以下措施来缓解这种情况:

    首先,确保原生 Android 启动画面的配置和@capacitor/splash-screen 创建的启动画面相同,这样当从第一个到第二个时,您不会得到“调整大小”。

    然后,您必须将初始屏幕分成 2 层,一层用于背景(可以拉伸以填充视口而不保持其纵横比),另一层用于您的徽标(或其他应该是居中并保持其纵横比)。

    然后,为您的初始屏幕创建一个自定义可绘制对象(即 drawable/launch_splash.xml),这将允许您创建一个包含任意多个图层的初始屏幕(在我们的示例 2 中,一个用于背景,一个用于用于徽标)。

    最后,使用此自定义可绘制对象代替原始启动屏幕。

    这是我所做的完整示例:

    capacitor.config.ts

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

    (确保在对capacitor.config.ts 进行任何更改后重新构建您的应用程序,或自行将更改报告到capacitor.config.json 文件)。

    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);
      }
    
    }
    
    

    【讨论】:

      【解决方案3】:

      所以我们的目标是不要让这些图像被拉伸或变胖。保留标准纵横比图像中的图像。要解决此问题并使启动画面能够响应屏幕设备的天文多样性和宽高比,您必须进行操作:

      • capacitor.config.json(离子项目)
      • app.component.ts(离子项目)
      • styles.xml(Android 项目)

      #1 电容器配置 JSON(离子项目)

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

      #2 应用组件 TS(离子项目)

      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 项目)

      <?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>
      

      就是这样!所有图像现在都保留了纵横比,并且它们将始终响应所有设备。

      参考文献

      【讨论】: