Modyfikowanie interfejsu użytkownika

Korzystając z pakietu Navigation SDK na iOS, możesz modyfikować wrażenia użytkownika z mapą, określając, które z wbudowanych elementów sterujących interfejsu i elementów mają się pojawiać na mapie oraz które gesty są dozwolone. Możesz też zmienić wygląd interfejsu nawigacji. Wskazówki dotyczące dopuszczalnych modyfikacji interfejsu nawigacji znajdziesz na stronie z zasadami.

Elementy sterujące interfejsu mapy

Pakiet Navigation SDK udostępnia wbudowane elementy sterujące interfejsu podobne do tych, które można znaleźć w aplikacji Mapy Google na iOS. Widoczność tych elementów sterujących możesz przełączać za pomocą klasy GMSUISettings. Zmiany wprowadzone w tej klasie są natychmiast odzwierciedlane na mapie.

Kompas

Pakiet Navigation SDK udostępnia grafikę kompasu, która w określonych okolicznościach pojawia się w prawym górnym rogu mapy i tylko wtedy, gdy jest włączona. Gdy użytkownik kliknie kompas, kamera animuje powrót do pozycji z orientacją 0 (orientacja domyślna), a kompas po chwili znika.

Jeśli nawigacja jest włączona, a tryb kamery jest ustawiony na „śledzenie”, kompas pozostaje widoczny. Kliknięcie kompasu przełącza widok kamery między perspektywą pochyloną a widokiem ogólnym.

Aby uniknąć rozpraszania uwagi kierowcy, kompas pozostaje w tym samym miejscu, jeśli nagłówek (w trybie portretowym) rozszerza się i koliduje z domyślną pozycją kompasu. Jeśli dodasz dodatkowy niestandardowy element sterujący nagłówka lub widok akcesoriów nagłówka, kompas zostanie ukryty, aby uniknąć konfliktów interfejsu.

Kompas obsługuje tryby dzienny i nocny, a także tryb ciemny.

Kompas jest domyślnie włączony w wersji 11.0.0 i nowszych. Możesz wyłączyć kompas, ustawiając wartość właściwości compassButton obiektu GMSUISettings na false.

Swift

mapView.settings.compassButton = false

Objective-C

mapView.settings.compassButton = NO;

Przycisk Moja lokalizacja

Przycisk Moja lokalizacja pojawia się w prawym dolnym rogu ekranu tylko wtedy, gdy przycisk lokalizacji jest włączony. Gdy użytkownik kliknie ten przycisk, kamera animuje się, aby skupić się na bieżącej lokalizacji użytkownika, jeśli jest ona znana. Możesz włączyć przycisk, ustawiając wartość właściwości myLocationButton elementu GMSUISettings na true.

Swift

mapView.settings.myLocationButton = true

Objective-C

mapView.settings.myLocationButton = YES;

Przycisk Wyśrodkuj

Gdy nawigacja jest włączona, przycisk wyśrodkowania pojawia się, gdy użytkownik przewija widok mapy, i znika, gdy użytkownik kliknie, aby wyśrodkować mapę. Aby przycisk wyśrodkowania był widoczny, ustaw właściwość recenterButtonEnabled elementu GMSUISettings na true. Aby zapobiec wyświetlaniu przycisku ponownego wyśrodkowania, ustaw wartość recenterButtonEnabled na false.

Swift

mapView.settings.isRecenterButtonEnabled = true

Objective-C

mapView.settings.recenterButtonEnabled = YES;

Akcesoria interfejsu mapy

Pakiet Navigation SDK udostępnia akcesoria interfejsu, które pojawiają się podczas nawigacji podobnie jak w aplikacji Mapy Google na iOS. Możesz dostosować widoczność lub wygląd tych elementów sterujących, jak opisano w tej sekcji. Wprowadzone tu zmiany zostaną odzwierciedlone podczas następnej podróży użytkownika.

Podczas nawigacji u góry ekranu wyświetla się nagłówek nawigacji, a u dołu – stopka nawigacji. Nagłówek nawigacji pokazuje nazwę ulicy i kierunek następnego skrętu na trasie, a także kierunek kolejnego skrętu. Stopka nawigacji pokazuje szacowany czas i odległość do miejsca docelowego, a także szacowany czas dotarcia.

