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

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

地図 UI コントロール

Navigation SDK には、Google Maps for iOS アプリのものと同様の組み込み UI コントロールがいくつか用意されています。これらのコントロールの表示を切り替えるには、GMSUISettings クラスを使用します。このクラスで加えた変更は、すぐに地図に反映されます。

コンパス

Navigation SDK には、特定の状況下で、有効にした場合にのみ地図の右上に表示されるコンパス グラフィックが用意されています。コンパスが表示されるのは、カメラの向きが真北(ゼロではない方位)以外の方角になっている場合に限られます。ユーザーがコンパスをクリックすると、カメラが方向指定 0 の位置(デフォルトの向き)にアニメーションで戻り、すぐにコンパスがフェードアウトします。

ナビゲーションが有効になっていて、カメラモードが [フォロー中] に設定されている場合、コンパスは表示されたままになり、コンパスをタップすると、傾斜したカメラと全体を表示したカメラが切り替わります。

コンパスはデフォルトで無効になっています。コンパスを有効にするには、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 に設定します。中央揃えボタンが表示されないようにするには、recenterButtonEnabledNO に設定します。

Swift

mapView.settings.isRecenterButtonEnabled = true

Objective-C

mapView.settings.recenterButtonEnabled = YES;

マップ UI アクセサリ

Navigation SDK には、Google Maps for iOS アプリと同様にナビゲーション中に表示される 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 は、現在のビューをすべてアニメーション化してから、カスタムビュー内でアニメーション化します。カスタムビューを表示するには、ナビゲーション ヘッダーを表示する必要があります。

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

ビューのサイズを随時変更する必要がある場合は、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. ユーザーがエントリ ポイント ボタンをタップしたときに、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)
  // 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];
  ...
}

...

ルートの進行状況バー

ナビゲーションに追加されたルートの進行状況バー。

ルートの進行状況バーは、ナビゲーションの開始時に地図の右端に表示される垂直バーです。有効にすると、ドライバーの目的地と現在地とともに、ルート全体の概要が表示されます。

これにより、ドライバーはズームインすることなく、交通状況などの今後の問題をすばやく予測できます。その後、必要に応じてルートを変更できます。運転手がルートを変更する場合、進行状況バーは、その地点から新しいルートが開始されているかのようにリセットされます。

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

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

  • 現在地 - ルートにおけるドライバーの現在地。

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

ルートの進行状況バーを有効にするには、GMSUISettingsnavigationTripProgressBarEnabled プロパティを設定します。

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

アラートレベルを設定すると、ドライバーが制限速度を指定した分だけ超えたときに、速度計の表示形式を変更できます。たとえば、現在の速度が、速度制限を時速 5 マイル(5 マイル)以上超えたときは赤のテキスト色で表示され、時速 10 マイル(10 マイル)を超えたときは赤の背景色で表示されるように指定できます。

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

Swift

mapView.shouldDisplaySpeedometer = true

Objective-C

mapView.shouldDisplaySpeedometer = YES;

速度計のアラートの設定の詳細については、速度計のアラートを構成するをご覧ください。

目的地のマーカー

GMSUISettingsshowsDestinationMarkers プロパティを設定すると、特定の経路の目的地マーカーの表示と非表示を切り替えることができます。以下の例では、目的地のマーカーをオフにしています。

Swift

mapView.settings.showsDestinationMarkers = false

Objective-C

mapView.settings.showsDestinationMarkers = NO;

マップの機能

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

デフォルトの地図操作を無効にする

地図上のデフォルトの操作を無効にするには、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

次のコードサンプルでは、レイアウト ガイドを使用して、地図ビュー内にラベルのペアを配置しています。

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 デフォルト。最大 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){...}];