Modyfikowanie interfejsu użytkownika

Za pomocą pakietu Navigation SDK na iOS możesz modyfikować interfejs użytkownika na mapie, określając, które wbudowane elementy sterujące i elementy interfejsu mają się na niej pojawiać oraz które gesty mają być 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 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ą od razu widoczne 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 powróci do pozycji z kierunkiem zerowym (domyślna orientacja), a kompas zniknie po chwili.

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 ogólną.

Aby uniknąć rozproszenia uwagi kierowcy, kompas pozostaje w tym samym położeniu, jeśli nagłówek (w trybie pionowym) rozszerza się i koliduje z domyślnym położeniem kompasu. Jeśli dodasz dodatkowy niestandardowy element sterujący nagłówka lub widok dodatkowy nagłówka, kompas zostanie ukryty, aby uniknąć konfliktów w interfejsie.

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

Kompas jest domyślnie wyłączony. Kompas możesz włączyć, ustawiając właściwość compassButton elementu GMSUISettings na true. Nie możesz jednak wymusić, aby kompas był zawsze widoczny.

Swift

mapView.settings.compassButton = true

Objective-C

mapView.settings.compassButton = YES;

Przycisk Moja lokalizacja

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

Swift

mapView.settings.myLocationButton = true

Objective-C

mapView.settings.myLocationButton = YES;

Przycisk wyśrodkowania

Gdy nawigacja jest włączona, przycisk ponownego wyśrodkowania pojawia się, gdy użytkownik przewija widok mapy, a znika, gdy dotknie mapy, aby ją ponownie wyśrodkować. Aby przycisk ponownego 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 do interfejsu mapy

Pakiet Navigation SDK udostępnia akcesoria interfejsu, które pojawiają się podczas nawigacji podobnie jak w aplikacji Mapy Google na iOS. Widoczność i wygląd tych elementów sterujących możesz dostosować w sposób opisany w tej sekcji. Zmiany wprowadzone w tym miejscu zostaną odzwierciedlone podczas kolejnej podróży użytkownika.

Podczas nawigacji nagłówek nawigacji pojawia się u góry ekranu, a stopka nawigacji – u dołu. W nagłówku nawigacji wyświetlana jest nazwa ulicy i kierunek następnego skrętu na trasie, a także kierunek kolejnego skrętu. W stopce nawigacji wyświetla się szacowany czas i odległość do miejsca docelowego oraz szacowany czas przyjazdu.

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

  • navigationHeaderEnabled – określa, czy nagłówek nawigacyjny jest widoczny (domyślnie true).
  • navigationFooterEnabled – określa, czy widoczny jest stopka nawigacyjna (domyślnie true).
  • navigationHeaderPrimaryBackgroundColor – ustawia podstawowy kolor tła nagłówka nawigacji.
  • navigationHeaderSecondaryBackgroundColor – ustawia dodatkowy kolor tła nagłówka nawigacji.

Poniższy przykład kodu pokazuje włączanie widoczności nagłówka i stopki, a następnie ustawianie koloru 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 danych, który implementuje protokół GMSNavigationAccessoryView. Ten protokół ma 1 wymaganą metodę: -heightForAccessoryViewConstrainedToSize:onMapView:. Otrzymujesz maksymalny dostępny rozmiar widoku na danej mapie i musisz podać wysokość, jakiej wymaga Twój widok.

Następnie możesz przekazać ten widok do obiektu mapView, wywołując funkcję setHeaderAccessoryView: Obiekt mapView animuje zniknięcie bieżących widoków, a potem animuje pojawienie się widoku niestandardowego. Nagłówek nawigacji musi być widoczny, aby można było wyświetlić widok niestandardowy.

Aby usunąć widok dodatkowy nagłówka niestandardowego, przekaż wartość nil do setHeaderAccessoryView:.

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

Przykład

Poniższy przykład kodu przedstawia widok niestandardowy, który implementuje protokół GMSNavigationAccessoryView. Ten widok niestandardowy jest następnie używany do ustawienia niestandardowego widoku dodatkowego 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];

Tryb nocny

Metoda odbiornika GMSNavigatorListener.didChangeSuggestedLightingMode jest wywoływana, gdy zaktualizowane zostaną szacowane warunki oświetleniowe. Na przykład gdy w bieżącej lokalizacji urządzenia zapadnie noc. Możesz programowo modyfikować działanie trybu nocnego w ten 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żna to zrobić. Te kroki mogą się różnić w zależności od Twojej implementacji.

  1. Włącz przycisk punktu wejścia po tym, jak setDestinations na GMSNavigator(nawigatorze) zostanie ukończone i guidanceActive na nawigatorze zostanie włączone.
  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 (kontrolera widoku) i dodaj directionsListView jako podrzędny widok kontrolera widoku. Metody reloadDatainvalidateLayout na kontrolerze należy wywoływać tak samo jak w przypadku UICollectionView.
  4. Umieść kontroler widoku w hierarchii kontrolerów widoku aplikacji.

Poniższy przykład kodu pokazuje dodawanie elementu 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

Pasek postępu podróży dodany do nawigacji.

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

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

