Skip to content

转弯气泡

本指南:使用 TurnBubbleFeature 在地图上展示逐向导航转弯气泡。

功能介绍

转弯气泡用于在路线步骤附近展示 转向箭头下一道路名,帮助用户理解即将发生的机动动作。该能力由导航模块的 NavigationEventListener.onNavigationEventUpdated 驱动:回调中的 NavigationEvent.currentManeuver 提供当前机动信息,并在 legIndex / stepIndex 变化时更新气泡。

职责划分

角色 职责
HMI 根据产品需求,将当前机动映射为 TurnType,调用 enableTurnBubble(..., turnBubbleType, ...) 传入;选用哪种类型、是否区分细分场景(如 Y 形岔口)由 HMI 自行决定
SDK 对外暴露完整的 TurnType 枚举(com.telenav.sdk.map.model.TurnType),供 HMI 选用;不负责图标纹理选择
地图引擎 / TSS 资源 读取 HMI 传入的 TurnType ordinal,在 atlas 的 street_bubble.layout 中映射到对应图标纹理并渲染气泡样式

效果示意

转弯气泡

获取入口:

1
val turnBubble = mapView.getFeaturesController()?.turnBubbles()

核心接口

方法 说明
enableTurnBubble(routeId, legIndex, stepIndex, turnBubbleType, nextStreetName) 为指定step展示转弯气泡
disableTurnBubble(routeId, legIndex, stepIndex) 隐藏指定step气泡
disableAllTurnBubbles() 清除全部气泡

接口详细说明

1. enableTurnBubble — 展示转弯气泡

为指定导航路线的某个 leg / step 启用转弯气泡,显示转向箭头与下一道路名。

1
2
3
4
5
6
7
fun enableTurnBubble(
    routeId: String,
    legIndex: Int,
    stepIndex: Int,
    turnBubbleType: TurnType,
    nextStreetName: String?
)

参数 类型 说明
routeId String 当前导航路线 ID,来自 RoutesController.addRouteLine 返回值
legIndex Int 路线 leg 索引;来自 NavigationEvent.legIndexManeuverInfo.legIndex;≥ 0
stepIndex Int leg 内 step 索引;与路线 step 对齐(SDK 示例在机动 step 上使用 NavigationEvent.stepIndex + 1);≥ 0
turnBubbleType TurnType HMI 按产品需求传入的转弯类型;SDK 暴露全部支持的 TurnType 枚举值,具体选用哪一种由 HMI 决定(可参考下文 TurnTypeExtensions,亦可自行实现映射)
nextStreetName String? 下一道路名,通常取 ManeuverInfo.streetName;无道路名时传 null

示例代码

1
2
3
4
5
6
7
turnBubble.enableTurnBubble(
    routeId = navRouteId,
    legIndex = 0,
    stepIndex = 2,
    turnBubbleType = TurnType.LEFT,
    nextStreetName = "Main St"
)


2. disableTurnBubble — 隐藏指定步骤气泡

1
fun disableTurnBubble(routeId: String, legIndex: Int, stepIndex: Int)
参数 类型 说明
routeId String 需要隐藏气泡的路线 ID
legIndex Int 路线 leg 索引
stepIndex Int leg 内 step 索引

示例代码

1
turnBubble.disableTurnBubble(navRouteId, legIndex = 0, stepIndex = 1)


3. disableAllTurnBubbles — 清除全部气泡

1
fun disableAllTurnBubbles()

移除所有已激活的转弯气泡。适用于:停止导航、路线变化、重算路、显著位置更新等场景。

示例代码

1
turnBubble.disableAllTurnBubbles()


使用流程

  1. 使用 RoutesController 渲染当前导航路线,记录 routeId
  2. NavigationEventListener.onNavigationEventUpdated 中接收 NavigationEvent(见下文“示例实现”)。
  3. 通过显示策略在 step 变化时更新转弯气泡;导航结束或重算路时调用 disableAllTurnBubbles()

示例实现

机动(maneuver)数据来自导航模块 NavigationEventListener.onNavigationEventUpdated。常见做法是在 ViewModel 中实现该回调并 postLiveData,UI 层观察后交给显示策略处理。

监听导航事件

使用转弯气泡前,先观察导航事件并驱动显示策略更新:

1
2
3
navViewModel.navigationEvent.observe(viewLifecycleOwner) {
    turnBubbleDisplayStrategy.updateNavigationEvent(it)
}

navigationEvent 由 ViewModel 在 onNavigationEventUpdated 中更新;注册方式:navigationService.eventHub.addNavigationEventListener(listener)

转弯气泡显示策略

