Flutter中flutter-mapbox-gl地图遮挡App Drawer侧边栏问题
问题原因
mapbox_gl 采用PlatformView嵌入原生地图组件,这类原生视图默认渲染优先级高于Flutter自身的Widget绘制层。你的代码中在MapControl、ViewView两层都额外嵌套了Scaffold,多层Scaffold冲突导致HomeView挂载的Drawer无法覆盖在原生地图上方,最终出现遮挡。
解决方案
方案1:移除冗余Scaffold(优先尝试,90%场景可直接修复)
整个路由栈只保留HomeView中的根Scaffold即可,删掉子页面多余的Scaffold嵌套:
- 修改
map.dart,去掉MapboxMap外层包裹的Scaffold:
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:mapbox_gl/mapbox_gl.dart'; import '../services/item.dart'; class MapControl extends StatefulWidget { const MapControl({Key? key}) : super(key: key); @override State<StatefulWidget> createState() => MapControlState(); } class MapControlState extends State<MapControl> { final itemService = Get.find<ItemService>(); MapboxMapController? mapController; _onMapCreated(MapboxMapController controller) { mapController = controller; } _onStyleLoadedCallback() { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: const Text("Style loaded :)"), backgroundColor: Theme.of(context).primaryColor, duration: const Duration(seconds: 1), )); } @override Widget build(BuildContext context) { return MapboxMap( styleString: MapboxStyles.LIGHT, accessToken: 'xxxxxxxxxxxxxxxxx', onMapCreated: _onMapCreated, initialCameraPosition: const CameraPosition(target: LatLng(0.0, 0.0)), onStyleLoadedCallback: _onStyleLoadedCallback, ); } }
- 修改
view_view.dart,去掉外层冗余Scaffold:
import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../common/calendar.dart'; import '../../../common/list.dart'; import '../../../common/map.dart'; import '../../../models/items.dart'; import '../controllers/view_controller.dart'; class ViewView extends GetView<ViewController> { const ViewView({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Obx( () => getView(controller.itemService.currentActiveViewItem.value) ); } Widget getView(Item? viewItem) { switch (viewItem?.type?.name) { case "CalendarView": return const CalendarControl(); case "ListView": return const ListControl(); case "MapView": return const MapControl(); default: return Container(); } } }
方案2:监听Drawer状态动态切换Map显示(方案1无效时使用)
如果移除冗余Scaffold后仍存在遮挡,可以在Drawer打开时临时隐藏Map组件,用占位组件替代,Drawer关闭后再恢复显示:
- 在HomeController中新增状态记录Drawer开合状态:
final RxBool isDrawerOpen = false.obs;
- 给HomeView的根Scaffold绑定GlobalKey,监听Drawer状态变化:
class HomeView extends GetView<HomeController> { final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); @override Widget build(BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((_) { _scaffoldKey.currentState?.drawerController?.addListener(() { controller.isDrawerOpen.value = _scaffoldKey.currentState?.drawerController?.isOpen ?? false; }); }); return Obx(() => Scaffold( key: _scaffoldKey, appBar: AppBar( title: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ RealNetIcon(controller.itemService.currentItem.value), Text(controller.itemService.currentItem.value?.name ?? "RealNet") ], ), centerTitle: true, ), body: Navigator( key: Get.nestedKey(1), initialRoute: '/empty', onGenerateRoute: controller.onGenerateRoute, ), drawer: NavDrawer(), bottomNavigationBar: controller.itemService.currentViewItems.value.length >= 2 ? BottomNavigationBar( type: BottomNavigationBarType.fixed, currentIndex: controller.itemService.currentActiveViewIndex.value, onTap: (value) { controller.itemService.updateActiveViewIndex(value); }, items: [ ...controller.itemService.currentViewItems.value.map((viewItem) => BottomNavigationBarItem( label: viewItem.name, icon: RealNetIcon(viewItem), )), ], ) : null, )); } }
- 修改ViewView中的getView逻辑,Drawer打开时替换Map为占位组件:
Widget getView(Item? viewItem) { if (controller.isDrawerOpen.value && viewItem?.type?.name == "MapView") { return Container( color: Colors.grey[100], alignment: Alignment.center, child: const CircularProgressIndicator(), ); } switch (viewItem?.type?.name) { case "CalendarView": return const CalendarControl(); case "ListView": return const ListControl(); case "MapView": return const MapControl(); default: return Container(); } }
方案3:Android端开启透明窗口配置
如果仅Android端存在遮挡,可修改MainActivity配置开启透明窗口,让原生视图层级低于Flutter绘制层:
打开android/app/src/main/kotlin/对应包名/MainActivity.kt,修改代码:
import io.flutter.embedding.android.FlutterActivity import android.os.Build import android.os.Bundle import androidx.annotation.RequiresApi class MainActivity: FlutterActivity() { @RequiresApi(Build.VERSION_CODES.LOLLIPOP) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.setBackgroundDrawableResource(android.R.color.transparent) } }
复现环境信息
- Flutter版本:3.0.1 stable(Windows平台)
- 依赖版本:mapbox_gl: ^0.16.0, get: ^4.6.3
- 问题截图:

内容的提问来源于stack exchange,提问作者Christine
相关产品推荐
相关产品推荐

