flutter混合开发过程中的一个小问题
- 如何透明背景设置
- 如何处理事件响应
我们的项目是一个以视频为主体的应用,视频上面覆盖了各类互动,弹幕等组件,我们希望一步一步把我们上面的覆盖层改成flutter实现。
在早一些的版本中flutter提供了FlutterView,让我们把flutter作为一个android中的一个组件使用,FlutterView实际上是SurfaceView的子类,它为flutter提供绘制能力,但是在近些的版本中FlutterView不再是public方法了,所以我们得用FlutterFragment来实现该场景,FlutterFragment内部持有FlutterView。
以下是fragment的使用方法:
FlutterFragment flutterFragment = FlutterFragment.createDefault();
activity.getSupportFragmentManager()
.beginTransaction()
.add(R.id.flutter_container, flutterFragment)
.commit();
通过FlutterFragment 可以做事件监听和广播,这里就不表述了,我主要讲一下我遇到的两个问题及最后的解决方案。
如何透明背景设置
在我们的场景中,fragment覆盖在视频流上面,所以它必须是透明的,但是flutterFragment是默认有背景的,这其实是因为我们默认产生的代码中使用的是MaterialApp带上的背景色,这里不使用materialApp即可,
@override
Widget build(BuildContext context) {
return Localizations(
locale: Locale('en'),
delegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
child: Directionality(
child: Navigator(
onGenerateRoute: generate,//路由分发
onUnknownRoute: unKnownRoute,
initialRoute: '/',
),
textDirection: TextDirection.ltr,
),
);
}
我们直接运行flutter部分会出现黑窗口,在项目中展现的就是透明的了
如何处理事件响应
我们的场景中,原生层需要响应一些事件,但是FlutterFragment是会消耗掉所有事件的,其实这个很好理解,因为原生和flutter的通信是异步的,原生层不可能等flutter层做完事件分发才决定哪个view去消耗事件,所以flutterView干脆直接全部消耗了。
FlutterView的源码可以看出,其对触摸事件的处理逻辑也非常简单,把事件解析成flutter需要的格式然后发给flutter就完了。
基于此,我们也不可能有完美的方案让事件分发和原生的分发机制保持一致,退而求其次,我们是可以轻易做到原生和flutter同时可以响应事件。
第一,FlutterFragment不能直接拿到事件,否则它一定会消耗,所以需要在外面包裹一层自定义view,重写view的dispatchTouchEvent方法直接返回false,这样它的子类就无法消耗事件了
第二,在FlutterFragment寄生的activity中重写dispatchTouchEvent
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
findViewById(R.id.flutter_container).dispatchTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
这种方案虽然不完美,但是也能满足大部分该类场景的需求,flutter透明背景的设置方法是在stackFlow上找到的,看得出来还是有不少人有这种需求的