修改导航界面

使用 Navigation SDK for iOS,您可以通过确定将哪些内置界面控件和元素显示在地图上,以及允许使用哪些手势,来修改地图的用户体验。您还可以修改导航界面的视觉外观。如需了解有关可以对导航界面进行哪些修改的准则,请参阅“政策”页面

地图界面控件

Navigation SDK 提供了一些内置界面控件,类似于 iOS 版 Google 地图应用中的控件。您可以使用 GMSUISettings 类切换这些控件的可见性。您对该类所做的更改会立即体现在地图上。

罗盘

Navigation SDK 提供了一个罗盘图形,该图形在特定情况下且仅在启用时才会显示在地图右上角。仅当镜头的朝向使得其方向角不是正北(非零方位)时,才会显示罗盘。当用户点击罗盘时,镜头会以动画方式恢复到方位为零(默认朝向)的位置,并且罗盘会在不久后逐渐消失。

如果启用了导航并将镜头模式设置为“跟随”,罗盘仍保持可见状态,并且点按罗盘可在倾斜的镜头视角和总览的镜头视角之间切换。

默认情况下,罗盘处于停用状态。您可以通过将 GMSUISettingscompassButton 属性设置为 YES 来启用罗盘。不过,您无法强制始终显示罗盘。

Swift

mapView.settings.compassButton = true

Objective-C

mapView.settings.compassButton = YES;

“我的位置”按钮

仅当启用了“我的位置”按钮时,“我的位置”按钮才会显示在屏幕右下角。当用户点击该按钮时,如果当前已知用户的位置,相机会以动画形式聚焦于用户的当前位置。您可以通过将 GMSUISettingsmyLocationButton 属性设置为 YES 来启用该按钮。

Swift

mapView.settings.myLocationButton = true

Objective-C

mapView.settings.myLocationButton = YES;

“重新居中”按钮

启用导航后,当用户滚动地图视图时,“重新中心”按钮会显示;当用户点按地图以重新居中时,“重新中心”按钮会消失。若要允许显示“重新居中”按钮,请将 GMSUISettingsrecenterButtonEnabled 属性设置为 YES。如需禁止显示“重新居中”按钮,请将 recenterButtonEnabled 设置为 NO

Swift

mapView.settings.isRecenterButtonEnabled = true

Objective-C

mapView.settings.recenterButtonEnabled = YES;

地图界面配件

Navigation SDK 提供在导航期间显示的界面配件,类似于 iOS 版 Google 地图应用中的配件。您可以按照本部分中的说明调整这些控件的可见性或视觉外观。您在此处所做的更改会反映到驾驶员下次出行期间。

在导航期间,导航页眉显示在屏幕顶部,导航页脚显示在底部。导航标题会显示路线的下一个转弯的街道名称和方向,以及下一个转弯的方向。导航页脚会显示到目的地的预计时间和距离,以及预计到达时间。

您可以使用以下属性以编程方式切换导航页眉和页脚的可见性并设置其颜色:

  • navigationHeaderEnabled - 控制导航标题是否可见(默认值为 true)。
  • navigationFooterEnabled - 控制导航页脚是否可见(默认值为 true)。
  • navigationHeaderPrimaryBackgroundColor - 设置导航标题的主要背景颜色。
  • navigationHeaderSecondaryBackgroundColor - 设置导航标头的辅助背景颜色。

以下代码示例展示了如何启用页眉和页脚的可见性,然后将 navigationHeaderPrimaryBackgroundColor 设置为蓝色,并将 navigationHeaderSecondaryBackgroundColor 设置为红色。

Swift

mapView.settings.isNavigationHeaderEnabled = true
mapView.settings.isNavigationFooterEnabled = true
mapView.settings.navigationHeaderPrimaryBackgroundColor = .blue
mapView.settings.navigationHeaderSecondaryBackgroundColor = .red

Objective-C

mapView.settings.navigationHeaderEnabled = YES;
mapView.settings.navigationFooterEnabled = YES;
mapView.settings.navigationHeaderPrimaryBackgroundColor = [UIColor blueColor];
mapView.settings.navigationHeaderSecondaryBackgroundColor = [UIColor redColor];

