启动画面

从 Android 12 开始, SplashScreen API 可让应用启动 包含动画,包括启动时的进入应用动作、显示启动画面的启动画面 您的应用图标,以及向应用本身的过渡。SplashScreenWindow和 因此涵盖 Activity

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
图 1.启动画面。

启动画面体验将标准设计元素融入到每个应用中 发布时,该图标也是可自定义的,因此您的应用可以保留其独特的品牌信息。

除了使用 SplashScreen 平台 API 之外,您还可以使用 SplashScreen 用于封装 SplashScreen API 的 compat 库。

启动画面的工作原理

当用户在应用进程未运行(冷启动)时启动应用 start)或 Activity 并非 (即温启动时), 以下事件发生:

  1. 系统会使用主题和您为其指定的所有动画来显示启动画面 定义。

  2. 当应用准备就绪后,系统会关闭启动画面并显示应用。

在浏览器设置期间, 热启动

启动画面的元素和机制

启动画面的元素由 Android 清单文件。每个元素都有浅色模式和深色模式版本。

启动画面的可自定义元素包括应用图标、图标背景和窗口背景:

显示启动画面中包含的元素的图片
图 2. 可自定义的启动画面元素 屏幕。

请考虑以下元素,如图 2 所示:

1 应用图标必须是矢量可绘制对象。它 可以是静态的,也可以是动画形式的。虽然动画的时长可以不受限制,但我们建议不超过 1,000 毫秒。启动器图标是默认的图标。

2 图标背景是可选的,且适用于以下情况: 您需要提高图标和窗口背景之间的对比度。如果您使用 自适应图标 与窗口背景的对比度足够高时显示背景。

3 与自适应图标一样, 前景会被遮盖。

4 窗口背景由不透明的单色组成。如果窗口背景已设置且为纯色,则使用该背景 则默认设置为“0”。

启动画面尺寸

启动画面图标使用的规格与 自适应图标、 如下所示:

  • 品牌图片:尺寸必须为 200×80 dp。
  • 带有图标背景的应用图标:尺寸必须为 240×240 dp,并且适合放在 直径为 160 dp 的圆圈。
  • 无图标背景的应用图标:尺寸必须为 288×288 dp,并且不能超出 直径 192 dp 的圆形。

例如,如果图片的完整尺寸为 300×300 dp,则图标需要位于直径 200 dp 的圆圈内。圆圈外的一切都会转动 不可见(遮盖)。

图片:显示纯色和透明背景的不同图标尺寸
图 3. 以下应用的启动画面图标尺寸 分别设置纯色和透明背景。

启动画面动画和启动序列

额外的延迟时间通常与在冷启动时启动应用有关。为启动画面添加动画图标可带来明显的美感,并且 可提供更优质的体验用户研究表明,感知到的初创公司 动画的时长会更短。

启动画面动画会嵌入到启动序列组件中, 如图 4 所示。

图片显示了 12 个连续帧的启动序列,首先用户点按启动器图标,随着图标的放大而填满整个屏幕
图 4. 启动序列。
  1. 进入动画:包含从系统视图到启动画面的动画。它 由系统控制,不可自定义。

  2. 启动画面(在序列的“等待”部分显示):启动画面 屏幕可自定义,因此您可以提供自己的徽标动画和 品牌塑造。必须符合要求 才能正常运行。

  3. 退出动画:由隐藏启动画面的动画组成。 如果您想对其进行自定义,请使用 SplashScreenView 及其 图标。您可以使用转换设置,在它们上运行任何动画, 不透明度和颜色在这种情况下,请在应用 动画播放完毕。

运行图标动画时,如果应用先前已准备就绪,应用启动功能可让您选择跳过相应序列。该应用会触发 onResume() 或启动画面会自动超时,因此请确保动态效果 轻松跳过启动画面只能通过 onResume() 关闭 当从视觉角度来看应用稳定后,系统不会显示额外的旋转图标 所需的资源。引入不完整的界面可能会给用户带来不快,甚至可能 给人一种难以预测或不够完善的印象。

启动画面动画要求