该策略根据 NavigationEventlegIndex / stepIndex 变化,决定何时显示或隐藏转弯气泡(SDK 示例:TurnBubbleDisplayStrategy)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class TurnBubbleDisplayStrategy(private val turnBubbleCallback: Callback) {

    private var currentLegIndex = -1
    private var currentStepIndex = -1

    fun updateNavigationEvent(navigationEvent: NavigationEvent) {
        if (currentLegIndex != navigationEvent.legIndex ||
            currentStepIndex != navigationEvent.stepIndex
        ) {
            turnBubbleCallback.hideTurnBubble(currentLegIndex, currentStepIndex + 1)
            currentLegIndex = navigationEvent.legIndex
            currentStepIndex = navigationEvent.stepIndex

            navigationEvent.currentManeuver?.let {
                turnBubbleCallback.showTurnBubble(
                    currentLegIndex,
                    currentStepIndex + 1,
                    it.getTurnType(),
                    navigationEvent.currentManeuver?.streetName
                )
            }
        }
    }

    fun resetStatus() {
        currentLegIndex = -1
        currentStepIndex = -1
    }

    interface Callback {
        fun showTurnBubble(
            legIndex: Int,
            stepIndex: Int,
            turnType: TurnType,
            nextStreetName: String?
        )
        fun hideTurnBubble(legIndex: Int, stepIndex: Int)
    }
}

对接地图 API

Callback 实现中调用 TurnBubbleFeature

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
turnBubbleDisplayStrategy = TurnBubbleDisplayStrategy(object : TurnBubbleDisplayStrategy.Callback {
    override fun showTurnBubble(
        legIndex: Int,
        stepIndex: Int,
        turnType: TurnType,
        nextStreetName: String?
    ) {
        mapView.getFeaturesController()?.turnBubbles()?.enableTurnBubble(
            routeId, legIndex, stepIndex, turnType, nextStreetName
        )
    }

    override fun hideTurnBubble(legIndex: Int, stepIndex: Int) {
        mapView.getFeaturesController()?.turnBubbles()?.disableTurnBubble(
            routeId, legIndex, stepIndex
        )
    }
})

导航停止或重算路时:

1
2
mapView.getFeaturesController()?.turnBubbles()?.disableAllTurnBubbles()
turnBubbleDisplayStrategy.resetStatus()

转弯类型与地图渲染

HMI 只需传入 TurnType图标长什么样、对应哪张纹理,由 TSS 资源决定。地图引擎将 turnBubbleTypeordinal(整型序号) 传给样式系统,在 street_bubble.layoutstepped(turnType, [...]) 中查找纹理并渲染。

例如:图标与气泡外观的权威定义在 atlas TSS 资源中:

项目 路径
TSS 布局定义 atlas-data/styles/layouts/street_bubble.layout
图标纹理目录 atlas-data/badges/textures/bubble/turn/
气泡锚点(handle) atlas-data/badges/textures/bubble/turn-bubble-handle.png

核心映射逻辑(turn-street 图层):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
icon-image: stepped(turnType,
[
  ...
  9:  turn_merge_left.png,                 // MERGE_LEFT
  10: turn_merge_right.png,                // MERGE_RIGHT
  11: turn_arrow_stay_left_straight.png,   // STAY_LEFT(@turn-street-icon-stay-left-straight)
  12: turn_arrow_stay_right_straight.png,  // STAY_RIGHT(@turn-street-icon-stay-right-straight)
  13: turn_enter_left.png,                 // ENTER_LEFT
  14: turn_enter_right.png,                // ENTER_RIGHT
  15: turn_exit_left.png,                  // EXIT_LEFT
  16: turn_exit_right.png,                 // EXIT_RIGHT
  ...
  40: turn_enter_left.png,                 // STAY_LEFT_FORK(@turn-street-icon-stay-left)
  41: turn_enter_right.png                 // STAY_RIGHT_FORK(@turn-street-icon-stay-right)
]);
完整 ordinal → 纹理对照见下文 转弯类型与图标对照表


转弯类型与图标对照表

下表列出 SDK 暴露的 TurnType 与 TSS 资源中的默认图标映射,供 HMI 选型与 atlas 定制参考。ordinal 与纹理的对应关系以 street_bubble.layout 中的 stepped(turnType, [...]) 为准。

基本转向

TurnType 说明 图标
STRAIGHT 0 直行 STRAIGHT
LEFT 1 左转 LEFT
RIGHT 2 右转 RIGHT
SLIGHT_LEFT 3 稍向左转 SLIGHT_LEFT
SLIGHT_RIGHT 4 稍向右转 SLIGHT_RIGHT
SHARP_LEFT 5 急左转 SHARP_LEFT
SHARP_RIGHT 6 急右转 SHARP_RIGHT
UTURN_LEFT 7 左侧掉头 UTURN_LEFT
UTURN_RIGHT 8 右侧掉头 UTURN_RIGHT

