提示:该方式实现的自定义闪屏页已被官方弃用,不推荐使用
官方文档
一开始进入 app 显示的是 theme 主题背景,即
<activity
android:name=".MainActivity"
android:theme="@style/LaunchTheme"
...>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
intent-filter>
activity>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
- "android:windowBackground"
>@drawable/launch_background
style>
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
- "android:windowBackground"
>?android:colorBackground
style>
resources>
接着会开始启动 Flutter 引擎,可在 AndroidManifest.xml 里的启动 Activity 配置
<activity
android:name=".MainActivity"
android:theme="@style/LaunchTheme">
<meta-data-->
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
intent-filter>
activity>
如果自定义该页面,来看 FlutterActivity 启用该页面的流程
public class FlutterActivity extends Activity
implements FlutterActivityAndFragmentDelegate.Host, LifecycleOwner {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
switchLaunchThemeForNormalTheme();
super.onCreate(savedInstanceState);
delegate = new FlutterActivityAndFragmentDelegate(this);
delegate.onAttach(this);
delegate.onRestoreInstanceState(savedInstanceState);
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
configureWindowForTransparency();
// Flutter 在此给 Activity 设置 View
setContentView(createFlutterView());
configureStatusBarForFullscreenFlutterExperience();
}
@NonNull
private View createFlutterView() {
return delegate.onCreateView(
/* inflater=*/ null,
/* container=*/ null,
/* savedInstanceState=*/ null,
/*flutterViewId=*/ FLUTTER_VIEW_ID,
/*shouldDelayFirstAndroidViewDraw=*/ getRenderMode() == RenderMode.surface);
}
}
创建 View 即调用 FlutterActivityAndFragmentDelegate.onCreateView()
class FlutterActivityAndFragmentDelegate implements ExclusiveAppComponent<Activity> {
@NonNull
View onCreateView(...) {
...
// host 即是 FlutterActivity
// delegate = new FlutterActivityAndFragmentDelegate(this);
SplashScreen splashScreen = host.provideSplashScreen();
if (splashScreen != null) {
/// 该警告提示该方式设置闪屏页已经弃用
Log.w(
TAG,
"A splash screen was provided to Flutter, but this is deprecated. See"
+ " flutter.dev/go/android-splash-migration for migration steps.");
FlutterSplashView flutterSplashView = new FlutterSplashView(host.getContext());
flutterSplashView.setId(ViewUtils.generateViewId(FLUTTER_SPLASH_VIEW_FALLBACK_ID));
flutterSplashView.displayFlutterViewWithSplash(flutterView, splashScreen);
return flutterSplashView;
}
if (shouldDelayFirstAndroidViewDraw) {
delayFirstAndroidViewDraw(flutterView);
}
return flutterView;
}
}
所以真正创建 SplashScreen 在 FlutterActivity#provideSplashScreen()
@Nullable
@Override
public SplashScreen provideSplashScreen() {
Drawable manifestSplashDrawable = getSplashScreenFromManifest();
if (manifestSplashDrawable != null) {
return new DrawableSplashScreen(manifestSplashDrawable);
} else {
return null;
}
}
该方法返回一个 SplashScreen 接口对象,所以我们的操作就是在继承 FlutterActivity 的 Activity 复写该方法返回自定义的 SplashScreen
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// 注意:如果要查看 FlutterActivity 层的日志,需要将日志层级设为最低的 VERBOSE
io.flutter.Log.setLogLevel(android.util.Log.VERBOSE);
// 如果 Flutter 启动耗时,则会停留在 第一个 theme 设置的闪屏页
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public SplashScreen provideSplashScreen() {
return new MySplashScreen2();
}
}
public class MySplashScreen implements SplashScreen {
@Nullable
@Override
public View createSplashView(@NonNull Context context, @Nullable Bundle savedInstanceState) {
// 该方法返回自定义闪屏页
return null;
}
@Override
public void transitionToFlutter(@NonNull Runnable onTransitionComplete) {
// 该回调方法执行时机即 Flutter 层初始化完成退出自定义闪屏页
onTransitionComplete.run();
}
}
最后,该方式确实能够实现自定义闪屏页,但由于闪屏页主要用于展示应用启动的过渡,还是不应该用于业务需求,从官方文档已经源码也可以看出。