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

Flutter实现类谷歌/苹果地图上滑视图:求Draggable Widget示例代码

刚接触Flutter就想实现地图类的上滑视图,确实得先找对合适的控件!其实比起单纯的Draggable,DraggableScrollableSheet才是做这种谷歌/苹果地图式上滑面板的最佳选择——它专门用来实现可拖拽、能滚动的底部面板,完全贴合你的需求。我给你写个带详细注释的简化示例,你可以直接运行看效果:

示例代码:地图风格上滑视图
import 'package:flutter/material.dart';

void main() => runApp(const MapBottomSheetDemo());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        // 用Stack把地图和上滑面板叠在一起
        body: Stack(
          children: [
            // 模拟地图区域(实际开发中替换成地图插件,比如google_maps_flutter)
            Container(
              color: Colors.lightBlue[100],
              child: const Center(
                child: Text("地图区域"),
              ),
            ),
            // 核心:可拖拽的上滑面板
            DraggableScrollableSheet(
              // 初始高度占屏幕的20%
              initialChildSize: 0.2,
              // 最小收起状态的高度(不能再往下拖)
              minChildSize: 0.1,
              // 最大展开状态的高度(占屏幕80%)
              maxChildSize: 0.8,
              // 拖拽时的背景阴影
              expand: false,
              builder: (BuildContext context, ScrollController scrollController) {
                return Container(
                  decoration: const BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.only(
                      topLeft: Radius.circular(16),
                      topRight: Radius.circular(16),
                    ),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.grey,
                        blurRadius: 10,
                        spreadRadius: 1,
                      )
                    ],
                  ),
                  // 用SingleChildScrollView让面板内容可以滚动
                  child: SingleChildScrollView(
                    controller: scrollController,
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          // 顶部的拖拽指示器(视觉提示用户可以拖拽)
                          Center(
                            child: Container(
                              width: 40,
                              height: 6,
                              decoration: BoxDecoration(
                                color: Colors.grey[300],
                                borderRadius: BorderRadius.circular(3),
                              ),
                            ),
                          ),
                          const SizedBox(height: 20),
                          // 面板内容示例
                          const Text(
                            "地点详情",
                            style: TextStyle(
                              fontSize: 20,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                          const SizedBox(height: 10),
                          const Text("这是一个模拟的地点信息面板,你可以在这里展示地址、评分、评论等内容。"),
                          // 加足够多的内容来测试滚动
                          ...List.generate(20, (index) {
                            return Padding(
                              padding: const EdgeInsets.symmetric(vertical: 8.0),
                              child: Text("列表项 ${index + 1}"),
                            );
                          }),
                        ],
                      ),
                    ),
                  ),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}
关键知识点说明
  • DraggableScrollableSheet参数解析:
    • initialChildSize:面板初始显示的高度比例(0到1之间)
    • minChildSize:面板能收起的最小高度比例
    • maxChildSize:面板能展开的最大高度比例
    • scrollController:用来关联内部的滚动组件,实现拖拽和滚动的联动
  • 为什么不用Draggable?Draggable更适合单个独立的可拖拽小部件(比如拖拽一个按钮),而这种底部面板需要支持拖拽调整高度+内容滚动,DraggableScrollableSheet是Flutter官方专门为这类场景设计的控件,上手更简单。
  • 实际开发中,把模拟地图的Container替换成你用的地图插件就行,两者的交互不会冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:55:17