并线

车道汇入场景,纹理为 turn_merge_*.png

TurnType 说明 图标
MERGE_LEFT 9 向左并线 MERGE_LEFT
MERGE_RIGHT 10 向右并线 MERGE_RIGHT

分道保持与 Y 形岔口

主路分道与 Y 形岔口相关类型。STAY_LEFT / STAY_RIGHT(11、12)表示继续沿主路直行、旁路向一侧分出,纹理为 turn_arrow_stay_*_straight.pngSTAY_LEFT_FORK / STAY_RIGHT_FORK(40、41)表示在 Y 形路口走左/右分支,layout 通过 @turn-street-icon-stay-left/right 别名复用 turn_enter_*.png(与 ENTER_LEFT / ENTER_RIGHT 纹理相同,ordinal 不同)。

TurnType 说明 图标
STAY_LEFT 11 主路直行,旁路向右上分出 STAY_LEFT
STAY_RIGHT 12 主路直行,旁路向左上分出 STAY_RIGHT
STAY_LEFT_FORK 40 Y 形岔口:走左侧分支 STAY_LEFT_FORK
STAY_RIGHT_FORK 41 Y 形岔口:走右侧分支 STAY_RIGHT_FORK

匝道 / 辅路进入

从左侧或右侧驶入道路/高速(turn_enter_*.png)。

TurnType 说明 图标
ENTER_LEFT 13 从左侧驶入 ENTER_LEFT
ENTER_RIGHT 14 从右侧驶入 ENTER_RIGHT

匝道 / 辅路驶出

从主路向左侧或右侧驶出(turn_exit_*.png)。

TurnType 说明 图标
EXIT_LEFT 15 向左侧驶出 EXIT_LEFT
EXIT_RIGHT 16 向右侧驶出 EXIT_RIGHT

右行环岛(Right-hand roundabout)

TurnType 说明 图标
ROUNDABOUT_ENTER 17 进入环岛 ROUNDABOUT_ENTER
ROUNDABOUT_EXIT 18 驶出环岛 ROUNDABOUT_EXIT
ROUNDABOUT_STRAIGHT 19 环岛直行 ROUNDABOUT_STRAIGHT
ROUNDABOUT_SLIGHT_LEFT 20 环岛稍向左 ROUNDABOUT_SLIGHT_LEFT
ROUNDABOUT_LEFT 21 环岛左转 ROUNDABOUT_LEFT
ROUNDABOUT_SHARP_LEFT 22 环岛急左转 ROUNDABOUT_SHARP_LEFT
ROUNDABOUT_UTURN 23 环岛掉头 ROUNDABOUT_UTURN
ROUNDABOUT_SHARP_RIGHT 24 环岛急右转 ROUNDABOUT_SHARP_RIGHT
ROUNDABOUT_RIGHT 25 环岛右转 ROUNDABOUT_RIGHT
ROUNDABOUT_SLIGHT_RIGHT 26 环岛稍向右 ROUNDABOUT_SLIGHT_RIGHT

左行环岛(Left-hand roundabout)

适用于左侧通行地区(如英国、澳大利亚等)。SDK 参考实现在 leftSideDriving == trueAssistAction.ENTER_ROUNDABOUT 时,按出口角度返回 LEFT_ROUNDABOUT_*(不含 LEFT_ROUNDABOUT_ENTER);LEFT_ROUNDABOUT_EXITAssistAction.EXIT_ROUNDABOUT 时返回。

TurnType 说明 图标
LEFT_ROUNDABOUT_ENTER 27 进入环岛(左行) LEFT_ROUNDABOUT_ENTER
LEFT_ROUNDABOUT_EXIT 28 驶出环岛(左行) LEFT_ROUNDABOUT_EXIT
LEFT_ROUNDABOUT_STRAIGHT 29 环岛直行(左行) LEFT_ROUNDABOUT_STRAIGHT
LEFT_ROUNDABOUT_SLIGHT_LEFT 30 环岛稍向左(左行) LEFT_ROUNDABOUT_SLIGHT_LEFT
LEFT_ROUNDABOUT_LEFT 31 环岛左转(左行) LEFT_ROUNDABOUT_LEFT
LEFT_ROUNDABOUT_SHARP_LEFT 32 环岛急左转(左行) LEFT_ROUNDABOUT_SHARP_LEFT
LEFT_ROUNDABOUT_UTURN 33 环岛掉头(左行) LEFT_ROUNDABOUT_UTURN
LEFT_ROUNDABOUT_SHARP_RIGHT 34 环岛急右转(左行) LEFT_ROUNDABOUT_SHARP_RIGHT
LEFT_ROUNDABOUT_RIGHT 35 环岛右转(左行) LEFT_ROUNDABOUT_RIGHT
LEFT_ROUNDABOUT_SLIGHT_RIGHT 36 环岛稍向右(左行) LEFT_ROUNDABOUT_SLIGHT_RIGHT

