Flutter中Huawei Maps不响应Offstage隐藏、Stack层级异常问题
问题背景
应用原有地图功能基于Google Maps实现,运行逻辑全部正常。为上架AppGallery替换为Huawei Maps做同等功能实现后,出现两类Google Maps上不存在的异常:
- 使用
Offstage、Opacity组件设置地图隐藏均失效,地图在Stack布局中无法按预期隐藏,异常效果如下:
- 多组件堆叠场景下,地图本应位于其他组件下层,实际会悬浮在所有组件最上层。
复现代码
页面布局逻辑
return Builder( builder: (context) { bContext = context; widget.firstLoad = false; googleMapKey = GlobalKey<GoogleMapDrawerState>( debugLabel: 'googleMapWidget'); Provider.of<ControllerProvider>(context, listen: false) .loadGoogleMapKey(googleMapKey); var googleMap = GoogleMapDrawer( key: googleMapKey, mapCompleted: (controller) { Provider.of<ControllerProvider>(context, listen: false) .loadController(controller); if (Theme.of(context).brightness == Brightness.dark) { Provider.of<ControllerProvider>(context, listen: false) .changeTheme(Brightness.dark); } }, markers: Provider.of<ControllerProvider>(context, listen: false) .marker != null ? [ Provider.of<ControllerProvider>(context, listen: false) .marker ] : [], cameraPosition: hm.CameraPosition( target: hm.LatLng(53.00825 + 0.004, 18.59762), zoom: 15)); return Scaffold( body: Stack(children: [ Offstage( offstage: true, child: googleMap, ),
自定义地图封装组件
代码中注释段为原Google Maps实现,和Huawei Maps调用逻辑完全一致:
return SizedBox( height: size.height * 0.51, width: size.width, child: /*GoogleMap( initialCameraPosition: widget.cameraPosition!, markers: markers != null ? Set.from(markers) : <Marker>{}, onMapCreated: (controller) { Provider.of<ControllerProvider>(context, listen: false) .currentMapBrightness = Theme.of(context).brightness; widget.mapCompleted(controller); })*/ HuaweiMap( initialCameraPosition: widget.cameraPosition!, markers: markers != null ? Set.from(markers) : <Marker>{}, onMapCreated: (controller) { Provider.of<ControllerProvider>(context, listen: false) .currentMapBrightness = Theme.of(context).brightness; widget.mapCompleted(controller); }, ) );
问题原因
这是Flutter平台原生视图渲染模式差异导致的,和业务代码逻辑无关:
- Google Maps Flutter插件默认采用Texture接入模式渲染,地图内容直接绘制在Flutter的渲染纹理上,完全遵循Flutter组件树的层级、显隐、透明度规则,所以所有布局控制都能正常生效。
- Huawei Maps Flutter插件在Android端默认采用
SurfaceView作为原生视图渲染载体,SurfaceView的渲染窗口独立于Flutter的UI渲染树,不受Flutter框架的Offstage、Opacity、Stack层级规则约束,会默认悬浮在所有Flutter组件的最上层,直接导致隐藏失效、层级错乱问题。
修复方案
按优先级推荐以下3种可落地的解决方式:
- 修改华为地图渲染模式(优先推荐)
在HuaweiMap组件初始化时新增参数,将Android端默认的Surface渲染模式改为Texture渲染模式,修改后地图行为和Google Maps完全一致,所有布局控制规则正常生效,且无明显性能损耗:HuaweiMap( // 新增渲染模式配置 androidRenderMode: AndroidRenderMode.texture, initialCameraPosition: widget.cameraPosition!, markers: markers != null ? Set.from(markers) : <Marker>{}, onMapCreated: (controller) { Provider.of<ControllerProvider>(context, listen: false) .currentMapBrightness = Theme.of(context).brightness; widget.mapCompleted(controller); }, ) - 调整显隐逻辑为条件渲染
如果不需要保留地图交互状态(比如不需要记住用户缩放、拖动的位置),直接放弃Offstage/Opacity的隐式控制,用条件判断直接在需要隐藏时把地图从组件树中移除,从根源上避免SurfaceView悬浮:// 替换原有Offstage包裹逻辑 offstage ? SizedBox() : googleMap - 层级问题临时兼容
如果仅需要解决地图悬浮在其他组件上层的问题、不需要控制透明度/显隐,可以给HuaweiMap外层包裹一层ClipRect组件,同时确保Stack中需要显示在地图上层的组件,在children列表中排在地图组件之后,即可临时修复层级错乱问题,但该方案对Offstage、Opacity的适配稳定性不如前两种方案。
内容的提问来源于stack exchange,提问作者Karol Wiśniewski
相关产品推荐
相关产品推荐

