以下内容参考自flutter_splash_screen插件
Flutter app启动流程
Flutter应用相对于原生app启动,需要额外加载一个Flutter引擎启动过程,大概是如下流程:
原生框架启动 --> Flutter引擎启动 --> Flutter视图
所以,在Flutter app中,启动图的持续时间应该是从原生引擎启动到Flutter视图正式出现的时间。启动图的显示应该是在原生端进行显示,关闭则是Flutter进行。
Flutter端:
- 关闭启动图类封装
import 'package:flutter/services.dart';
class FlutterSplashScreen {
static const MethodChannel _channel = const MethodChannel('flutter_splash_screen');
static Future<Null> hide() async {
await _channel.invokeMethod('hide');
}
}- 在即将显示Flutter视图端地方,关闭启动图:
Future.delayed(const Duration(milliseconds: 500),() {
FlutterSplashScreen.hide();
}
);Android
1. 在Android端实现一个类,封装显示与隐藏启动页方法
大概的思路便是在Activity启动前弹出一个带有启动图的对话框:
```
import android.app.Activity;
import android.app.Dialog;
import android.os.Build;
import java.lang.ref.WeakReference;
public class SplashScreen {
private static Dialog mSplashDialog;
private static WeakReference<Activity> mActivity;
/**
* 打开启动屏
*/
public static void show(final Activity activity, final int themeResId) {
if (activity == null) return;
mActivity = new WeakReference<>(activity);
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (!activity.isFinishing()) {
mSplashDialog = new Dialog(activity, themeResId);
mSplashDialog.setContentView(R.layout.launch_screen);
mSplashDialog.setCancelable(false);
if (!mSplashDialog.isShowing()) {
mSplashDialog.show();
}
}
}
});
}
/**
* 打开启动屏
*/
public static void show(final Activity activity, final boolean fullScreen) {
int resourceId = fullScreen ? R.style.SplashScreen_Fullscreen :
R.style.SplashScreen_SplashTheme;
show(activity, resourceId);
}
/**
* 打开启动屏
*/
public static void show(final Activity activity) {
show(activity, false);
}
/**
* 关闭启动屏
*/
public static void hide(Activity activity) {
if (activity == null) {
if (mActivity == null) {
return;
}
activity = mActivity.get();
}
if (activity == null) return;
final Activity _activity = activity;
_activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (mSplashDialog != null && mSplashDialog.isShowing()) {
boolean isDestroyed = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
isDestroyed = _activity.isDestroyed();
}
if (!_activity.isFinishing() && !isDestroyed) {
mSplashDialog.dismiss();
}
mSplashDialog = null;
}
}
});
}}```
所需的资源文件:
- 启动layout,这里设置启动图资源
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/splash"
android:scaleType="centerCrop" />
</RelativeLayout>- style,这里需要添加windowIsTranslucent属性为true,关闭app启动时的背景
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="SplashScreen_SplashAnimation">
<item name="android:windowExitAnimation">@android:anim/fade_out</item>
</style>
<style name="SplashScreen_SplashTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowAnimationStyle">@style/SplashScreen_SplashAnimation</item>
</style>
<style name="SplashScreen_Fullscreen" parent="SplashScreen_SplashTheme">
<item name="android:windowFullscreen">true</item>
</style>
</resources>2. Android原生层实现启动闪屏页:
在MainActivity onCreate中调用show:
@Override
public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
SplashScreen.show(this,true);
super.onCreate(savedInstanceState, persistentState);
}3. Flutter调用插件实现
- Flutter插件接口封装:
import android.app.Activity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
public class FlutterSplashScreenPlugin implements MethodCallHandler {
private final Activity activity;
private FlutterSplashScreenPlugin(Activity activity) {
this.activity = activity;
}
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(),"flutter_splash_screen");
channel.setMethodCallHandler(new FlutterSplashScreenPlugin(registrar.activity()));
}
@Override
public void onMethodCall(MethodCall methodCall, Result result) {
switch (methodCall.method) {
case "show":
show();
break;
case "hide":
hide();
break;
default:
result.notImplemented();
}
}
/**
* 打开启动屏
*/
private void show() {
SplashScreen.show(activity);
}
/**
* 关闭启动屏
*/
private void hide() {
SplashScreen.hide(activity);
}
}- 在Android MainActivity中注册该插件:
@Overridepublic void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor(),"flutter_splash_screen")
.setMethodCallHandler(
new FlutterSplashScreenPlugin(this)
)
;
}iOS端
研究中...