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;
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_31433709/article/details/130782787