请选择平台: Android iOS

配置实时中断

实时路况干扰是一系列功能,可提醒用户注意其路线上的干扰,并允许用户报告和验证他们遇到的干扰。干扰示例包括交通事故、交通拥堵、警察和测速相机、施工、车道封闭和某些天气状况。本页面介绍了实时干扰功能及其配置选项,包括使用自定义导航界面的应用需要注意的事项。

实时异常情况功能

Navigation SDK 包含以下实时中断功能,作为核心导航体验的一部分:

这些功能可配置,且默认处于启用状态。以下部分详细介绍了这些功能和可用的配置选项。

沿途异常情况互动式标注

当应用显示路线时(无论是在路线概览中还是在有效导航期间),任何当前中断都会以标注的形式显示在路线上。启用路况图层后,地图上还会显示路线外的交通中断情况。标注包含一个图标,用于指示中断类型。

沿途标注

您可以使用 shouldDisplayPrompts 控制沿路线显示中断标注,该属性还可控制在用户接近中断时显示自动提醒。

mapView.navigator.shouldDisplayPrompts = true

在用户点按标注时显示中断详情

点按中断标注可打开信息卡,查看更多详细信息。这适用于路线内和路线外标注,但路线外标注仅在启用路况图层时才会显示。该卡片会显示中断类型、上次报告的时间,有时还会显示一个选项,供您投票表明中断是否仍然存在。信息卡类型及其配置选项因用户是否处于主动导航状态而异。

在开始主动导航之前,在路线概览上显示标注信息卡

在开始导航之前,用户可以点按地图或路线概览上的路线内或路线外标注,以打开信息卡。偏离路线标注需要启用路况图层。信息卡会提供有关中断的更多详细信息。

概览信息卡片

您可以使用 showsIncidentCards 控制用户能否点按路线概览中的中断标注来显示更多信息。

mapView.settings.showsIncidentCards = true

在有效导航期间标注信息卡

在主动导航期间,用户可以点按路线内或路线外的中断标注,以打开信息卡。该卡片会显示中断类型和最后报告的时间,并包含供用户投票确认中断是否仍然存在的按钮。

用户可以针对 5 公里范围内(不包括封路)的路线内和路线外交通中断情况进行投票。Google 会处理这些投票,以帮助确定是否继续显示该路况异常。其他 Google 地图和 Navigation SDK 用户也可能会在地图上看到这些投票。

正在进行导航信息卡片

您可以使用 shouldDisplayPrompts 控制在主动导航期间是否显示中断标注以及中断标注是否可点按,该方法还可控制沿路线显示标注以及在用户接近中断时显示自动提醒。

mapView.navigator.shouldDisplayPrompts = true

在导航期间自动发出异常提醒并提供投票功能

在主动导航期间,当用户接近路线上的中断时,系统会显示一条提示,其中包含有关中断的信息以及用于投票确定中断是否仍然存在的按钮。 Google 会处理用户提交的投票,并可能会在地图上向其他 Google 地图和 Navigation SDK 用户显示这些投票,还会根据这些投票来确定是否继续显示中断。

正在进行导航信息卡片

您可以使用 shouldDisplayPrompts 配置在主动导航期间显示提醒提示,该方法还可控制沿路线标注的显示。

mapView.navigator.shouldDisplayPrompts = true

在导航期间报告异常路况

在主动导航模式下,导航界面上会显示一个按钮,用户可以通过该按钮报告沿途的新干扰。当用户点按该按钮时,系统会显示一个菜单,其中包含可报告的干扰类型。 用户提交的报告会由 Google 处理,并可能会在地图上向其他 Google 地图和 Navigation SDK 用户显示。

“报告”按钮 报告菜单

显示或隐藏标准报告按钮

您可以使用 navigationReportIncidentButtonEnabled 配置在主动导航期间标准报告按钮的可见性。

// Enables the incident reporting FAB to show in situations where incident
// reporting is possible.
mapView.settings.navigationReportIncidentButtonEnabled = true

添加自定义报告按钮

