ナビゲーション UI を変更する

Navigation SDK for iOS を使用すると、地図に表示する組み込みの UI コントロールと要素や、許可する操作を指定して、地図のユーザー エクスペリエンスを変更できます。ナビゲーション UI の外観を変更することもできます。ナビゲーション UI の許容される変更に関するガイドラインについては、ポリシー ページを参照してください。

地図の UI コントロール

Navigation SDK には、iOS 版 Google マップ アプリケーションのものに似た、組み込み UI コントロールが用意されています。これらのコントロールの表示と非表示を切り替えるには、GMSUISettings クラスを使用します。このクラスに加えた変更は、すぐにマップに反映されます。

コンパス

Navigation SDK には、特定の状況下でマップの右上に表示されるコンパス グラフィックがあります。このグラフィックは、有効になっている場合にのみ表示されます。ユーザーがコンパスをクリックすると、カメラの方向指定がゼロの位置(デフォルトの向き)に戻り、その後、コンパスが徐々に消えていきます。

ナビゲーションが有効で、カメラモードが「追跡」に設定されている場合、コンパスは表示されたままになり、コンパスをタップすると、カメラの視点が傾斜視点と概要視点の間で切り替わります。

ドライバーの注意散漫を防ぐため、ヘッダー(縦向きモード)が展開してコンパスのデフォルトの位置と競合する場合、コンパスは同じ位置に留まります。セカンダリ ヘッダーのカスタム コントロールまたはヘッダー アクセサリ ビューを追加すると、UI の競合を避けるためにコンパスが非表示になります。

コンパスは、日中モードと夜間モード、ダークモードをサポートしています。

コンパスはデフォルトで無効になっています。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 に設定します。再センタリング ボタンが表示されないようにするには、recenterButtonEnabledfalse に設定します。

Swift

mapView.settings.isRecenterButtonEnabled = true

Objective-C

mapView.settings.recenterButtonEnabled = YES;

地図 UI のアクセサリ

Navigation SDK には、iOS 版 Google マップ アプリケーションに表示されるものと同様の、ナビゲーション中に表示される UI アクセサリが用意されています。このセクションで説明するように、これらのコントロールの表示 / 非表示や外観を調整できます。ここで変更した内容は、ユーザーの次回の乗車時に反映されます。

ナビゲーション中、ナビゲーション ヘッダーは画面上部に表示され、ナビゲーション フッターは画面下部に表示されます。ナビゲーション ヘッダーには、ルート上の次の曲がり角の道路名と方向、および次の曲がり角の方向が表示されます。ナビゲーション フッターには、目的地までの予定時間と距離、および予定到着時刻が表示されます。

次のプロパティを使用すると、ナビゲーション ヘッダーとフッターの表示 / 非表示を切り替えたり、色をプログラムで設定したりできます。

  • 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: という必須メソッドが 1 つあります。指定された mapView のビューで使用可能な最大サイズが渡されるので、ビューに必要な高さを指定する必要があります。

このビューを setHeaderAccessoryView: を呼び出して mapView に渡すことができます。mapView は現在のビューをアニメーションで消去し、カスタムビューをアニメーションで表示します。カスタムビューを表示できるように、ナビゲーション ヘッダーが表示されている必要があります。

カスタム ヘッダー アクセサリ ビューを削除するには、setHeaderAccessoryView:nil を渡します。

ビューのサイズをいつでも変更する必要がある場合は、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];

夜間モード

推定された照明条件が更新されると、GMSNavigatorListener.didChangeSuggestedLightingMode リスナー メソッドがトリガーされます。たとえば、デバイスの現在地で夜になった場合などです。夜間モードの動作は、次の方法でプログラム的に変更できます。

Directions List

アプリで手順ごとの道案内を提供できます。次の例は、その方法の一例です。これらの手順は、実装によって異なる場合があります。

  1. GMSNavigator(ナビゲーター)の setDestinations が正常に完了し、ナビゲーターの guidanceActive が有効になったら、エントリ ポイント ボタンを有効にします。
  2. ユーザーがエントリ ポイント ボタンをタップしたら、GMSMapViewmapView)に関連付けられたナビゲーターを使用して GMSNavigationDirectionsListController(コントローラ)を作成します。
  3. コントローラを UIViewController(ビュー コントローラ)のインスタンスに追加し、directionsListView をビュー コントローラのサブビューとして追加します。コントローラの reloadData メソッドと invalidateLayout メソッドは、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)
  // Make sure 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];
  // Make sure 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];
  ...
}

...

乗車中の進行状況バー

ナビゲーションに移動状況バーが追加されました。

ルートの進行状況バーは、ナビゲーションの開始時に地図の開始側/先頭側に表示される縦棒です。有効にすると、ユーザーの目的地と現在地とともに、旅行全体の概要が表示されます。

これにより、ズームインしなくても、トラフィックなどの今後の問題をすばやく予測できます。必要に応じて、ルートを変更できます。ユーザーがルートを変更すると、その時点から新しいルートが開始されたかのように、進行状況バーがリセットされます。

乗車中の進行状況バーには、次のステータス インジケーターが表示されます。

  • トラフィック ステータス - 今後のトラフィックのステータス。

  • 現在地 - 乗車中のドライバーの現在地。

  • ルートの経過時間 - ルートの経過時間。

GMSUISettingsnavigationTripProgressBarEnabled プロパティを設定して、乗車中の進行状況バーを有効にします。

Swift

mapView.settings.isNavigationTripProgressBarEnabled = true

Objective-C

mapView.settings.navigationTripProgressBarEnabled = YES;

