手势冲突处理

当地图嵌入 ListViewPageView 等可滚动容器时,地图手势与容器滚动手势会产生竞争。插件提供 gestureRecognizers 参数来配置手势竞技场策略。

本文档介绍三种手势冲突解决方案及其适用场景。




问题场景

ListView(
  children: [
    const SizedBox(height: 200, child: Text('顶部内容')),
    SizedBox(
      height: 300,
      child: TencentMap(...), // 地图嵌入 ListView
    ),
    const SizedBox(height: 200, child: Text('底部内容')),
  ],
)

默认情况下,手指在地图区域上下滑动时,Flutter 的手势竞技场会判定为 ListView 滚动,导致地图无法响应平移手势。


解决方案

通过 gestureRecognizers 配置手势策略:

策略一:默认(GestureArena 竞争)

TencentMap(
  gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
  ...
)

地图和容器共同参与手势竞技场,由 Flutter 自动判定获胜者。适合地图和容器内容独立的场景。

策略二:地图优先(Eager)

TencentMap(
  gestureRecognizers: {
    Factory<OneSequenceGestureRecognizer>(
      () => EagerGestureRecognizer(),
    ),
  },
  ...
)

地图优先消费所有手势,容器无法滚动。适合地图区域较大、不希望容器拦截的场景。

策略三:双指归地图

TencentMap(
  gestureRecognizers: {
    Factory<OneSequenceGestureRecognizer>(
      () => VerticalDragGestureRecognizer()
        ..onUpdate = (_) {}, // 消费垂直拖拽
    ),
  },
  ...
)

单指滑动归容器滚动,双指操作归地图(缩放/旋转)。适合地图嵌入长列表的场景。


完整示例

ListView(
  children: [
    const SizedBox(height: 200, child: Center(child: Text('顶部'))),
    SizedBox(
      height: 350,
      child: TencentMap(
        initialCameraPosition: const CameraPosition(
          target: LatLng(39.9087, 116.3975),
          zoom: 12,
        ),
        // 双指归地图策略
        gestureRecognizers: {
          Factory<OneSequenceGestureRecognizer>(
            () => VerticalDragGestureRecognizer()..onUpdate = (_) {},
          ),
        },
      ),
    ),
    const SizedBox(height: 200, child: Center(child: Text('底部'))),
  ],
)

策略选择建议

场景 推荐策略
地图占满全屏 默认即可
地图嵌入短列表,列表内容少 Eager(地图优先)
地图嵌入长列表,需要滚动浏览 双指归地图
地图在 PageView 中,需要翻页 默认 + PageView 的 pageSnapping
本页内容