Możesz przełączać widoczność nagłówka i stopki nawigacji oraz ustawiać ich kolory automatycznie za pomocą tych właściwości:

W przykładzie poniżej pokazujemy, jak włączyć widoczność nagłówka i stopki, a następnie ustawić kolor navigationHeaderPrimaryBackgroundColor na niebieski i navigationHeaderSecondaryBackgroundColor na czerwony.

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];

Możesz dostosować aplikację, zastępując widok nagłówka nawigacji dodatkowej własnym widokiem akcesoriów. W tym celu utwórz widok, który implementuje protokół GMSNavigationAccessoryView. Ten protokół ma jedną wymaganą metodę: -heightForAccessoryViewConstrainedToSize:onMapView:. Otrzymasz maksymalny dostępny rozmiar widoku w danym mapView i musisz podać wysokość, której wymaga Twój widok.

Następnie możesz przekazać ten widok do mapView, wywołując setHeaderAccessoryView: mapView animuje wyjście wszystkich bieżących widoków, a potem animuje wejście Twojego niestandardowego widoku. Aby widok niestandardowy mógł się wyświetlać, nagłówek nawigacji musi być widoczny.

Aby usunąć widok akcesoriów niestandardowego nagłówka, przekaż nil do setHeaderAccessoryView:.

Jeśli widok musi zmienić rozmiar w dowolnym momencie, możesz wywołać funkcję invalidateLayoutForAccessoryView:, przekazując widok, który musi zmienić rozmiar.

Przykład

Poniższy przykładowy kod pokazuje widok niestandardowy, który implementuje protokół GMSNavigationAccessoryView. Ten widok niestandardowy jest następnie używany do ustawiania niestandardowego widoku akcesoriów nagłówka nawigacji.

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];

Kolory nagłówka w trybie słabego oświetlenia

Pakiet Navigation SDK na iOS oblicza sugerowany tryb jasny na podstawie pory dnia i bieżącej lokalizacji urządzenia, a gdy sugerowany tryb się zmienia (np. o wschodzie lub zachodzie słońca), wywołuje metodę detektora GMSNavigatorListener.didChangeSuggestedLightingMode. Możesz programowo modyfikować działanie trybu słabego oświetlenia w następujący sposób:

Lista wskazówek

W aplikacji możesz podać szczegółowe instrukcje. Poniższy przykład pokazuje jeden ze sposobów, w jaki możesz to zrobić. Te kroki mogą się różnić w zależności od Twojej implementacji.

  1. Włącz przycisk punktu wejścia po pomyślnym zakończeniu setDestinations w GMSNavigator (navigator) i włączeniu guidanceActive w navigator.
  2. Gdy użytkownik kliknie przycisk punktu wejścia, utwórz GMSNavigationDirectionsListController (kontroler) z nawigatorem powiązanym z GMSMapView (mapView).
  3. Dodaj kontroler do instancji UIViewController (kontroler widoku) i dodaj directionsListView jako podrzędny widok kontrolera widoku. Metody reloadData i invalidateLayout na kontrolerze powinny być wywoływane tak samo jak w przypadku metody UICollectionView.
  4. Umieść kontroler widoku w hierarchii kontrolerów widoku aplikacji.

Poniższy przykładowy kod pokazuje, jak dodać 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];
  ...
}

...

Pasek postępu przejazdu

Do nawigacji dodano pasek postępu podróży.

Pasek postępu podróży to pionowy pasek, który pojawia się po stronie początkowej/głównej mapy po rozpoczęciu nawigacji. Gdy ta opcja jest włączona, wyświetla się podsumowanie całej podróży wraz z miejscem docelowym i aktualną pozycją użytkownika.

Dzięki temu użytkownicy mogą szybko przewidzieć wszelkie nadchodzące problemy, takie jak korki, bez konieczności powiększania mapy. W razie potrzeby może zmienić trasę. Jeśli użytkownik zmieni trasę, pasek postępu zostanie zresetowany, tak jakby od tego momentu rozpoczęła się nowa podróż.

