Skip to content

触摸与手势

本指南:配置地图手势开关,并接收地图 / 标注 / 路线 / POI 等触摸回调。

功能介绍

MapView 提供多层级触摸能力:

  • 手势配置:按需开启或关闭缩放、旋转、倾斜、平移。
  • 专项触摸监听:地图通用按压、标注、路线、POI、地图元素、路侧停车等。
  • 原始事件ViewTouchListener 接收 Android MotionEvent

Cluster / 副屏场景通过 MapGestureProvider 统一处理,见 多屏显示

核心接口一览

分类 接口 说明
手势配置 setActiveGestures(gestures) 启用手势集合
地图触摸 setOnTouchListener 通用按压事件
原始事件 setOnViewTouchListener Android MotionEvent
标注触摸 setOnAnnotationTouchListener 标注点击,含 touchedAnnotations
路线触摸 setOnRouteTouchListener 路线点击,含 routeID
POI 触摸 setOnPOITouchListener POI 点击
地图元素 setOnMapElementTouchListener 地图元素点击
路侧停车 setOnStreetParkingTouchListener 停车位点击

接口详细说明

1. setActiveGestures — 手势开关

控制用户可通过手势执行的地图操作。默认 全部启用;传 null 或空集合则 关闭全部

1
2
3
fun setActiveGestures(
    gestures: Set<GestureType>?
)

参数 类型 说明
gestures Set<GestureType>? 允许的手势集合

GestureType 枚举

说明
Zoom 双指缩放
Rotate 旋转
Tilt 倾斜(3D)
Pan 平移

示例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 允许缩放与平移
mapView.setActiveGestures(setOf(GestureType.Zoom, GestureType.Pan))

// 全部手势
mapView.setActiveGestures(setOf(
    GestureType.Zoom, GestureType.Rotate,
    GestureType.Tilt, GestureType.Pan
))

// 禁用全部手势(如纯展示 HUD)
mapView.setActiveGestures(null)


2. setOnTouchListener — 地图通用按压

接收地图区域的通用触摸事件,常用于获取点击位置的地理坐标。

1
2
3
4
fun pressEvent(
    touchType: TouchType,
    position: TouchPosition
)

参数 类型 说明
touchType TouchType 触摸类型
position TouchPosition 触摸位置(含屏幕坐标与地理信息)

TouchType 枚举

说明
Down / Up 按下 / 抬起
Click 单击
LongClick 长按
Move 移动
Cancel 取消
FingerDoubleClick 单指双击
TwoFingersDoubleClick 双指双击

示例代码

1
2
3
4
5
6
7
mapView.setOnTouchListener { touchType, position ->
    if (touchType == TouchType.Click) {
        val world = mapView.getCameraController()
            ?.viewportToWorld(position.viewportPosition)
        world?.let { onMapClicked(it.latitude, it.longitude) }
    }
}


3. setOnRouteTouchListener — 路线触摸

用于用户点击地图上的路线,典型场景是 选中备选路线并高亮

1
2
3
4
5
fun pressEvent(
    touchType: TouchType,
    position: TouchPosition,
    routeID: String
)

参数 类型 说明
touchType TouchType 触摸类型
position TouchPosition 触摸位置
routeID String 被点击的路线 ID

setOnRouteTouchListener必填注册项(非 nullable 参数),不需要路线触摸时传空实现 {}

示例代码

1
2
3
4
5
mapView.setOnRouteTouchListener { touchType, _, routeId ->
    if (touchType == TouchType.Click) {
        mapView.getRoutesController()?.highlight(routeId)
    }
}

详见 路线渲染 中的路线触摸章节。


4. setOnAnnotationTouchListener — 标注触摸

1
fun pressEvent(touchedAnnotations: List<TouchedAnnotation>)
参数 类型 说明
touchedAnnotations List<TouchedAnnotation> 被点击的标注列表(可能多个重叠)

示例代码

1
2
3
4
5
mapView.setOnAnnotationTouchListener { touchType, _, touchedAnnotations ->
    if (touchType == TouchType.Click) {
        touchedAnnotations.firstOrNull()?.let { onAnnotationClicked(it) }
    }
}


5. setOnPOITouchListener — POI 触摸