乗車中の進行状況バーの位置

  • バーの左側は、スピードメーター、Google ロゴ、再センタリング ボタン(表示されている場合)の左側とほぼ揃っています。幅は 12 ポイントです。
  • 乗車中の進行状況バーは、画面の縦方向のスペースに応じて動的に変化します。バーの下端は画面の下端から 210 pt の位置に配置されます。乗車中の進行状況バーの上端は、画面の上端から 170 pt 以上離れており、バーの最大高さは 400 pt です。
  • ルートの進行状況バーがターンカードや他のナビゲーション UI 要素と重なっている場合、進行状況バーは他の要素の下に表示されます。

Prompt Visibility API(試験運用版)

プロンプトの可視性 API を使用すると、Navigation SDK によって生成された UI 要素と独自のカスタム UI 要素の競合を回避できます。Navigation SDK の UI 要素が表示される直前と、要素が削除された直後にコールバックを受け取るリスナーを追加します。コードサンプルを含む詳細については、リアルタイムの運行停止を構成するページの Prompt Visibility API セクションをご覧ください。

信号機と一時停止標識

ナビゲーション中に表示される一時停止標識と信号機。

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 は地図の下隅に制限速度コントロールを表示し、現在の制限速度を表示します。ドライバーが制限速度を超えると、コントロールが展開され、ドライバーの現在の速度を示す 2 つ目のスピードメーターが表示されます。

アラートレベルを設定すると、ドライバーが制限速度を一定量超えた場合に、スピードメーターの表示形式を変更できます。たとえば、運転者が制限速度を 5 mph 超えた場合は現在の速度を赤色のテキストで表示し、10 mph 超えた場合は赤色の背景色で表示するように指定できます。

速度制限コントロールを表示するには、GMSUISettingsshouldDisplaySpeedometer プロパティを true に設定します。制限速度コントロールの表示を無効にするには、shouldDisplaySpeedometerfalse に設定します。

Swift

mapView.shouldDisplaySpeedometer = true

Objective-C

mapView.shouldDisplaySpeedometer = YES;

スピードメーターのアラートの設定について詳しくは、スピードメーターのアラートを構成するをご覧ください。

目的地マーカー

特定のルートの目的地マーカーの表示と非表示を切り替えるには、GMSUISettingsshowsDestinationMarkers プロパティを設定します。次の例は、目的地マーカーをオフにする方法を示しています。

Swift

mapView.settings.showsDestinationMarkers = false

Objective-C

mapView.settings.showsDestinationMarkers = NO;

地図の機能

Navigation SDK を使用すると、ユーザーのナビゲーション エクスペリエンスをさらにカスタマイズできます。インスタンスに加えた変更は、ユーザーがアプリを次回更新したときに反映されます。

目的地と入口のハイライト表示

目的地と入り口のハイライト表示。

placeID を使用して目的地が作成されると、目的地となる建物がハイライト表示され、可能な場合は入り口のアイコンが表示されます。これらの視覚的な手がかりは、ユーザーが目的地を識別して移動するのに役立ちます。

placeID を使用してデスティネーションを作成するには、placeID を受け取る GMSNavigationWaypoint イニシャライザのいずれかを使用します。たとえば、ルートをナビゲートするチュートリアルで作成された目的地には、目的地がハイライト表示され、利用可能な場合は入り口のラベルが表示されます。

デフォルトの地図ジェスチャーを無効にする

地図のデフォルトのジェスチャーを無効にするには、GMSMapView のプロパティとして使用できる GMSUISettings クラスのプロパティを設定します。次のジェスチャーはプログラムで有効にしたり無効にしたりすることができます。なお、操作を無効にしても、カメラ設定へのプログラムによるアクセスは制限されません。

  • scrollGestures - スクロール ジェスチャーを有効にするか無効にするかを制御します。有効な場合、ユーザーはスワイプによってカメラをパンすることができます。
  • zoomGestures - ズーム操作を有効にするか無効にするかを制御します。有効にすると、ユーザーはダブルタップ、2 本指タップ、ピンチ操作でカメラをズームできます。scrollGestures が有効になっているときにダブルタップまたはピンチ操作を行うと、カメラが指定したポイントにパンすることがあります。
  • tiltGestures - 傾斜ジェスチャーを有効にするか無効にするかを制御します。有効にすると、2 本の指で上下にスワイプしてカメラを傾けることができます。
  • rotateGestures - 回転ジェスチャーを有効にするか無効にするかを制御します。有効にすると、ユーザーは 2 本の指で回転させるジェスチャーを使用してカメラを回転させることができます。

この例では、パンとズームの両方のジェスチャーが無効になっています。

Swift

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

Objective-C

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

位置の制御と UI 要素

次のプロパティを使用すると、ナビゲーション ヘッダーとフッターの位置を基準にして、コントロールやその他の UI 要素を配置できます。

  • navigationHeaderLayoutGuide
  • navigationFooterLayoutGuide
  • bottomTrailingButtonsLayoutGuide

次のコード例は、レイアウト ガイドを使用して地図ビューに 2 つのラベルを配置する方法を示しています。

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;

bottomTrailingButtonsLayoutGuide を使用してリアルタイムの運行状況レポート ボタンを配置する方法の例については、リアルタイムの運行状況を構成するをご覧ください。

別の経路を非表示にする

ユーザー インターフェースに表示される情報が多すぎる場合は、デフォルトの 2 つよりも少ない代替ルートを表示するか、代替ルートをまったく表示しないことで、表示をすっきりさせることができます。このオプションは、GMSNavigationRoutingOptions を構成し、次の列挙値のいずれかを使用して alternateRoutesStrategy を設定することで、ルートを取得する前に構成できます。

列挙値説明
GMSNavigationAlternateRoutesStrategyAll デフォルト。別のルートを最大 2 つ表示します。
GMSNavigationAlternateRoutesStrategyOne 別のルートが 1 つ表示されます(利用可能な場合)。
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){...}];