特殊机动

TurnType 说明 图标
HOOK_TURN 37 Hook Turn(如墨尔本有轨电车路口) HOOK_TURN
ENTER_FERRY 38 进入轮渡 ENTER_FERRY
TOLLBOOTH 39 通过收费站 TOLLBOOTH

定制图标或调整样式时,在 atlas TSS 资源中替换 bubble/turn/ 纹理或修改 street_bubble.layoutstepped(turnType, [...]) 映射即可;HMI 侧继续传入相同的 TurnType,无需改动 SDK 调用代码。

SDK 参考实现(TurnTypeExtensions,可选)

TurnTypeExtensions.kt 中的 ManeuverInfo.getTurnType() 仅为 可选参考:演示如何将 turnAction / turnAssistAction 映射为 TurnType。HMI 不必使用该实现,可按产品需求自行映射或扩展;无论采用哪种映射,只要传入合法的 TurnType,引擎均按 TSS 资源渲染对应图标。

该参考实现 未覆盖全部类型

参考实现已覆盖的类型:

分类 覆盖的 TurnType
基本转向 STRAIGHTLEFTRIGHTSLIGHT_LEFTSLIGHT_RIGHTSHARP_LEFTSHARP_RIGHTUTURN_LEFTUTURN_RIGHT
分道保持 / Y 形岔口 STAY_LEFTSTAY_RIGHTSTAY_LEFT_FORKSTAY_RIGHT_FORK 需 HMI 自行映射
匝道 / 辅路进出 ENTER_LEFTENTER_RIGHTEXIT_LEFTEXIT_RIGHT
环岛驶出 ROUNDABOUT_EXITLEFT_ROUNDABOUT_EXITENTER_ROUNDABOUT 时按 roundaboutInfo.exitAngles 映射 ROUNDABOUT_* / LEFT_ROUNDABOUT_*(不含 *_ENTER
特殊机动 ENTER_FERRYHOOK_TURNTOLLBOOTH

参考实现未覆盖、需 HMI 自行映射的类型:

TurnType 说明
MERGE_LEFT 9 向左并线
MERGE_RIGHT 10 向右并线
ROUNDABOUT_ENTER 17 进入环岛(右行)
LEFT_ROUNDABOUT_ENTER 27 进入环岛(左行)

参考实现入口逻辑:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
fun ManeuverInfo.getTurnType(): TurnType {
    val lsd = leftSideDriving
    val angle = roundaboutInfo?.exitAngles?.getOrNull((roundaboutInfo?.exitNumber ?: 1) - 1)

    return when (turnAssistAction) {
        AssistAction.ENTER_FERRY -> TurnType.ENTER_FERRY
        AssistAction.PERFORM_HOOK_TURN -> TurnType.HOOK_TURN
        AssistAction.PASS_TOLL_BOOTH -> TurnType.TOLLBOOTH
        AssistAction.EXIT_ROUNDABOUT ->
            if (lsd) TurnType.LEFT_ROUNDABOUT_EXIT else TurnType.ROUNDABOUT_EXIT
        AssistAction.ENTER_ROUNDABOUT -> getRoundaboutTurnType(angle, lsd)
        else -> getTurnTypeFromAction(turnAction, turnAssistAction)
    }
}

getTurnTypeFromAction 处理左右转、稍转、急转、掉头、靠左/靠右直行及高速匝道进出;未匹配时返回 STRAIGHT。并线(MERGE_*)、环岛进入(*_ENTER)、Y 形岔口(STAY_*_FORK)等场景需 HMI 根据 ManeuverInfo 字段自行判断并传入对应 TurnType


注意事项

  • 转弯气泡更新应与导航步骤变化保持同步。
  • 启用下一个气泡前,建议先隐藏上一个,避免残留过期引导。
  • turnBubbleType 由 HMI 按产品需求传入;TurnTypeExtensions.getTurnType() 仅为可选参考,未覆盖的类型需 HMI 自行映射。
  • 图标与气泡样式由 TSS 资源(street_bubble.layout + bubble/turn/ 纹理)决定,与 HMI 采用哪套 TurnType 映射逻辑无关。
  • 导航停止、路线变化或重算路时,应调用 disableAllTurnBubbles()

相关指南