탐색 UI 수정

iOS용 Navigation SDK를 사용하면 지도에 표시할 기본 제공 UI 컨트롤과 요소, 허용되는 동작을 지정하여 지도의 사용자 환경을 수정할 수 있습니다. 내비게이션 UI의 시각적 모양을 수정할 수도 있습니다. 허용되는 내비게이션 UI 수정사항에 관한 가이드라인은 정책 페이지를 참고하세요.

지도 UI 컨트롤

Navigation SDK는 iOS용 Google 지도 애플리케이션에 있는 것과 유사한 몇 가지 내장 UI 컨트롤을 제공합니다. GMSUISettings 클래스를 사용하여 이러한 컨트롤의 표시 여부를 설정할 수 있습니다. 이 클래스의 변경사항은 지도에 즉시 반영됩니다.

나침반

Navigation SDK는 특정 상황에서 지도의 오른쪽 위 모서리에 표시되는 나침반 그래픽을 제공하며, 이 그래픽은 사용 설정된 경우에만 표시됩니다. 나침반은 카메라의 방향이 정확한 북쪽이 아닌 방향 (0이 아닌 방위)이 되도록 설정되어 있을 때만 표시됩니다. 사용자가 나침반을 클릭하면 카메라가 방위가 0인 위치 (기본 방향)로 다시 움직이고 나침반은 바로 사라집니다.

내비게이션이 사용 설정되어 있고 카메라 모드가 '이행 중'으로 설정된 경우 나침반이 계속 표시되고 나침반을 탭하면 기울어진 카메라 관점과 개요 카메라 관점 간에 전환됩니다.

나침반은 기본적으로 비활성화되어 있습니다. 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:라는 필수 메서드가 하나 있습니다. 지정된 지도 뷰에서 뷰에 사용할 수 있는 최대 크기가 제공되며 뷰에 필요한 높이를 제공해야 합니다.

그런 다음 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. 사용자가 진입점 버튼을 탭하면 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에서 신호등과 정지 표지판을 사용 설정할 수 있습니다. 이 기능을 사용하면 사용자가 경로에 신호등 또는 정지 표지판 아이콘을 표시하도록 설정하여 더 효율적이고 정확한 이동을 위한 더 나은 맥락을 제공할 수 있습니다.

기본적으로 iOS용 Navigation SDK에서는 신호등과 정지 표지판이 사용 중지되어 있습니다. 이 기능을 사용 설정하려면 각 옵션(showsTrafficLightsshowsStopSigns)의 GMSMapView 설정을 개별적으로 호출합니다.


Swift

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

Objective-C

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

속도계 제어

내비게이션이 사용 설정되어 있고 이동 모드가 운전으로 설정된 경우 iOS용 Navigation SDK는 지도의 하단에 현재 속도 제한을 보여주는 속도 제한 컨트롤을 표시합니다. 운전자가 속도 제한을 초과하면 컨트롤이 확장되어 운전자의 현재 속도가 표시된 두 번째 속도계가 표시됩니다.

운전자가 속도 제한을 지정된 양만큼 초과할 때 속도계 디스플레이의 형식을 변경하도록 알림 수준을 설정할 수 있습니다. 예를 들어 운전자가 제한 속도를 5mph 초과하면 현재 속도가 빨간색 텍스트 색상으로 표시되고, 10mph 초과하면 빨간색 배경 색상으로 표시되도록 지정할 수 있습니다.

속도 제한 제어를 표시하려면 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는 사용자의 탐색 환경을 추가로 맞춤설정하는 기능을 제공합니다. 인스턴스에 적용한 변경사항은 사용자가 앱을 다음에 업데이트할 때 반영됩니다.

기본 지도 동작 사용 중지

GMSMapView의 속성으로 사용할 수 있는 GMSUISettings 클래스의 속성을 설정하여 지도에서 기본 제스처를 비활성화할 수 있습니다. 다음 제스처는 프로그래밍 방식으로 활성화/비활성화할 수 있습니다. 제스처를 비활성화하더라도 카메라 설정에 대한 프로그래매틱 액세스는 제한되지 않습니다.

  • scrollGestures: 스크롤 제스처의 사용 설정 여부를 제어합니다. 이 제스처가 활성화된 경우, 사용자가 카메라를 스와이프해서 패닝할 수 있습니다.
  • zoomGestures: 확대/축소 제스처의 사용 설정 여부를 제어합니다. 이 제스처가 활성화된 경우, 사용자가 카메라를 두 번 누르거나 두 손가락으로 누르거나 손가락을 모아서 확대/축소할 수 있습니다. scrollGestures가 활성화되었을 때 두 번 누르기나 손가락 모으기 제스처로 카메라를 지정된 지점으로 패닝할 수 있습니다.
  • tiltGestures: 틸트 제스처의 사용 설정 여부를 제어합니다. 이 제스처가 활성화된 경우, 사용자가 카메라를 똑바로 위아래로 스와이프해서 틸트할 수 있습니다.
  • rotateGestures: 회전 제스처의 사용 설정 여부를 제어합니다. 이 제스처가 활성화된 경우, 사용자가 두 손가락 회전 제스처를 사용해서 카메라를 회전할 수 있습니다.

이 예시에서는 화면 이동과 확대/축소 제스처가 모두 비활성화되어 있습니다.

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){...}];