Modyfikowanie interfejsu użytkownika

Za pomocą pakietu SDK nawigacji na iOS możesz zmieniać sposób, w jaki korzystasz z mapy, określając, które z wbudowanych opcji i elementów interfejsu użytkownika mają być widoczne 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 Zasady.

Elementy sterujące interfejsu mapy

Pakiet Navigation SDK zawiera wbudowane elementy interfejsu, podobne do tych w aplikacji Mapy Google na iOS. Widoczność tych ustawień możesz przełączać za pomocą klasy GMSUISettings. Zmiany wprowadzone na tych zajęciach są natychmiast odzwierciedlane na mapie.

Kompas

Pakiet Google Navigation SDK udostępnia grafikę kompasu, która wyświetla się w prawym górnym rogu mapy tylko wtedy, gdy jest włączona. Kompas pojawia się tylko wtedy, gdy kamera jest ustawiona tak, że jego orientacja jest inna niż dokładna północ (zakres niezerowy). Gdy użytkownik kliknie kompas, kamera cofnie się do pozycji z odchyleniem od zera (orientacja domyślna), a wkrótce znika.

Gdy włączona jest nawigacja i tryb aparatu jest ustawiony na „obserwowany”, kompas pozostaje widoczny, a dotykanie go przełącza się między przechylaną a ogólną perspektywą kamery.

Kompas jest domyślnie wyłączony. Aby włączyć kompas, ustaw właściwość compassButton elementu GMSUISettings na YES. Nie można jednak wymusić wyświetlania kompasu.

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 przycisk Moja lokalizacja. Gdy użytkownik kliknie przycisk, kamera przełączy się na jego bieżącą lokalizację, jeśli jest ona znana. Aby go włączyć, ustaw właściwość myLocationButton GMSUISettings na YES.

Swift

mapView.settings.myLocationButton = true

Objective-C

mapView.settings.myLocationButton = YES;

Przycisk wyśrodkuj ponownie

Gdy nawigacja jest włączona, przycisk wyśrodkowania pojawia się, gdy użytkownik przewija widok mapy, i znika, gdy użytkownik kliknie, aby ponownie wyśrodkować mapę. Aby umożliwić wyświetlenie przycisku wyśrodkowania, ustaw właściwość recenterButtonEnabled elementu GMSUISettings na YES. Aby przycisk wygaszania nie był wyświetlany, ustaw recenterButtonEnabled na NO.

Swift

mapView.settings.isRecenterButtonEnabled = true

Objective-C

mapView.settings.recenterButtonEnabled = YES;

Akcesoria do interfejsu Map

Pakiet Navigation SDK udostępnia akcesoria interfejsu, które wyświetlają się podczas nawigacji, podobne do tych w aplikacji Mapy Google na iOS. Możesz dostosować widoczność lub wygląd tych elementów sterujących w sposób opisany w tej sekcji. Wprowadzone tu zmiany będą odzwierciedlane podczas następnej podróży kierowcy.

Podczas nawigacji nagłówek wyświetla się na górze ekranu, a stopka – na dole. Nagłówek nawigacji zawiera nazwę ulicy i kierunek dla następnego zakrętu oraz kierunek następnego skrętu. W stopce nawigacyjnej widać szacowany czas i odległość do miejsca docelowego oraz szacowany czas dotarcia.

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

  • navigationHeaderEnabled – określa, czy nagłówek nawigacyjny ma być widoczny (wartość domyślna to true).
  • navigationFooterEnabled – określa, czy stopka nawigacyjna ma być widoczna (wartość domyślna to true).
  • navigationHeaderPrimaryBackgroundColor – ustawia podstawowy kolor tła nagłówka nawigacyjnego.
  • navigationHeaderSecondaryBackgroundColor – ustawia dodatkowy kolor tła nagłówka nawigacyjnego.

