修改导航界面

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

地图界面控件

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

罗盘

Navigation SDK 提供的指南针图形会在特定情况下出现在地图的右上角(仅当已启用时)。仅当相机的朝向使得其具有非正北方(非零方位)的方位时,才会显示罗盘。当用户点击指南针时,摄像头以动画呈现方式恢复到方位为零(默认朝向)的位置,并且指南针会在之后不久逐渐消失。

如果导航已启用且相机模式设为“跟随”,罗盘将保持可见状态,点按罗盘即可在倾斜视图和概览视图之间切换。

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

Swift

mapView.settings.compassButton = true

Objective-C

mapView.settings.compassButton = YES;

“我的位置”按钮

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

Swift

mapView.settings.myLocationButton = true

Objective-C

mapView.settings.myLocationButton = YES;

“重新将当前位置设为地图的中心”按钮

启用导航功能后,当用户滚动地图视图时,系统会显示重新居中按钮,当用户点按以重新居中地图时,该按钮会消失。如需允许显示“最近用过”按钮,请将 GMSUISettingsrecenterButtonEnabled 属性设置为 true。如需阻止显示“最近用过”按钮,请将 recenterButtonEnabled 设为 false

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 添加为视图控制器的子视图。应像对 UICollectionView 一样调用控制器上的 reloadDatainvalidateLayout 方法。
  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 = true
mapView.settings.showsStopSigns = true

Objective-C

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

速度计控制

启用导航功能并将行驶模式设为“驾车”后,Navigation SDK for iOS 会在地图的下角显示一个限速控件,用于显示当前限速。当驾驶员超速时,该控件会展开,显示第二个速度计,其中显示驾驶员的当前速度。

您可以设置提醒级别,以便在驾驶员超出速度限制的指定幅度时更改速度表显示的格式。例如,您可以指定当驾驶员超速 5 英里/小时时,当前速度显示为红色文本,当驾驶员超速 10 英里/小时时,当前速度显示为红色背景。

如需显示限速控制,请将 GMSUISettingsshouldDisplaySpeedometer 属性设置为 true。如需停用限速控件的显示,请将 shouldDisplaySpeedometer 设置为 false

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;

隐藏备选路线

如果界面因信息过多而显得杂乱无序,您可以通过显示的备选路线数量少于默认值(2 条)或根本不显示备选路线来减少杂乱。您可以在提取路线之前配置此选项,方法是配置 GMSNavigationRoutingOptions,并使用以下枚举值之一设置 alternateRoutesStrategy

枚举值说明
GMSNavigationAlternateRoutesStrategyAll 默认。最多显示两个备选路线。
GMSNavigationAlternateRoutesStrategyOne 显示一条备选路线(如果有)。
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){...}];