Flutter 闪屏页实现

提示:该方式实现的自定义闪屏页已被官方弃用,不推荐使用
官方文档

一开始进入 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();
    }
}

最后,该方式确实能够实现自定义闪屏页,但由于闪屏页主要用于展示应用启动的过渡,还是不应该用于业务需求,从官方文档已经源码也可以看出。

你可能感兴趣的:(flutter,android)