您现在的位置是:首页 >技术教程 >Android,原生启动页面和Flutter Splash页面存在偏差问题解决网站首页技术教程
Android,原生启动页面和Flutter Splash页面存在偏差问题解决
Android,原生启动页面和Flutter Splash页面存在偏差问题解决
项目一直存在一个比较尴尬的问题:就是点击应用程序时,原生启动页和Flutter加载页明明用的是同一张图片,但是每次启动的时候总是会存在偏差,图片中间的Logo在Flutter页面中相对于Android原生的页面往往会上移一些,这个其实挺蠢的= =说的夸张一点就给用户一种,应用闪退重启过了的感觉。
之前一直给各种各样的托词,说是什么Flutter对于图片的处理和原生不同等等等等…但是最近还是决定彻底解决这个问题。
我们项目启动后马上就跳转到FlutterBoostActivity了,然后FlutterBoostActivity是通过在AndroidManifests.xml配置文件里为自己对应的Activity标签中添加如下子标签来设置Acitivity启动背景的。
<meta-data android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/splash_bg"/>
然后FlutterActivity在getSplashScreenFromManifest方法中获取到对应的资源Id,依次转换成
Drawable->DrawableSplashScreen->FlutterSplashView。其中DrawableSplashScreen继承自SplashScreen,
然后FlutterSplashView最后作为启动视图显示到具体页面。
标题提及的问题出在Drawable->DrawableSplashScreen的转换。
FlutterActivity:
@Nullable
@Override
public SplashScreen provideSplashScreen() {
Drawable manifestSplashDrawable = getSplashScreenFromManifest();
if (manifestSplashDrawable != null) {
return new DrawableSplashScreen(manifestSplashDrawable);
} else {
return null;
}
}
DrawableSplashScreen:
/**
* Constructs a {@code DrawableSplashScreen} that displays the given {@code drawable} and
* crossfades to Flutter content in 500 milliseconds.
*
* @param drawable A drawable to display on the Splash screen view.
*/
public DrawableSplashScreen(@NonNull Drawable drawable) {
this(drawable, ImageView.ScaleType.FIT_XY, 500);
}
我们可以看到,图片的缩放模式被限制死了为FIT_XY,而我们这边Flutter启动页面的图片缩放模式为cover。这样就出问题了。
请注意,Android和Flutter图片的显示模式并不是一样的,大家需要根据自己的要求进行选择,并不能说一概而论。
Android
Android中的scaleType属性是ImageView的一个属性,通过设置该属性可以控制图片如何缩放、裁剪以适应ImageView控件的大小。比较常用的选项有CENTER、CENTER_CROP、FIT_XY等,具体作用如下:
- CENTER:居中显示图片,不进行缩放
- CENTER_CROP:按照比例缩放图片,使图片完全填充ImageView,并水平垂直居中显示。图片可能会被裁剪。
- FIT_XY:按照ImageView的大小缩放图片,可能导致图片变形。
Flutter
Flutter中的BoxFit属性也是用于控制图片如何适应容器的。与Android中的scaleType类似,Flutter中的BoxFit也提供了多种选项,包括contain、cover、fitWidth、fitHeight等。具体作用如下:
- contain:将图片缩放到尽可能大,同时保持其宽高比不变,使其完全位于容器内。
- cover:将图片缩放到尽可能大,同时保持其宽高比不变,使其覆盖整个容器。
- fitWidth:将图片的宽度缩放到与容器相同,同时保持其宽高比不变。
- fitHeight:将图片的高度缩放到与容器相同,同时保持其宽高比不变。
总的来说,Android中的scaleType和Flutter中的BoxFit都是用于控制图片适应容器的方式,但它们的具体实现略有不同。
那么怎么做出更改呢?我们绝对不能更改FlutterBoostActivity,因为万一以后清一下Cache,那么一切白改了。我们需要定义一个类继承自FlutterBoostActivity,然后在类中重写一个方法:即用我们需要的原生裁剪方式替代官方默认的裁剪方式。
@Nullable
@Override
public SplashScreen provideSplashScreen() {
Drawable manifestSplashDrawable = getSplashScreen();
if (manifestSplashDrawable != null) {
return new DrawableSplashScreen(manifestSplashDrawable, ImageView.ScaleType.CENTER_CROP, 500);
} else {
return null;
}
}
@Nullable
private Drawable getSplashScreen() {
try {
Bundle metaData = getMetaData();
int splashScreenId = metaData != null ? metaData.getInt("io.flutter.embedding.android.SplashScreenDrawable") : 0;
return splashScreenId != 0
? ResourcesCompat.getDrawable(getResources(), splashScreenId, getTheme())
: null;
} catch (Resources.NotFoundException e) {
io.flutter.Log.e(TAG, "Splash screen not found. Ensure the drawable exists and that it's valid.");
throw e;
} catch (PackageManager.NameNotFoundException e) {
// This is never expected to happen.
return null;
}
}