修改导航界面

使用 iOS 版 Navigation SDK,您可以确定在地图上显示哪些内置界面控件和元素,以及您允许哪些手势,从而修改用户在地图上的体验。您还可以修改 Navigation 界面的视觉外观。如需了解有关可以对 Navigation 界面进行修改的指南,请参阅政策页面

地图界面控件

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. 在用户点按入口点按钮时,创建一个 GMSNavigationDirectionsListController(控制器),其导航器与 GMSMapView (mapView) 相关联。
  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];
  ...
}

...

行程进度条

向导航中添加了行程进度条。

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

该 API 让用户能够快速预测任何即将发生的问题,例如路况信息,而无需放大。如有必要,他们可以更改行程路线。如果用户重新规划行程路线,进度条将重置,就好像从该点开始了新的行程一样。

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

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

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

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

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

Swift

mapView.settings.isNavigationTripProgressBarEnabled = true

Objective-C

mapView.settings.navigationTripProgressBarEnabled = YES;

红绿灯和停车标志

导航期间显示的停车标志和红绿灯。

您可以在mapView中启用红绿灯和停车标志。借助此功能,用户可以显示沿途的交通信号灯或停车标志图标,从而提供更好的上下文,使行程更高效、更准确。

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


Swift

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

Objective-C

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

速度计控件

启用导航并将出行方式设置为驾车后,适用于 iOS 的 Navigation SDK 会在地图下角显示一个速度限制控件,用于显示当前速度限制。当驾驶员超过速度限制时,该控件将展开,显示带有驾驶员当前速度的第二个速度计。

您可以设置警报级别,以便在驾驶员超过限速指定限值时更改速度计显示内容的格式。例如,您可以指定:当驾驶员超过限速 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;

隐藏备选路线

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

枚举值说明
GMSNavigationAlternateRoutesStrategy 全部 默认。最多显示两条备选路线。
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){...}];