Poniższy przykładowy kod pokazuje, jak włączyć widoczność nagłówka i stopki, a następnie ustawić 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 dodatkowy widok nagłówka nawigacji własnym widokiem akcesoriów. Aby to zrobić, utwórz widok, który implementuje protokół GMSNavigationAccessoryView. Ten protokół ma jedną wymaganą metodę: -heightForAccessoryViewConstrainedToSize:onMapView:. Dostajesz maksymalny możliwy rozmiar widoku w danym widoku mapy i musisz podać wysokość, której wymaga dany widok.

Możesz przekazać ten widok do mapView, wywołując funkcję setHeaderAccessoryView:. Komponent mapView animuje wszystkie bieżące widoki, a następnie animuje się w widoku niestandardowym. Aby widok niestandardowy mógł zostać wyświetlony, nagłówek nawigacyjny musi być widoczny.

Aby usunąć widok niestandardowych akcesoriów w nagłówku, przekaż nil do: setHeaderAccessoryView:

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

Przykład

Poniższy przykładowy kod ilustruje widok niestandardowy, który implementuje protokół GMSNavigationAccessoryView. Ten widok niestandardowy służy do skonfigurowania niestandardowego widoku akcesorium nagłówka nawigacyjnego.

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

Lista wskazówek dojazdu

W aplikacji możesz udostępnić szczegółowe wskazówki dojazdu. Poniższy przykład pokazuje, jak to zrobić. Te kroki mogą się różnić w zależności od implementacji.

  1. Włącz przycisk punktu wejścia po wykonaniu instrukcji setDestinations w nawigatorze GMSNavigator i uaktywnieniu przycisku guidanceActive w nawigatorze.
  2. Gdy użytkownik kliknie przycisk punktu wejścia, utwórz GMSNavigationDirectionsListController (kontroler) z nawigatorem powiązanym z elementem GMSMapView (mapView).
  3. Dodaj kontroler do instancji UIViewController (widok kontrolera) i dodaj directionsListView jako widok podrzędny kontrolera widoków. Metody reloadData i invalidateLayout na kontrolerze powinny być wywoływane tak samo jak metody UICollectionView.
  4. Przekaż kontroler widoków na hierarchię kontrolerów widoków aplikacji.

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

...

Pasek postępu podróży

Dodano pasek postępu podróży do nawigacji.

Pasek postępu podróży to pionowy pasek, który pojawia się na końcu mapy przy prawej krawędzi mapy po rozpoczęciu nawigacji. Po włączeniu wyświetla ogólny przegląd całej podróży, a także miejsce docelowe i bieżącą pozycję kierowcy.

Umożliwia kierowcom szybkie przewidzenie nadchodzących problemów, np. korków, bez konieczności powiększania widoku. W razie potrzeby mogą wtedy zmienić trasę podróży. Jeśli kierowca zmieni trasę, pasek postępu resetuje się tak, jakby od tego momentu rozpoczęła się nowa podróż.

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

  • Stan ruchu – stan nadchodzącego ruchu.

  • Bieżąca lokalizacja – aktualna lokalizacja kierowcy w czasie podróży.

  • Ukończona trasa – czas, który upłynął od przejazdu.

Włącz pasek postępu podróży, ustawiając właściwość navigationTripProgressBarEnabled w GMSUISettings.

Swift

mapView.settings.isNavigationTripProgressBarEnabled = true

Objective-C

mapView.settings.navigationTripProgressBarEnabled = YES;

Światła uliczne i znaki „Stop”

Znaki „Zatrzymaj” i sygnalizacja świetlna wyświetlane w trakcie nawigacji.

Jeśli chcesz włączyć sygnalizację świetlną i znaki „Stop”, możesz to zrobić na stronie mapView. Dzięki tej funkcji kierowca może włączyć wyświetlanie sygnalizacji świetlnej lub ikon znaków stopu na trasie, co zapewni lepszy kontekst i zwiększyć dokładność trasy.

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


Swift

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

Objective-C

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

Sterowanie prędkościomierzem

Gdy nawigacja jest włączona, pakiet SDK nawigacji na iOS wyświetla w dolnym rogu mapy element sterujący, który wskazuje aktualne ograniczenie prędkości. Gdy kierowca przekroczy dozwoloną prędkość, przycisk rozwija się i wyświetla drugi prędkościomierz z aktualną prędkością kierowcy.