您可以在导航界面中添加自定义报告按钮,以取代标准异常报告按钮。当用户点击自定义按钮时,您可以通过调用 presentReportIncidentsPanel 方法来触发举报菜单的显示。在添加自定义报告按钮之前,请调用 reportIncidentsAvailable,验证应用是否处于主动导航状态,以及用户是否位于已启用报告功能的国家/地区。如果其中任何一项不符合要求,举报菜单都不会显示。

  // Check if reporting is available before displaying your button
  let isReportingAvailable = mapview.isIncidentReportingAvailable()
  customReportingIncidentButton.isHidden = !isReportingAvailable
  customReportingIncidentButton.addTarget(self, action: #selector(didTapReportIncidentButton), for: .touchUpInside)
  
  // Trigger the reporting flow if the button is clicked
  func didTapReportIncidentButton() {
          mapView.presentReportIncidentsPanel(self) { [weak self] error in
              guard let self = self else { return }
              if let error = error as NSError? {
                  if error.domain == GMSMapViewPresentReportIncidentPanelErrorDomain {
                      let errorCode = GMSMapViewPresentReportIncidentPanelErrorCode(rawValue: error.code)
                      
                      switch errorCode {
                      case .internal:
                          self.showErrorMessage(
                              title: "Error Presenting Report Incident Panel",
                              message: "An internal error occurred."
                          )
                      case .reportingNotAvailable:
                          self.showErrorMessage(
                              title: "Error Presenting Report Incident Panel",
                              message: "Reporting is not available."
                          )
                      case .none:
                          self.showErrorMessage(
                              title: "Error Presenting Report Incident Panel",
                              message: "An unknown error occurred."
                          )
                      }
                  } else {
                      // Handle other potential errors (e.g., network errors)
                      self.showErrorMessage(
                          title: "Error Presenting Report Incident Panel",
                          message: "An unexpected error occurred: \(error.localizedDescription)"
                      )
                  }
              }
              // If error is nil, the panel was presented successfully. You can add any extra logic here.
          }
     }

使用自定义导航界面

如果您的 Navigation SDK 实现包含自定义界面元素,则需要考虑实时中断元素,以避免冲突。

举报按钮位置

默认情况下,中断报告按钮位于地图的底部末端/尾角,对于从左到右书写的语言,该按钮位于右侧;对于从右到左书写的语言,该按钮位于左侧。如果您需要移动举报按钮,以便为自定义界面元素腾出空间,请使用 bottomTrailingButtonsLayoutGuide。

Swift

// Create a new layout guide
let topRightLayoutGuide = UILayoutGuide()
self.view.addLayoutGuide(topRightLayoutGuide)

// Activate constraints using fixed constants here as an example
// assuming the current reporting button is of fixed height
topRightLayoutGuide.topAnchor.constraint(equalTo: _mapView.navigationHeaderLayoutGuide.bottomAnchor, constant: 50).isActive = true
topRightLayoutGuide.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: -14).isActive = true

// Assign the layout guide
_mapView.bottomTrailingButtonsLayoutGuide = topRightLayoutGuide

// Create an alternate layout guide to use when the header and the footer are not full width
let topRightAlternateLayoutGuide = UILayoutGuide()
self.view.addLayoutGuide(topRightAlternateLayoutGuide)

// Activate constraints using fixed constants here as an example
// assuming the current RTD button is of fixed height
topRightAlternateLayoutGuide.topAnchor.constraint(equalTo: _mapView.navigationHeaderLayoutGuide.bottomAnchor, constant: 20).isActive = true
topRightAlternateLayoutGuide.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: -10).isActive = true

// Assign the layout guide
_mapView.bottomTrailingButtonsAlternateLayoutGuide = topRightAlternateLayoutGuide

Objective-C

// Create a new layout guide
UILayoutGuide *topRightLayoutGuide = [[UILayoutGuide alloc] init];
[self.view addLayoutGuide:topRightLayoutGuide];

// Activate constraints using fixed constants here as an example
// assuming the current RTD button is of fixed height
[[topRightLayoutGuide.topAnchor
    constraintEqualToAnchor:_mapView.navigationHeaderLayoutGuide.bottomAnchor
                   constant:50]
    setActive:YES];

[[topRightLayoutGuide.trailingAnchor
    constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor
                   constant:-14]
    setActive:YES];

// Assign the layout guide
_mapView.bottomTrailingButtonsLayoutGuide = topRightLayoutGuide;

// Create an alternate layout guide to use when the header and the footer are not full width
UILayoutGuide *topRightAlternateLayoutGuide = [[UILayoutGuide alloc] init];
[self.view addLayoutGuide:topRightAlternateLayoutGuide];

// Activate constraints using fixed constants here as an example
// assuming the current RTD button is of fixed height
[[topRightAlternateLayoutGuide.topAnchor
    constraintEqualToAnchor:_mapView.navigationHeaderLayoutGuide.bottomAnchor
                   constant:50]
    setActive:YES];

[[topRightAlternateLayoutGuide.trailingAnchor
    constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor
                   constant:-14]
    setActive:YES];

// Assign the layout guide
_mapView.bottomTrailingButtonsAlternateLayoutGuide = topRightAlternateLayoutGuide;

Prompt Visibility API(实验性)

Prompt Visibility API 可帮助您避免 Navigation SDK 生成的界面元素与您自己的自定义界面元素之间发生冲突,方法是添加一个监听器,以便在 Navigation SDK 界面元素即将显示之前以及该元素被移除后立即接收回调。您可以接收有关实时中断元素(包括信息卡、提示和中断报告菜单)以及 Navigation SDK 生成的其他通知的回调。

Swift

// Additional methods added to GMSNavigatorListener
...
func navigatorWillPresentPrompt(_ navigator: GMSNavigator) {
  // Hide any sort of custom UI element.
}

func navigatorDidDismissPrompt(_ navigator: GMSNavigator) {
  // Show any sort of custom UI element.
}
...

Objective-C

// Additional methods added to GMSNavigatorListener
...
- (void)navigatorWillPresentPrompt:(GMSNavigator *)navigator {
  // Hide any sort of custom UI element.
}

- (void)navigatorDidDismissPrompt:(GMSNavigator *)navigator {
  // Show any sort of custom UI element.
}
...