启动画面必须符合以下规范:

  • 设置不透明的单一窗口背景颜色。昼与夜 模式, SplashScreen 兼容型库

  • 确保动画图标符合以下规范:

    • 格式:图标必须是 AnimatedVectorDrawable (AVD) XML。
    • 尺寸:AVD 图标大小必须是自适应图标大小的四倍 图标,如下所示: <ph type="x-smartling-placeholder">
        </ph>
      • 图标区域必须为 432dp,也就是 未遮盖自适应图标的 108 dp 区域。
      • 图片内部三分之二的内容显示在启动器图标上, 并且必须是 288dp,也就是 构成自适应图标的内部遮罩区域。
    • 时长:我们建议在手机上的时长不超过 1,000 毫秒。您可以使用 延迟启动,但不能超过 166 毫秒。如果应用 启动时间超过 1,000 毫秒,假设使用循环动画。
  • 确定合适的时间来关闭启动画面,这发生在应用绘制第一帧时。您可以按照说明进一步自定义 在关于 让启动画面在屏幕上显示更长时间

启动画面资源

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
图 5.示例 AVD。

下载 入门套件示例, 演示了如何创建动画、设置动画格式以及将动画导出到 AVD。 此软件包包含以下工具:

  • 动画的 Adobe After Effects 项目文件。
  • 最终导出的 AVD XML 文件。
  • 动画的 GIF 示例。

下载这些文件,即表示您同意 Google 服务条款

Google 隐私权政策介绍了此服务如何处理数据。

自定义应用中的启动画面

默认情况下,如果存在以下情况,SplashScreen 会使用主题的 windowBackground windowBackground 是单色。如需自定义启动画面,请添加 属性。

您可以通过执行以下任一操作来自定义应用的启动画面:

  • 设置主题属性以更改其外观。

  • 让其在屏幕上显示更长时间。

  • 自定义用于关闭启动画面的动画。

开始使用

核心 SplashScreen 库为所有用户提供 Android 12 启动画面 搭载 API 级别为 23 的 Android 设备。如需将其添加到您的项目,请将以下代码段添加到 您的 build.gradle 文件:

Groovy

dependencies {
    implementation "androidx.core:core-splashscreen:1.0.0"
}

Kotlin

dependencies {
    implementation("androidx.core:core-splashscreen:1.0.0")
}

设置启动画面的主题以更改其外观

您可以在 Activity 主题中指定以下属性进行自定义 启动画面如果您已有旧版启动画面 使用 android:windowBackground 等属性的实现,不妨考虑 为 Android 12 及更高版本提供备用资源文件。

  1. 使用 windowSplashScreenBackground 以特定的单色填充背景:

    <item name="android:windowSplashScreenBackground">@color/...</item>
    
  2. 使用 windowSplashScreenAnimatedIcon 替换起始窗口中心的图标。

    对于仅以 Android 12(API 级别 32)为目标平台的应用,请执行以下操作:

    如果对象可通过 AnimationDrawableAnimatedVectorDrawable,请将 windowSplashScreenAnimationDuration 设置为 在显示起始窗口的同时播放动画。这不是必填字段 因为对于 Android 13,该时长是直接从 AnimatedVectorDrawable

    <item name="android:windowSplashScreenAnimatedIcon">@drawable/...</item>
    
  3. 使用 windowSplashScreenAnimationDuration 指示启动画面图标动画的时长。设置 不会影响启动画面的实际显示时间 但您可以在自定义启动画面退出时检索该组件 使用 SplashScreenView.getIconAnimationDuration。 请参阅以下部分 让启动画面在屏幕上显示更长时间 了解详情。

    <item name="android:windowSplashScreenAnimationDuration">1000</item>
    
  4. 使用windowSplashScreenIconBackgroundColor 设置启动画面图标后面的背景。 窗口背景与图标之间的对比度不够。

    <item name="android:windowSplashScreenIconBackgroundColor">@color/...</item>
    
  5. 您可以使用 windowSplashScreenBrandingImage 设置要在启动画面底部显示的图片。不过, 不建议使用品牌图片。

    <item name="android:windowSplashScreenBrandingImage">@drawable/...</item>
    
  6. 您可以使用 windowSplashScreenBehavior 指定应用是否始终在 Android 13 及更高版本。默认值为 0, 如果启动 activity 将 splashScreenStyle 设置为 SPLASH_SCREEN_STYLE_ICON, 或遵循系统行为(如果启动的 activity 未指定 样式。如果您希望从不显示空的启动画面, 要显示的动画图标,请将此值设置为 icon_preferred

    <item name="android:windowSplashScreenBehavior">icon_preferred</item>
    

让启动画面在屏幕上显示更长时间

当应用绘制第一帧后,启动画面会立即关闭。如果您 需要加载少量数据,例如从 您可以使用异步方式 ViewTreeObserver.OnPreDrawListener 来挂起应用以绘制其第一帧。

如果您的启动 activity 在绘制之前结束(例如,不是 设置内容视图并在 onResume 之前完成(预绘制) 监听器。

Kotlin

// Create a new event for the activity.
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Set the layout for the content view.
    setContentView(R.layout.main_activity)

    // Set up an OnPreDrawListener to the root view.
    val content: View = findViewById(android.R.id.content)
    content.viewTreeObserver.addOnPreDrawListener(
        object : ViewTreeObserver.OnPreDrawListener {
            override fun onPreDraw(): Boolean {
                // Check whether the initial data is ready.
                return if (viewModel.isReady) {
                    // The content is ready. Start drawing.
                    content.viewTreeObserver.removeOnPreDrawListener(this)
                    true
                } else {
                    // The content isn't ready. Suspend.
                    false
                }
            }
        }
    )
}

Java

// Create a new event for the activity.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Set the layout for the content view.
    setContentView(R.layout.main_activity);

    // Set up an OnPreDrawListener to the root view.
    final View content = findViewById(android.R.id.content);
    content.getViewTreeObserver().addOnPreDrawListener(
            new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    // Check whether the initial data is ready.
                    if (mViewModel.isReady()) {
                        // The content is ready. Start drawing.
                        content.getViewTreeObserver().removeOnPreDrawListener(this);
                        return true;
                    } else {
                        // The content isn't ready. Suspend.
                        return false;
                    }
                }
            });
}

