You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现地图组件延伸至底部圆角Bottom Sheet下方

解决方案

要解决Bottom Sheet圆角周围的空隙问题,同时保证地图控件不被遮挡,核心思路是让地图延伸至Bottom Sheet下方,并动态适配Bottom Sheet的高度。具体实现步骤如下:

关键修改:使用Scaffold的extendBody属性+动态高度适配

将原HomePage改为StatefulWidget,通过GlobalKey获取Bottom Sheet的实际高度,给地图添加底部内边距避免控件被遮挡,同时开启extendBody让地图填满空隙:

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final _bottomSheetKey = GlobalKey();
  double _bottomSheetHeight = 0;

  @override
  void initState() {
    super.initState();
    // 布局完成后获取Bottom Sheet的高度
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (_bottomSheetKey.currentContext != null) {
        final renderBox = _bottomSheetKey.currentContext!.findRenderObject() as RenderBox;
        setState(() {
          _bottomSheetHeight = renderBox.size.height;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: const NavBar(),
      // 核心:让body延伸至bottomSheet下方,消除空隙
      extendBody: true,
      appBar: AppBar(
          foregroundColor: Colors.deepOrangeAccent,
          backgroundColor: Colors.white,
          centerTitle: true,
          title: const Text(
            'Home',
            style: TextStyle(fontWeight: FontWeight.w600),
          ),
          shape: const Border(
              bottom: BorderSide(color: Colors.black54, width: 0.5))),
      // 给地图加底部padding,避免缩放按钮被Bottom Sheet遮挡
      body: Padding(
        padding: EdgeInsets.only(bottom: _bottomSheetHeight),
        child: const MapWidget(),
      ),
      bottomSheet: BottomSheet(
        key: _bottomSheetKey,
        builder: (BuildContext context) => const MainBottomSheet(),
        onClosing: () {},
      ),
    );
  }
}

原Bottom Sheet代码无需修改

你的MainBottomSheet组件的圆角、阴影样式已经符合需求,保留原代码即可:

class MainBottomSheet extends StatelessWidget {
  const MainBottomSheet({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.all(16),
      decoration: const BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.only(
            topLeft: Radius.circular(20),
            topRight: Radius.circular(20),
          ),
          boxShadow: [
            BoxShadow(
                color: Colors.black,
                blurRadius: 10,
                spreadRadius: 0,
                offset: Offset(0, 7),
                blurStyle: BlurStyle.normal),
          ]),
      child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            RadioMenuButton(
              value: true,
              groupValue: true,
              onChanged: (bool? value) {
                if (value == true) {
                  showModalBottomSheet(
                    context: context,
                    builder: (BuildContext context) => const SearchBottomSheet(),
                  );
                }
              },
              style: ButtonStyle(
                shape: MaterialStatePropertyAll(
                  RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(20.0),
                  ),
                ),
              ),
              child: const Text('Start Location'),
            ),
            const Divider(),
            RadioMenuButton(
                value: true,
                groupValue: true,
                onChanged: (bool? value) {
                  if (value == true) {
                    showModalBottomSheet(
                      context: context,
                      builder: (BuildContext context) => const SearchBottomSheet(),
                    );
                  }
                },
                style: ButtonStyle(
                  shape: MaterialStatePropertyAll(
                    RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(20.0),
                    ),
                  ),
                ),
                child: const Text('Destination')),
            const Divider(),
            const SizedBox(
              height: 20,
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16),
              child: ElevatedButton(
                onPressed: () {},
                style: const ButtonStyle(
                  backgroundColor:
                      MaterialStatePropertyAll(Colors.deepOrangeAccent),
                  elevation: MaterialStatePropertyAll(3),
                ),
                child: const Text(
                  'Find Route',
                  style: TextStyle(
                      color: Colors.white,
                      fontSize: 20,
                      fontWeight: FontWeight.bold),
                ),
              ),
            )
          ]),
    );
  }
}

效果说明

  1. 开启extendBody: true后,地图会延伸至Bottom Sheet的下方,完全填充圆角周围的空隙;
  2. 通过GlobalKey动态获取Bottom Sheet的高度,避免了固定高度的适配问题;
  3. 地图底部的内边距确保缩放按钮、Google标识等控件不会被Bottom Sheet遮挡。

内容的提问来源于stack exchange,提问作者Ahsan Irfan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:19:53