Na pasku postępu podróży wyświetlane są te wskaźniki stanu:

  • Stan ruchu – stan ruchu na drodze przed Tobą.

  • Bieżąca lokalizacja – bieżąca lokalizacja kierowcy podczas przejazdu.

  • Przebyta trasa – przebyta część podróży.

Włącz pasek postępu przejazdu, ustawiając właściwość navigationTripProgressBarEnabled w GMSUISettings.

Swift

mapView.settings.isNavigationTripProgressBarEnabled = true

Objective-C

mapView.settings.navigationTripProgressBarEnabled = YES;

Położenie paska postępu podróży

  • Lewa strona paska jest mniej więcej wyrównana z lewą stroną prędkościomierza, logo Google i przycisku Wyśrodkuj (gdy jest widoczny). Szerokość to 12 pt.
  • Pasek postępu podróży dynamicznie reaguje na przestrzeń pionową na ekranie. Dolna krawędź paska znajduje się 210 pt od dolnej krawędzi ekranu. Górna krawędź paska postępu trasy znajduje się co najmniej 170 pkt od górnej krawędzi ekranu, a maksymalna wysokość paska wynosi 400 pkt.
  • Jeśli pasek postępu podróży nakłada się na nagłówek nawigacji lub inne elementy interfejsu nawigacji, pojawia się pod tymi elementami.

Prompt Visibility API (eksperymentalny)

Interfejs Prompt Visibility API pozwala uniknąć konfliktów między elementami interfejsu generowanymi przez pakiet Navigation SDK a własnymi elementami interfejsu. W tym celu dodaje się detektor, który odbiera wywołanie zwrotne, zanim pojawi się element interfejsu pakietu Navigation SDK i zaraz po jego usunięciu. Więcej informacji, w tym przykłady kodu, znajdziesz w sekcji Prompt Visibility API na stronie Konfigurowanie zakłóceń w czasie rzeczywistym.

Sterowanie prędkościomierzem

Gdy nawigacja jest włączona, a tryb podróży jest ustawiony na jazdę samochodem, pakiet Navigation SDK na iOS wyświetla w dolnym rogu mapy element sterujący ograniczeniem prędkości, który pokazuje aktualne ograniczenie prędkości. Gdy kierowca przekroczy dozwoloną prędkość, element sterujący rozwinie się, aby wyświetlić drugi prędkościomierz z aktualną prędkością kierowcy.

Możesz ustawić poziomy alertów, aby zmienić formatowanie wyświetlania prędkościomierza, gdy kierowca przekroczy limit prędkości o określoną wartość. Możesz na przykład określić, że bieżąca prędkość ma być wyświetlana na czerwono, gdy kierowca przekroczy ograniczenie prędkości o 5 km/h, a na czerwonym tle, gdy przekroczy ograniczenie prędkości o 10 km/h.

Aby wyświetlić element sterujący ograniczeniem prędkości, ustaw właściwość shouldDisplaySpeedometer obiektu GMSUISettings na true. Aby wyłączyć wyświetlanie elementu sterującego ograniczeniem prędkości, ustaw dla parametru shouldDisplaySpeedometer wartość false.

Swift

mapView.settings.shouldDisplaySpeedometer = true

Objective-C

mapView.settings.shouldDisplaySpeedometer = YES;

Więcej informacji o ustawianiu alertów dotyczących prędkościomierza znajdziesz w artykule Konfigurowanie alertów dotyczących prędkościomierza.

Znaczniki miejsc docelowych

Możesz wyświetlać lub ukrywać markery miejsc docelowych na danej trasie, ustawiając właściwość showsDestinationMarkers obiektu GMSUISettings. W przykładzie poniżej pokazujemy, jak wyłączyć znaczniki miejsc docelowych.

Swift

mapView.settings.showsDestinationMarkers = false

Objective-C

mapView.settings.showsDestinationMarkers = NO;

Funkcje związane z korzystaniem z mapy

Pakiet Navigation SDK umożliwia dalsze dostosowywanie nawigacji dla użytkowników. Zmiany wprowadzone w instancji zostaną odzwierciedlone podczas następnej aktualizacji aplikacji przez użytkownika.

Wyróżnianie miejsc docelowych i wejść

Wyróżnianie miejsc docelowych i wejść