1
fun pressEvent(poiDescription: POIDescription?)
参数 类型 说明
poiDescription POIDescription? 被点击 POI 的描述信息

示例代码

1
2
3
4
5
mapView.setOnPOITouchListener { touchType, _, poiDescription ->
    if (touchType == TouchType.Click) {
        poiDescription?.let { showPoiDetail(it) }
    }
}


6. setOnMapElementTouchListener — 地图元素触摸

用于接收地图上 引擎内置元素 的触摸事件(非用户通过 Annotation API 添加的标注)。当前 SDK 仅支持 交通事件(TrafficIncident 类型。

1
fun setOnMapElementTouchListener(listener: MapElementTouchListener?)
1
2
3
4
5
fun pressEvent(
    touchType: TouchType,
    position: TouchPosition,
    mapElements: List<MapElement?>
)
参数 类型 说明
touchType TouchType 触摸类型
position TouchPosition 触摸位置元数据
mapElements List<MapElement?> 命中的地图元素列表,按与触摸点的 距离由近到远 排序;列表项可能为 null

TouchPosition 字段

字段 类型 说明
numberOfTouches Int 参与触摸的手指数
screenLocation PointF 触摸点屏幕坐标
geoLocation Location? 触摸点地理坐标(取自首个命中元素的位置)

使用前提:地图上需显示交通事件图层,否则无法拾取。可通过 FeaturesController.traffic() 开启路况(同时会启用交通事件显示),详见 地图特性

setOnMapElementTouchListener可选 监听器,不需要时传 null 取消注册。

MapElement 结构

MapElement 表示由地图引擎渲染、可通过触摸拾取的内置元素。

成员 说明
type 元素类型,见 MapElement.Type
TrafficIncident type == TrafficIncident 时的子类,通过 info 携带 TrafficInfo

MapElement.Type 枚举(当前值):

说明
TrafficIncident 地图上的交通事件图标

TrafficInfo 字段说明

通过 MapElement.TrafficIncident.info 获取。字段由引擎 TrafficPickable 映射而来:

字段 类型 说明
severity Int 事件严重程度,见下表
incidentType Int 事件类型,取值见 TrafficIncidentTypecom.telenav.sdk.map.content.model
sourceType Int 交通数据源类型编码(如 TMC、TPEG)
roadName String 所在道路名称(引擎字段 currentStreet
message String 事件描述文本
priority Int 事件优先级,见下表
urgency_level Int 紧急程度等级(引擎整型)
blocking_incident Boolean 是否阻断通行(对应引擎 laneClosed
crossStreet String 交叉路口描述(firstCrossStreet + secondCrossStreet 拼接)
firstCrossStreet String 第一交叉道路名称
secondCrossStreet String 第二交叉道路名称
hazardousLocation Location 危险点坐标:事件 开始影响道路 的位置(对应 hazardousPosition
incidentLocation Location 事件点坐标:事件 实际发生 的位置(对应 incidentPosition);地图拾取与图标定位亦基于此
tmcAffectedLength String TMC 影响路段长度描述
firstCrossStreetSubTypeDesc String 第一交叉道路子类型描述
secondCrossStreetSubTypeDesc String 第二交叉道路子类型描述

hazardousLocationincidentLocation 的关系

二者均来自交通数据源(TMC/TPEG),语义与导航侧 TrafficIncidentLocation 中的 hazardousPosition / incidentPosition 一致:

坐标 含义 典型用途
incidentLocation 事件实际发生位置 地图图标落点、触摸拾取、弹窗锚点
hazardousLocation 事件开始影响道路的位置 标示影响区起点(如施工/拥堵的上游端)

对于 点状事件(如单点事故),两者可能相同或非常接近;对于 沿线影响事件(施工占道、路段拥堵等),hazardousLocation 通常位于影响路段的一端,incidentLocation 为事件核心位置,两点可能不同。若数据源未提供有效坐标,对应 Location 可能为 (0, 0),使用前建议校验经纬度是否有效。

incidentType 取值TrafficIncidentType 常量):

常量 说明
UNKNOWN -1 未知
ACCIDENT 0 事故
CONGESTION 1 拥堵
ROAD_CLOSURE 2 道路封闭
CONSTRUCTION 3 施工
EVENT 4 活动/事件
DIFFICULT_DRIVING_CONDITION 5 恶劣驾驶条件
SNOW_AND_ICE 6 冰雪
SMOG_ALERTS 7 雾霾预警
WEATHER 8 天气
REDUCED_VISIBILITY 9 能见度降低
TURN_ON_RADIO 10 交通广播提示
MISCELLANEOUS 11 其他
ROAD_CONTRACTION 12 道路变窄
WIND 13 大风
DISABLED_VEHICLE 14 故障车辆
PLANNED_EVENT 15 计划活动
ROAD_HAZARD 16 道路危险
SCHEDULED_CONSTRUCTION 17 计划施工
POLICE 18 警察/执法
HARD_WARNING 19 严重警告
SOFT_WARNING 20 一般警告
BLOCKED 21 阻塞
SNOW 22 积雪
URGENT_MESSAGE 23 紧急消息
LANE_RESTRICTION 24 车道限制

severity 取值TrafficPickable 常量):

常量 说明
SEVERITY_SEVERE 1 严重
SEVERITY_MAJOR 2 较重
SEVERITY_MINOR 3 较轻

priority 取值TrafficPickable 常量):

常量 说明
PRIORITY_NORMAL 0 普通
PRIORITY_URGENT 1 紧急
PRIORITY_X_URGENT 2 非常紧急

示例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mapView.setOnMapElementTouchListener { touchType, position, mapElements ->
    if (touchType != TouchType.Click) return@setOnMapElementTouchListener

    for (element in mapElements) {
        when (element?.type) {
            MapElement.Type.TrafficIncident -> {
                if (element is MapElement.TrafficIncident) {
                    val info = element.info
                    when (info.incidentType) {
                        TrafficIncidentType.ACCIDENT -> { /* 事故 */ }
                        TrafficIncidentType.ROAD_CLOSURE -> { /* 道路封闭 */ }
                        // 其他类型见 TrafficIncidentType
                    }
                }
            }
            else -> {
                // 当前 SDK 仅支持 TrafficIncident,其他类型预留
            }
        }
    }
}

// 不需要监听时取消注册
mapView.setOnMapElementTouchListener(null)


7. setOnStreetParkingTouchListener — 路侧停车触摸

1
fun pressEvent(touchedParkings: List<OnStreetParkingLot>)
参数 类型 说明
touchedParkings List<OnStreetParkingLot> 被点击的停车位集合(聚合图标可能对应多条)

示例代码

1
2
3
4
5
6
7
8
mapView.setOnStreetParkingTouchListener { touchType, _, touchedParkings ->
    if (touchType == TouchType.Click) {
        touchedParkings.firstOrNull()?.let { parking ->
            mapView.getOnStreetParkingController()
                ?.highlightOnStreetParking(parking.id, true)
        }
    }
}

详见 路侧停车


8. setOnViewTouchListener — 原始 MotionEvent

直接接收 Android 原生 MotionEvent,适合需要自定义手势处理的场景。

示例代码

1
2
3
4
mapView.setOnViewTouchListener { event ->
  // 自定义处理
  false
}


9. Cluster 手势(MapGestureProvider)

ClusterMapView 通过 gestureProvider() 处理手势,支持两种输入方式:

方法 适用平台 说明
motionEventGesture().onTouchEvent(event) Android 触摸屏 转发 MotionEvent
primitiveEventGesture().onClick(x, y) 旋钮 / 遥控器 / Android Auto 平台无关原始手势

ClusterMapViewGestureBinder(推荐 TextureView 场景):

1
2
3
4
5
// 绑定
ClusterMapViewGestureBinder.bind(textureView, clusterMapView)

// 解绑
ClusterMapViewGestureBinder.unbind(textureView)

示例代码

1
2
3
4
// 触摸屏:转发 MotionEvent
clusterMapView.gestureProvider()
    .motionEventGesture()
    ?.onTouchEvent(event)

详见 多屏显示

注意事项

  • 多个监听器可同时注册,按引擎分发顺序触发。
  • setOnRouteTouchListener 为必填项,不需要时传空实现。
  • 屏幕坐标 ↔ 地理坐标转换配合 CameraController.worldToViewport / viewportToWorld,见 显示模式与视角
  • Cluster 场景使用 gestureProvider()不要ClusterMapView 调用 setActiveGestures

相关指南