Możesz ustawić poziomy alertów, aby zmienić formatowanie wyświetlacza prędkościomierza, gdy kierowca przekroczy dozwoloną prędkość o określoną wartość. Możesz na przykład określić, że aktualna prędkość ma się wyświetlać w kolorze czerwonym, gdy kierowca przekroczy limit prędkości o 5 mil/h, a czerwony kolor tła, gdy przekroczy dozwolone ograniczenie o 10 km/h.

Aby wyświetlić ustawienia ograniczenia prędkości, ustaw właściwość shouldDisplaySpeedometer elementu GMSUISettings na YES. Aby wyłączyć wyświetlanie elementów sterujących limitami prędkości, ustaw shouldDisplaySpeedometer na NO.

Swift

mapView.shouldDisplaySpeedometer = true

Objective-C

mapView.shouldDisplaySpeedometer = YES;

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

Znaczniki miejsca docelowego

Znaczniki miejsca docelowego na danej trasie możesz pokazywać i ukrywać, ustawiając właściwość showsDestinationMarkers na 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 SDK nawigacji umożliwia dalsze dostosowywanie sposobu nawigacji do potrzeb użytkowników. Zmiany wprowadzone w instancji będą odzwierciedlane podczas następnej aktualizacji aplikacji przez sterownika.

Wyłącz domyślne gesty mapy

Domyślne gesty na mapie możesz wyłączyć, 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ć automatycznie. Pamiętaj, że wyłączenie gestu nie ograniczy programowego dostępu do ustawień kamery.

  • scrollGestures – określa, czy gesty przewijania mają być włączone czy wyłączone. Jeśli to ustawienie jest włączone, użytkownicy mogą przesuwać aparat, przesuwając go.
  • zoomGestures – określa, czy gesty powiększenia mają być włączone czy wyłączone. Gdy ta opcja jest włączona, użytkownicy mogą kliknąć dwukrotnie, kliknąć 2 palcami lub ściągnąć palce, aby powiększyć obraz. Pamiętaj, że dwukrotne dotknięcie lub ściąganie palców, gdy włączona jest funkcja scrollGestures, może przesunąć kamerę w określonym punkcie.
  • tiltGestures – określa, czy gesty przechylania mają być włączone czy wyłączone. Po włączeniu użytkownicy mogą przechylać kamerę 2 palcami w pionie w dół lub w górę.
  • rotateGestures – określa, czy gesty obracania mają być włączone czy wyłączone. Gdy ta opcja jest włączona, użytkownicy mogą obracać kamerę 2 palcami.

W tym przykładzie zarówno gesty przesuwania, jak i powiększania zostały wyłączone.

Swift

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

Objective-C

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

Elementy sterujące położeniem i elementy interfejsu

Używając tych właściwości, możesz określić położenie elementów sterujących i innych elementów interfejsu względem pozycji nagłówka i stopki nawigacji:

  • navigationHeaderLayoutGuide
  • navigationFooterLayoutGuide

Poniższy przykładowy kod pokazuje, jak rozmieszczać parę etykiet w widoku mapy przy użyciu wskazówek dotyczących układu:

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;

Ukryj trasy alternatywne

Gdy interfejs użytkownika jest zapełniony nadmiarem informacji, można go zmniejszyć, wyświetlając mniej tras alternatywnych niż domyślna (2) lub nie wyświetlając ich wcale. Możesz skonfigurować tę opcję przed pobraniem tras. W tym celu skonfiguruj GMSNavigationRoutingOptions i ustaw alternateRoutesStrategy z jedną z tych wartości wyliczeniowych:

Wartość wyliczeniaOpis
Alternatywne trasy nawigacyjne GMS Domyślny: Wyświetla maksymalnie dwie alternatywne trasy.
Alternatywna Strategia Trasy Nawigacja w GMS Wyświetla jedną alternatywną trasę (jeśli jest dostępna).
GMSNavigationAlternateRoutesStrategyNone Ukrywa trasy alternatywne.

Przykład

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

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