最近在使用OverLay添加浮窗的时候,遇到个问题,在某个界面上弹出浮窗,界面跳转,浮窗仍然存在
研究发现,使用Overlay.of(context)来获取overlay的时候,会获取到最近的overlay,如果不做处理,一般会获取到MaterialApp中的navigator创建的Overlay。此时的overlay是全局的,如果当前界面收到某些事件回调导致跳转,会导致上述现象。
解决方法:可以在需要展示浮窗的界面顶层嵌套一层overlay,然后使用Overlay.of(context)获取到的就是当前界面的overlay,界面跳转即会消失
@override
Widget build(BuildContext context) {
TWLog("_DetailPageState build...");
// return _buildBody(context);
return Overlay(
initialEntries: [
OverlayEntry(
builder: (context) {
_logic.detailState.overlayContext = context;
return _buildBody(context);
},
),
],
);
}
添加蒙层
void showVideoTipLayer() {
// 获取当前页面overlay
var overlayContext = detailState.overlayContext;
if (overlayContext == null) {
return;
}
var overlay = Overlay.of(overlayContext);
if (overlay == null) {
return;
}
detailState.videoTipEntry = OverlayEntry(builder: (_) {
return DetailVideoTipView(videoViewHeight: DetailHeaderView.getHeight(), closeAction: () {
// 释放
detailState.videoTipEntry?.remove();
detailState.videoTipEntry = null;
},);
});
overlay.insert(detailState.videoTipEntry!); // 添加浮窗
}
这种写法虽然可以正常实现浮窗的创建和移除,但是会引发另外的问题,每次添加浮窗,都会使当前的树结构重构,所有的widget重新build,可能会出现某些界面布局问题
针对这种情况,对写法进行了改进,总结出下面的方案,具体写法如下:
1.准备工作 添加属性
/// 当前页Overlay的context
BuildContext? overlayContext;
/// 蒙层
OverlayEntry? videoTipEntry;
- 界面使用stack布局嵌套两层视图,顶部添加Overlay,底部添加需要创建的界面
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: Stack(
children: [
_buildBody(context), // 实际界面布局
Overlay(
initialEntries: [
OverlayEntry(
builder: (context) {
_logic.detailState.overlayContext = context;
return const SizedBox();
},
),
],
),
],
),
);
}
- 在适合的地方完成浮窗创建和添加,注意不要忘记释放
/// 添加蒙层
void showVideoTipLayer() {
// 获取当前页面overlay
var overlayContext = detailState.overlayContext;
if (overlayContext == null) {
return;
}
var overlay = Overlay.of(overlayContext);
if (overlay == null) {
return;
}
detailState.videoTipEntry = OverlayEntry(builder: (_) {
return DetailVideoTipView(videoViewHeight: DetailHeaderView.getHeight(), closeAction: () {
// 释放
detailState.videoTipEntry?.remove();
detailState.videoTipEntry = null;
},);
});
overlay.insert(detailState.videoTipEntry!); // 添加浮窗
}
这样就可以方便的针对某个界面添加独有的浮窗啦