Pasek postępu podróży wyświetla te wskaźniki stanu:

  • Stan ruchu – stan nadchodzącego ruchu.

  • 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ść navigationTripProgressBarEnabledGMSUISettings.

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 do lewej strony prędkościomierza, logo Google i przycisku Ponownie wyśrodkuj (gdy jest widoczny). Szerokość to 12 punktów.
  • Pasek postępu podróży dynamicznie reaguje na pionową przestrzeń na ekranie. Dolna krawędź paska znajduje się 210 punktów od dołu ekranu. Górna krawędź paska postępu podróży znajduje się co najmniej 170 punktów od górnej krawędzi ekranu, a maksymalna wysokość paska to 400 punktów.
  • Jeśli pasek postępu trasy nakłada się na kartę skrętu lub inne elementy interfejsu nawigacji, pojawia się pod nimi.

Prompt Visibility API (eksperymentalny)

Interfejs Prompt Visibility API pozwala uniknąć konfliktów między elementami interfejsu wygenerowanymi przez Navigation SDK a własnymi elementami interfejsu użytkownika. Wystarczy dodać odbiornik, który będzie otrzymywać wywołanie zwrotne przed pojawieniem się elementu interfejsu Navigation SDK i natychmiast po jego usunięciu. Więcej informacji, w tym przykłady kodu, znajdziesz w sekcji API widoczności promptów na stronie Konfigurowanie zakłóceń w czasie rzeczywistym.

sygnalizacja świetlna i znaki stopu;

Znaki stopu i sygnalizacja świetlna wyświetlane podczas nawigacji.

Podczas aktywnej nawigacji możesz włączyć wyświetlanie świateł i znaków stop w mapView, co zapewnia dodatkowe informacje o trasach i manewrach podczas podróży.

Domyślnie sygnalizacja świetlna i znaki stop są wyłączone w pakiecie Navigation SDK na iOS. Aby włączyć tę funkcję, wywołaj GMSMapView ustawienia każdej opcji osobno: showsTrafficLightsshowsStopSigns.


Swift

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

Objective-C

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

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 ograniczenie prędkości, element sterujący rozwinie się i wyświetli drugi prędkościomierz z bieżącą prędkością kierowcy.

Możesz ustawić poziomy alertów, aby zmienić formatowanie wyświetlacza prędkościomierza, gdy kierowca przekroczy limit prędkości o określoną wartość. Możesz na przykład określić, że aktualna prędkość będzie wyświetlana na czerwono, gdy kierowca przekroczy ograniczenie prędkości o 5 mil na godzinę, a na czerwonym tle, gdy przekroczy je o 10 mil na godzinę.

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

Swift

mapView.shouldDisplaySpeedometer = true

Objective-C

mapView.shouldDisplaySpeedometer = YES;

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

Znaczniki miejsc docelowych

Markery miejsc docelowych na danej trasie możesz wyświetlać lub ukrywać, ustawiając właściwość showsDestinationMarkers elementu 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 mapy

Pakiet Navigation SDK umożliwia dalsze dostosowywanie nawigacji do potrzeb 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 będzie wyświetlana ikona wejścia. Te wskazówki wizualne pomagają użytkownikom odróżnić miejsca docelowe i do nich dotrzeć.

Aby utworzyć miejsce docelowe z wartością placeID, użyj jednego z inicjatorów GMSNavigationWaypoint, który akceptuje wartość placeID. Na przykład miejsca docelowe utworzone w samouczku dotyczącym nawigacji po trasie obejmują wyróżnianie miejsca docelowego i etykiety wejść, jeśli są dostępne.

Wyłączanie domyślnych gestów 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ść klasy GMSMapView. Poniższe gesty można włączać i wyłączać programowo. Pamiętaj, że wyłączenie gestu nie ograniczy programowego dostępu 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ć 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ąć, dotknąć dwoma palcami lub uszczypnąć, aby powiększyć obraz z kamery. Pamiętaj, że dwukrotne kliknięcie lub ściągnięcie, gdy scrollGesturessą włączone, może spowodować przesunięcie kamery do określonego punktu.
  • tiltGestures – określa, czy gesty pochylenia są włączone czy wyłączone. Jeśli ta funkcja jest włączona, użytkownicy mogą przechylać kamerę, przesuwając 2 palcami w górę lub w dół.
  • rotateGestures – określa, czy gesty obracania są włączone czy wyłączone. Jeśli ta opcja jest włączona, użytkownicy mogą obracać kamerę za pomocą gestu obrotu 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

Za pomocą tych właściwości możesz określać położenie elementów sterujących i innych elementów interfejsu względem nagłówka i stopki nawigacji:

  • navigationHeaderLayoutGuide
  • navigationFooterLayoutGuide
  • bottomTrailingButtonsLayoutGuide

Poniższy przykład kodu pokazuje, jak używać linii pomocniczych układu do umieszczania 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 alternatywnych tras

Gdy interfejs użytkownika jest przeładowany informacjami, możesz zmniejszyć bałagan, wyświetlając mniej alternatywnych tras niż domyślne 2 trasy 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 wyliczeniowych:

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

Przykład

Poniższy przykład kodu 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){...}];

.