自定义用于关闭启动画面的动画

您可以通过 Activity.getSplashScreen() 进一步自定义启动画面的动画。

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ...

    // Add a callback that's called when the splash screen is animating to the
    // app content.
    splashScreen.setOnExitAnimationListener { splashScreenView ->
        // Create your custom animation.
        val slideUp = ObjectAnimator.ofFloat(
            splashScreenView,
            View.TRANSLATION_Y,
            0f,
            -splashScreenView.height.toFloat()
        )
        slideUp.interpolator = AnticipateInterpolator()
        slideUp.duration = 200L

        // Call SplashScreenView.remove at the end of your custom animation.
        slideUp.doOnEnd { splashScreenView.remove() }

        // Run your animation.
        slideUp.start()
    }
}

Java

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...

    // Add a callback that's called when the splash screen is animating to the
    // app content.
    getSplashScreen().setOnExitAnimationListener(splashScreenView -> {
        final ObjectAnimator slideUp = ObjectAnimator.ofFloat(
                splashScreenView,
                View.TRANSLATION_Y,
                0f,
                -splashScreenView.getHeight()
        );
        slideUp.setInterpolator(new AnticipateInterpolator());
        slideUp.setDuration(200L);

        // Call SplashScreenView.remove at the end of your custom animation.
        slideUp.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                splashScreenView.remove();
            }
        });

        // Run your animation.
        slideUp.start();
    });
}

在此回调开始时, 动画矢量可绘制对象 启动。根据应用启动的时长,可绘制对象可能在其动画的中间。使用 SplashScreenView.getIconAnimationStart 可了解动画何时开始。您可以按如下方式计算图标动画的剩余时长:

Kotlin

// Get the duration of the animated vector drawable.
val animationDuration = splashScreenView.iconAnimationDuration
// Get the start time of the animation.
val animationStart = splashScreenView.iconAnimationStart
// Calculate the remaining duration of the animation.
val remainingDuration = if (animationDuration != null && animationStart != null) {
    (animationDuration - Duration.between(animationStart, Instant.now()))
        .toMillis()
        .coerceAtLeast(0L)
} else {
    0L
}

Java

// Get the duration of the animated vector drawable.
Duration animationDuration = splashScreenView.getIconAnimationDuration();
// Get the start time of the animation.
Instant animationStart = splashScreenView.getIconAnimationStart();
// Calculate the remaining duration of the animation.
long remainingDuration;
if (animationDuration != null && animationStart != null) {
    remainingDuration = animationDuration.minus(
            Duration.between(animationStart, Instant.now())
    ).toMillis();
    remainingDuration = Math.max(remainingDuration, 0L);
} else {
    remainingDuration = 0L;
}

其他资源