记一次ViewPager+FlutterFragment渲染错乱的问题

279 阅读1分钟

背景

项目是原生+Flutter实现。首页都是使用的原生页面4个页面切换:Tabbar+ViewPager+Fragment

需求

将其中第三个Fragment通过Flutter实现,使用FlutterFragment承载渲染功能。

问题

  1. ViewPager使用setOffscreenPageLimit(4)实现全部加载,结果现象是:第三个FlutterFragment直接显示在第一个页面上,并且Touch事件是第一个Fragment响应。也就是说,第三个FlutterFragment直接盖在第一个页面之上,并且无Touch响应。
  2. 从Fragment1、2、4各自页面跳转业务页面返回后,直接呈现的是FlutterFragment内容盖在其他Tab页之上,并且无Event事件。

乱投医

因为项目紧急,没时间排查问题,且渲染相关的场景接触的不多,以为是ViewPager不兼容导致的,换成ViewPager2还是有这个问题。毛线都没解决。

解决

渲染逻辑不受View层代码控制的是什么原因,突然想到了SurfaceView这家伙不太受原生控制,然后查FlutterFragment源码

///FlutterFragment
@Override
@NonNull
public RenderMode getRenderMode() {
  String renderModeName =
      getArguments().getString(ARG_FLUTTERVIEW_RENDER_MODE, RenderMode.surface.name());
  return RenderMode.valueOf(renderModeName);
}

/** Render modes for a Flutter UI. */
public enum RenderMode {

  ///通过SurfaceView实现,性能好,但是不能做各种动画和原生View及配合的Z-index操作
  surface,
  
   ///通过SurfaceTexture实现,此模式的性能不如surface,但此模式下的Flutter UI可以动画和转换及Z-index操作
  texture,
 
   ///通过ImageReader绘制在Canvas上,最终是通过FlutterImageView实现,如在Flutter UI中嵌入了原生View,一般情况下不需要我们实现。
  image
}

默认是通过SurfaceView实现,我们重写FlutterFragment.getRenderMode返回RenderMode.texture,问题得以解决。