您可以自定义应用,只需将辅助导航标题视图替换为您自己的自定义配件视图即可。为此,您需要创建一个实现 GMSNavigationAccessoryView 协议的视图。此协议有一个必需的方法:-heightForAccessoryViewConstrainedToSize:onMapView:。您将获得视图在给定 mapView 上的最大可用尺寸,并且必须提供视图所需的高度。

然后,您可以调用 setHeaderAccessoryView:,将此视图传递给 mapView。mapView 会以动画形式呈现当前的所有视图,然后在自定义视图中添加动画效果。导航标题必须可见,才能显示自定义视图。

如需移除自定义标头配件视图,请将 nil 传递给 setHeaderAccessoryView:

如果您的视图必须随时更改大小,那么您可以调用 invalidateLayoutForAccessoryView:,并传入需要更改大小的视图。

示例

以下代码示例演示了一个实现 GMSNavigationAccessoryView 协议的自定义视图。然后,该自定义视图用于设置自定义导航标头配件视图。

Swift

class MyCustomView: UIView, GMSNavigationAccessoryView {
…
  func heightForAccessoryViewConstrained(to size: CGSize, on mapView: GMSMapView) -> CGFloat {
    // viewHeight gets calculated as the height your view needs.
    return viewHeight
  }
…
}

let customView = MyCustomView(...)
mapView.setHeaderAccessory(customView)

// At some later point customView changes size.
mapView.invalidateLayout(forAccessoryView: customView)

// Remove the custom header accessory view.
mapView.setHeaderAccessory(nil)

Objective-C

@interface MyCustomView : UIView <GMSNavigationAccessoryView>
…
@end

@implementation MyCustomView
…
- (CGFloat)heightForAccessoryViewConstrainedToSize:(CGSize)size onMapView:(GMSMapView *)mapView {
  // viewHeight gets calculated as the height your view needs.
  return viewHeight;
}
…
@end

MyCustomView *customView = [[MyCustomView alloc] init…];
[_mapView setHeaderAccessoryView:customView];

// At some later point customView changes size.
[_mapView invalidateLayoutForAccessoryView:customView];

// Remove the custom header accessory view.
[_mapView setHeaderAccessoryView:nil];

路线列表

您可以在应用中提供分步说明。以下示例展示了一种可行的方法。这些步骤可能会因您自己的实现而异。

  1. GMSNavigator(导航器)上的 setDestinations 成功完成且导航器上的 guidanceActive 已启用后,启用入口点按钮。
  2. 当用户点按入口点按钮时,使用与 GMSMapView (mapView) 关联的导航器创建一个 GMSNavigationDirectionsListController(控制器)。
  3. 将控制器添加到 UIViewController 的实例(视图控制器),并将 directionsListView 添加为视图控制器的子视图。控制器上的 reloadDatainvalidateLayout 方法应像调用 UICollectionView 方法一样。
  4. 将视图控制器推送到应用的视图控制器层次结构。

以下代码示例展示了如何添加 DirectionsListViewController

Swift

override func viewDidLoad() {
  super.viewDidLoad()
  // Add the directionsListView to the host view controller's view.
  let directionsListView = directionsListController.directionsListView
  directionsListView.frame = self.view.frame
  self.view.addSubview(directionsListView)
  directionsListView.translatesAutoresizingMaskIntoConstraints = false
  directionsListView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
  directionsListView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
  directionsListView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
  directionsListView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
  ...
}

override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(animated)
  // Ensure data is fresh when the view appears.
  directionsListController.reloadData()
  ...
}

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
  super.willTransition(to: newCollection, with: coordinator)
  // Invalidate the layout during rotation.
  coordinator.animate(alongsideTransition: {_ in
    self.directionsListController.invalidateLayout()
  })
  ...
}

Objective-C