Gdy miejsce docelowe zostanie utworzone za pomocą placeID, budynek docelowy zostanie wyróżniony, a w miarę możliwości wyświetli się ikona wejścia. Te wskazówki wizualne pomagają użytkownikom rozróżniać i znajdować miejsca docelowe.

Aby utworzyć miejsce docelowe z placeID, użyj jednego z inicjatorów GMSNavigationWaypoint, które akceptują placeID. Na przykład miejsca docelowe utworzone w samouczku dotyczącym nawigowania po trasie zawierają wyróżnienie miejsca docelowego i etykiety wejścia, jeśli są dostępne.

Wyświetlanie budynków 3D podczas nawigacji

Wyświetlanie budynków 3D podczas nawigacji

Budynki 3D są domyślnie wyświetlane podczas nawigacji. Aby wyłączyć tę funkcję, ustaw wartość buildingsEnabled na false (Swift) lub NO (Objective-C).

Wyłącz domyślne gesty na mapie

Możesz wyłączyć domyślne gesty na mapie, ustawiając właściwości klasy GMSUISettings, która jest dostępna jako właściwość GMSMapView. Poniższe gesty można włączać i wyłączać programowo. Pamiętaj, że wyłączenie gestu nie ograniczy dostępu programowego do ustawień aparatu.

  • scrollGestures – określa, czy gesty przewijania są włączone czy wyłączone. Jeśli ta opcja jest włączona, użytkownicy mogą przesuwać palcem, aby obracać kamerę.
  • zoomGestures – określa, czy gesty powiększania są włączone czy wyłączone. Jeśli ta opcja jest włączona, użytkownicy mogą dwukrotnie kliknąć, kliknąć dwoma palcami lub rozciągnąć palce, aby powiększyć obraz z kamery. Pamiętaj, że gdy scrollGestures są włączone, dwukrotne kliknięcie lub ściągnięcie palców może spowodować przesunięcie kamery do określonego punktu.
  • tiltGestures – określa, czy gesty przechylania są włączone czy wyłączone. Jeśli ta funkcja jest włączona, użytkownicy mogą przechylać kamerę, przesuwając 2 palcami w pionie w dół lub w górę.
  • rotateGestures – określa, czy gesty obracania są włączone czy wyłączone. Jeśli ta opcja jest włączona, użytkownicy mogą obracać kamerę, wykonując gest obracania dwoma palcami.

W tym przykładzie wyłączono gesty przesuwania i powiększania.

Swift

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

Objective-C

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

Elementy sterujące pozycją i elementy interfejsu

Możesz ustawić elementy sterujące i inne elementy interfejsu względem pozycji nagłówka i stopki nawigacji, używając tych właściwości:

  • navigationHeaderLayoutGuide
  • navigationFooterLayoutGuide
  • bottomTrailingButtonsLayoutGuide

Poniższy przykładowy kod pokazuje, jak używać prowadnic układu do pozycjonowania pary etykiet w widoku mapy:

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;

Przykład użycia elementu bottomTrailingButtonsLayoutGuide do umieszczenia przycisku zgłaszania utrudnień w czasie rzeczywistym znajdziesz w artykule Konfigurowanie utrudnień w czasie rzeczywistym.

Ukrywanie tras alternatywnych

Gdy interfejs użytkownika jest zbyt przeładowany informacjami, możesz zmniejszyć bałagan, wyświetlając mniej tras alternatywnych niż domyślne (2) lub nie wyświetlając ich wcale. Możesz skonfigurować tę opcję przed pobraniem tras, konfigurując GMSNavigationRoutingOptions i ustawiając alternateRoutesStrategy z jedną z tych wartości typu wyliczeniowego:

Wartość typu wyliczeniowegoOpis
GMSNavigationAlternateRoutesStrategyAll Domyślny: Wyświetla maksymalnie 2 trasy alternatywne.
GMSNavigationAlternateRoutesStrategyOne Wyświetla jedną trasę alternatywną (jeśli jest dostępna).
GMSNavigationAlternateRoutesStrategyNone Ukrywa alternatywne trasy.

Przykład

Poniższy przykładowy kod pokazuje, jak całkowicie ukryć trasy alternatywne.

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