向应用添加启动页(闪屏页)

Add Splash Screen Header

闪屏页(也称为启动页)是你的应用在启动时给用户的第一印象。它们就像是你的应用的基础,同时允许你在它展示的时间里,加载你的引擎和初始化你的应用。本指南将展示如何在 Flutter 编写的移动应用中恰当地使用闪屏页。

iOS 启动页

所有应用在交付到 Apple 应用商店之前 必须使用 Xcode storyboard 以提供应用启动页面。

默认的 Flutter 模板包括一个名为 LaunchScreen.storyboard 的 Xcode storyboard,可以根据您的选择进行定制你自己的资源。默认情况下,storyboard 将显示空白图像,但你可以修改它。在项目根目录下执行 open ios/Runner.xcworkspace 打开 Flutter 应用程序的 Xcode 项目。然后从项目导航器中选择 Runner/Assets.xcassets,并将所需图像拖拽至 LaunchImage 图像集中。

Apple 在 人机接口指南 部分中为发布启动页提供了详细的指南。

Android 启动页

在 Android 中,你有两个可以分开控制的页面:在 Android 应用初始化时的 启动页,以及在 Flutter 初始化时的 闪屏页

应用初始化

所有 Android 应用在操作系统准备应用进程时都需要一定的初始化时间。因此 Android 提供了 启动界面 的概念,在应用初始化的时候显示 Drawable

默认的 Flutter 项目模板定义了启动主题和启动背景。你可以在 styles.xml 中自定义一个主题,将一个 Drawable 配置给该主题的 windowBackground,它将作为启动页被展示。

<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
    <item name="android:windowBackground">@drawable/launch_background</item>
</style>

定义一个普通主题

此外,在 styles.xml 中定义一个 普通主题,当启动页消失后,它会应用在 FlutterActivity 上。普通主题的背景仅仅展示非常短暂的时间,例如,当启动页消失后、设备方向改变或者 Activity 恢复期间。因此建议普通主题的背景颜色使用与 Flutter UI 主要背景颜色相似的纯色。

<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
    <item name="android:windowBackground">@drawable/normal_background</item>
</style>

在 AndroidManifest.xml 中配置 FlutterActivity

AndroidManifest.xml 中,将 FlutterActivitytheme 设置为启动主题,将元数据元素添加到所需的 FlutterActivity,以知会 Flutter 在适当的时机从启动主题切换到普通主题。

<activity
    android:name=".MyActivity"
    android:theme="@style/LaunchTheme"
    // ...
    >
    <meta-data
        android:name="io.flutter.embedding.android.NormalTheme"
        android:resource="@style/NormalTheme"
        />
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

如此一来,Android 应用程序就会在在初始化时展示对应的启动页面。

Android S

请先查看 Android 闪屏页面 了解如何在 Android S 上配置闪屏页。

从 Android S 开始,你必须在你的 styles.xml 文件中使用新的闪屏 API 了。你需要考虑为 Android 12 和更高版本创建一个备用的资源文件,还要确保你的背景图片符合图标指南。查看文档 Android 闪屏页面 了解更多。

<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
    <item name="android:windowSplashScreenBackground">@color/bgColor</item>
    <item name="android:windowSplashScreenAnimatedIcon">@drawable/launch_background</item>
</style>

确保 io.flutter.embedding.android.SplashScreenDrawable 未在 manifest 中设置,且 provideSplashScreen 也没有具体实现,这些 API 已被废弃。如此一来 Android 的闪屏页可以在应用启动时平滑过渡到 Flutter。

某些应用可能希望在 Flutter 中继续显示 Android 闪屏页的最后一帧。例如,保持一帧的展示,同时 Dart 继续加载其他内容。想达到这样的效果,以下 API 可能有帮助:

import android.os.Build;
import android.os.Bundle;
import android.window.SplashScreenView;
import androidx.core.view.WindowCompat;
import io.flutter.embedding.android.FlutterActivity;

public class MainActivity extends FlutterActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Aligns the Flutter view vertically with the window.
        WindowCompat.setDecorFitsSystemWindows(getWindow(), false);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            // Disable the Android splash screen fade out animation to avoid
            // a flicker before the similar frame is drawn in Flutter.
            getSplashScreen()
                .setOnExitAnimationListener(
                    (SplashScreenView splashScreenView) -> {
                        splashScreenView.remove();
                    });
        }

        super.onCreate(savedInstanceState);
    }
}
import android.os.Build
import android.os.Bundle
import androidx.core.view.WindowCompat
import io.flutter.embedding.android.FlutterActivity

class MainActivity : FlutterActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    // Aligns the Flutter view vertically with the window.
    WindowCompat.setDecorFitsSystemWindows(getWindow(), false)

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
      // Disable the Android splash screen fade out animation to avoid
      // a flicker before the similar frame is drawn in Flutter.
      splashScreen.setOnExitAnimationListener { splashScreenView -> splashScreenView.remove() }
    }

    super.onCreate(savedInstanceState)
  }
}

然后你可以重新实现 Flutter 的第一帧,将元素摆放在与 Android 闪屏页相同的位置。关于这个的示例,请参考 Android 闪屏页示例应用