- (void)viewDidLoad {
  [super viewDidLoad];
  // Add the directionsListView to the host view controller's view.
  UIView *directionsListView = _directionsListController.directionsListView;
  directionsListView.frame = self.view.bounds;
  [self.view addSubview:directionsListView];
  directionsListView.translatesAutoresizingMaskIntoConstraints = NO;
  [directionsListView.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES;
  [directionsListView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor].active = YES;
  [directionsListView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor].active = YES;
  [directionsListView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
  ...
}

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  // Ensure data is fresh when the view appears.
  [_directionsListController reloadData];
  ...
}

- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection
              withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
  [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
  void(^animationBlock)(id <UIViewControllerTransitionCoordinatorContext>context) =
      ^void(id <UIViewControllerTransitionCoordinatorContext>context) {
    [_directionsListController invalidateLayout];
  };
  // Invalidate the layout during rotation.
  [coordinator animateAlongsideTransition:animationBlock
                               completion:nil];
  ...
}

...

行程进度条

添加到导航中的行程进度条。

行程进度条是一个竖线,在导航开始时,显示在地图尾部右侧边缘。启用后,它会显示整个行程的概览,以及司机的目的地和当前位置。

这有助于驾驶员快速预测任何即将发生的问题,例如路况,而无需放大。然后,他们可以根据需要重新规划行程。如果驾驶员重新规划行程,进度条会重置,就像从该点开始了新行程一样。

行程进度条会显示以下状态指示器:

  • 路况 - 即将到来的流量的状态。

  • 当前位置 - 驾驶员在行程中的当前位置。

  • 已用路线 - 行程的已用部分。

通过在 GMSUISettings 中设置 navigationTripProgressBarEnabled 属性,即可启用行程进度条。

Swift

mapView.settings.isNavigationTripProgressBarEnabled = true

Objective-C

mapView.settings.navigationTripProgressBarEnabled = YES;

红绿灯和停车标志

导航期间显示的停车标志和交通信号灯。

您可以在mapView中启用红绿灯和停车标志。借助此功能,驾驶员可以在路线上显示红绿灯或停车标志图标,从而为更高效、更准确的行程提供更好的背景信息。

默认情况下,Navigation SDK for iOS 中的红绿灯和停车标志处于停用状态。如需启用此功能,请分别调用每个选项的 GMSMapView 设置:showsTrafficLightsshowsStopSigns


Swift

mapView.settings.showsTrafficLights = YES;
mapView.settings.showsStopSigns = YES;

Objective-C

mapView.settings.showsTrafficLights = true;
mapView.settings.showsStopSigns = true;

速度计控件

启用导航后,Navigation SDK for iOS 会在地图右下角显示一个速度限制控件,以显示当前速度限制。当驾驶员超过速度限制时,该控件会展开即可显示驾驶员当前速度的第二个速度计。

您可以设置警报级别,以便在驾驶员超过速度限制指定量时更改速度计显示内容的格式。例如,您可以指定当驾驶员超过速度限制 5 英里/小时时以红色文本显示当前速度,当驾驶员超过速度限制 10 英里/小时时显示红色背景颜色。

如需显示速度限制控件,请将 GMSUISettingsshouldDisplaySpeedometer 属性设置为 YES。如需停止显示速度限制控件,请将 shouldDisplaySpeedometer 设置为 NO

Swift

mapView.shouldDisplaySpeedometer = true

Objective-C

mapView.shouldDisplaySpeedometer = YES;

如需详细了解如何为速度计设置提醒,请参阅配置速度计提醒

目的地标记

您可以通过设置 GMSUISettingsshowsDestinationMarkers 属性来显示或隐藏给定路线的目的地标记。以下示例展示了如何关闭目的地标记。

Swift

mapView.settings.showsDestinationMarkers = false

Objective-C

mapView.settings.showsDestinationMarkers = NO;

地图体验功能

借助 Navigation SDK,您可以进一步自定义用户的导航体验。您对实例所做的更改会在驱动程序下一次更新应用时反映。

停用默认地图手势

您可以通过设置 GMSUISettings 类(作为 GMSMapView 的一个属性提供)的属性来停用地图上的默认手势。您可以编程方式启用或停用以下手势。请注意,停用手势不会限制以编程方式访问相机设置。

  • scrollGestures - 控制是启用还是停用滚动手势。如果处于启用状态,用户可以通过滑动来平移摄像头。
  • zoomGestures - 控制是启用或停用缩放手势。启用后,用户可以通过点按两次、双指点按或双指张合来缩放摄像头。请注意,如果启用了 scrollGestures,点按两次或双指张合可能会将镜头平移到指定的点。
  • tiltGestures - 控制是启用还是停用倾斜手势。如果处于启用状态,用户可以通过双指垂直向下或向上滑动来倾斜相机。
  • rotateGestures - 控制是启用或停用旋转手势。启用后,用户可以使用双指旋转手势来旋转摄像头。

此例中,平移和缩放手势均已停用。

Swift

mapView.settings.scrollGestures = false
mapView.settings.zoomGestures = false

Objective-C

mapView.settings.scrollGestures = NO;
mapView.settings.zoomGestures = NO;

位置控件和界面元素

您可以使用以下属性,相对于导航页眉和页脚的位置来确定控件和其他界面元素的位置:

  • navigationHeaderLayoutGuide
  • navigationFooterLayoutGuide

以下代码示例展示了如何根据布局指南在地图视图中放置一对标签:

Swift

/* Add a label to the top left, positioned below the header. */
let topLabel = UILabel()
topLabel.text = "Top Left"
mapView.addSubview(topLabel)
topLabel.translatesAutoresizingMaskIntoConstraints = false
topLabel.topAnchor.constraint(equalTo: mapView.navigationHeaderLayoutGuide.bottomAnchor).isActive = true
topLabel.leadingAnchor.constraint(equalTo: mapView.leadingAnchor).isActive = true

/* Add a label to the bottom right, positioned above the footer. */
let bottomLabel = UILabel()
bottomLabel.text = "Bottom Right"
mapView.addSubview(bottomLabel)
bottomLabel.translatesAutoresizingMaskIntoConstraints = false
bottomLabel.bottomAnchor.constraint(equalTo: mapView.navigationFooterLayoutGuide.topAnchor).isActive = true
bottomLabel.trailingAnchor.constraint(equalTo: mapView.trailingAnchor).isActive = true

Objective-C

/* Add a label to the top left, positioned below the header. */
UILabel *topLabel = [[UILabel alloc] init];
topLabel.text = @"Top Left";
[view addSubview:topLabel];
topLabel.translatesAutoresizingMaskIntoConstraints = NO;
[topLabel.topAnchor
    constraintEqualToAnchor:mapView.navigationHeaderLayoutGuide.bottomAnchor].active = YES;
[topLabel.leadingAnchor constraintEqualToAnchor:mapView.leadingAnchor].active = YES;

/* Add a label to the bottom right, positioned above the footer. */
UILabel *bottomLabel = [[UILabel alloc] init];
bottomLabel.text = @"Bottom Right";
[view addSubview:bottomLabel];
bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;
[bottomLabel.bottomAnchor
    constraintEqualToAnchor:mapView.navigationFooterLayoutGuide.topAnchor].active = YES;
[bottomLabel.trailingAnchor constraintEqualToAnchor:mapView.trailingAnchor].active = YES;

隐藏备选路线

当界面因信息过多而变得杂乱无章时,您可以通过以下方法减少杂乱:显示的备用路线少于默认路线(两条),或者不显示任何备选路线。您可以在提取路由之前配置此选项,方法是配置 GMSNavigationRoutingOptions,并将 alternateRoutesStrategy 设置为以下枚举值之一:

枚举值说明
GMSNavigationAlternateRoutesStrategyAll 默认。最多显示两条备选路线。
GMSNavigationAlternativeRoutesStrategyOne 显示一条备选路线(如果有的话)。
GMSNavigationAlternateRoutesStrategyNone 隐藏备选路线。

示例

以下代码示例演示了如何完全隐藏备选路线。

Swift

let routingOptions = GMSNavigationRoutingOptions(alternateRoutesStrategy: .none)
navigator?.setDestinations(destinations,
                           routingOptions: routingOptions) { routeStatus in
  ...
}

Objective-C

GMSNavigationRoutingOptions *routingOptions = [[GMSNavigationRoutingOptions alloc] initWithAlternateRoutesStrategy:GMSNavigationAlternateRoutesStrategyNone];
[navigator setDestinations:destinations
            routingOptions:routingOptions
                  callback:^(GMSRouteStatus routeStatus){...}];