Android中Mapbox导航如何监听途经点(Waypoint)到达事件?
我之前在做Mapbox Android导航开发时也碰到过这个问题,确实默认的onArrival回调只会在到达最终目的地时触发,不过有两种靠谱的方式可以实现途经点到达的监听,分享给你:
方法一:通过监听导航路段(Leg)完成事件
Mapbox的导航路线会把整个行程拆分成多个Leg——每个Leg对应两个途经点(包括起点和终点)之间的路段。比如你设置了「起点→途经点A→途经点B→终点」,路线就会被拆成3个Leg:起点到A、A到B、B到终点。当某个Leg完成时,就意味着到达了该路段的终点,也就是我们要监听的途经点。
具体实现步骤:
- 启动导航前,先保存你的途经点列表(注意排除起点和终点,只保留中间的stop-point)
- 注册
ProgressChangeListener,监听导航进度变化 - 在回调中检查当前
Leg是否完成,匹配对应的途经点并执行操作
示例代码(Kotlin):
// 假设你已经构建好包含途经点的RouteOptions val waypoints = routeOptions.waypoints // 提取中间的途经点(排除起点和终点) val stopPoints = if (waypoints.size > 2) waypoints.subList(1, waypoints.size - 1) else emptyList() // 注册进度监听器 navigationView.registerProgressChangeListener(object : ProgressChangeListener { override fun onProgressChange(routeProgress: RouteProgress) { val currentLegProgress = routeProgress.currentLegProgress // 检查当前路段是否完成 if (currentLegProgress.isLegComplete) { val currentLegIndex = routeProgress.currentLegIndex // 匹配对应的途经点(注意Leg索引和途经点索引的对应关系) if (currentLegIndex < stopPoints.size) { val arrivedStopPoint = stopPoints[currentLegIndex] // 这里执行你需要的操作,比如弹窗提示、上报数据等 Log.d("MapboxNav", "到达途经点:${arrivedStopPoint.name ?: "未命名"}") // 可以添加标记避免重复触发,比如用一个集合记录已到达的途经点索引 } } } })
方法二:自定义里程碑(Milestone)实现精准位置触发
如果你需要更精确的触发(比如用户进入途经点周围5米范围内就执行操作),可以用Mapbox的Milestone机制,自定义触发条件来监听途经点位置。
具体实现步骤:
- 为每个途经点创建自定义
Milestone,设置触发范围(比如5米) - 启动导航时将这些里程碑添加到导航配置中
- 在里程碑的回调中执行到达操作
示例代码(Kotlin):
// 提取中间途经点 val waypoints = routeOptions.waypoints val stopPoints = if (waypoints.size > 2) waypoints.subList(1, waypoints.size - 1) else emptyList() // 为每个途经点创建自定义里程碑 val stopPointMilestones = stopPoints.mapIndexed { index, waypoint -> object : Milestone( // 设置触发条件:到达途经点的经纬度,且在5米范围内 Trigger.all( Trigger.latitude(waypoint.latitude()), Trigger.longitude(waypoint.longitude()), Trigger.range(5.0) ), "stop_point_milestone_$index" ) { override fun onTriggered( routeProgress: RouteProgress, navigator: Navigator, navigationOptions: NavigationOptions ): MilestoneResult { // 执行到达途经点的操作 Log.d("MapboxNav", "进入途经点范围:${waypoint.name ?: "未命名"}") return MilestoneResult.continueNavigation() // 继续导航 } } } // 启动导航时添加里程碑 val navigationOptions = NavigationOptions.Builder(context) .routeOptions(routeOptions) .milestones(stopPointMilestones) .build() navigationView.startNavigation(navigationOptions)
两种方法各有优势:方法一适合按路段完成逻辑触发,不需要精确位置;方法二更灵活,可以自定义触发距离,适合需要精准位置判断的场景。
内容的提问来源于stack exchange,提问作者Kinjal
相关产品推荐
相关产品推荐

