Modificar a IU de navegação

Com o SDK do Navigation para iOS, você pode modificar a experiência do usuário com seu mapa determinando quais elementos e controles de IU integrados aparecem no mapa e quais gestos são permitidos. Você também pode modificar a aparência visual da interface de navegação. Consulte a página Políticas para ver diretrizes sobre modificações aceitáveis na interface de navegação.

Controles de interface do mapa

O SDK do Navigation fornece alguns controles de interface integrados semelhantes aos encontrados no app Google Maps para iOS. É possível alternar a visibilidade desses controles usando a classe GMSUISettings. As alterações feitas nessa classe são aplicadas imediatamente ao mapa.

Bússola

O SDK do Navigation oferece um gráfico de bússola que aparece no canto superior direito do mapa em determinadas circunstâncias e somente quando ativado. A bússola só aparece quando a câmera está orientada com um rumo diferente do norte exato (um rolamento diferente de zero). Quando o usuário clica na bússola, a câmera volta a uma posição com rolamento zero (orientação padrão), e a bússola desaparece pouco tempo depois.

Se a navegação estiver ativada e o modo da câmera estiver definido como "seguindo", a bússola permanecerá visível, e o toque nela alterna entre as perspectivas inclinadas e de visão geral da câmera.

Por padrão, a bússola é desativada. É possível ativar a bússola definindo a propriedade compassButton de GMSUISettings como YES. No entanto, não é possível forçar a exibição permanente dela.

Swift

mapView.settings.compassButton = true

Objective-C

mapView.settings.compassButton = YES;

Botão "Meu local"

O botão "Meu local" aparece no canto inferior direito da tela somente quando está ativado. Quando um usuário clica no botão, a câmera passa a focar na localização atual do usuário, caso essa informação seja conhecida. Para ativar o botão, defina a propriedade myLocationButton de GMSUISettings como YES.

Swift

mapView.settings.myLocationButton = true

Objective-C

mapView.settings.myLocationButton = YES;

Botão "Recentralizar"

Quando a navegação está ativada, o botão "Centralizar" aparece quando o usuário rola a visualização de mapa e desaparece quando ele toca para recentralizar o mapa. Para permitir que o botão "Centralizar" seja exibido, defina a propriedade recenterButtonEnabled de GMSUISettings como YES. Para evitar que o botão "Centralizar" seja exibido, defina recenterButtonEnabled como NO.

Swift

mapView.settings.isRecenterButtonEnabled = true

Objective-C

mapView.settings.recenterButtonEnabled = YES;

Acessórios de interface do usuário do mapa

O SDK do Navigation fornece acessórios de interface que aparecem durante a navegação semelhantes aos encontrados no app Google Maps para iOS. Você pode ajustar a visibilidade ou a aparência desses controles, conforme descrito nesta seção. As mudanças feitas aqui são refletidas na próxima viagem do motorista.

Durante a navegação, o cabeçalho aparece na parte de cima da tela e o rodapé de navegação aparece na parte de baixo. O cabeçalho de navegação mostra o nome da rua e a direção da próxima curva na rota, bem como a direção da próxima curva. O rodapé de navegação mostra o tempo e a distância estimados até o destino, além do horário previsto de chegada.

É possível alternar a visibilidade do cabeçalho e do rodapé de navegação e definir as cores de maneira programática usando estas propriedades:

  • navigationHeaderEnabled: controla se o cabeçalho de navegação está visível (o padrão é true).
  • navigationFooterEnabled: controla se o rodapé de navegação está visível (o padrão é true).
  • navigationHeaderPrimaryBackgroundColor: define a cor de fundo principal do cabeçalho de navegação.
  • navigationHeaderSecondaryBackgroundColor: define a cor de plano de fundo secundária para o cabeçalho de navegação.

O exemplo de código a seguir mostra como ativar a visibilidade para o cabeçalho e o rodapé, depois definir navigationHeaderPrimaryBackgroundColor como azul e navigationHeaderSecondaryBackgroundColor como vermelho.

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

Você pode personalizar seu app substituindo a visualização do cabeçalho de navegação secundária pela sua própria visualização de acessório personalizada. Para isso, crie uma visualização que implemente o protocolo GMSNavigationAccessoryView. Esse protocolo tem um método obrigatório: -heightForAccessoryViewConstrainedToSize:onMapView:. Você receberá o tamanho máximo disponível para sua visualização no mapView especificado e precisará informar a altura necessária para a visualização.

Em seguida, você pode transmitir essa visualização para a mapView chamando setHeaderAccessoryView:. A mapView anima todas as visualizações atuais e depois anima na sua visualização personalizada. O cabeçalho de navegação precisa estar visível para que a visualização personalizada possa ser mostrada.

Para remover a visualização personalizada do acessório do cabeçalho, transmita nil para setHeaderAccessoryView:.

Se o tamanho da visualização precisar mudar a qualquer momento, chame invalidateLayoutForAccessoryView:, transmitindo a visualização que precisa mudar de tamanho.

Exemplo

O exemplo de código abaixo demonstra uma visualização personalizada que implementa o protocolo GMSNavigationAccessoryView. Essa visualização personalizada é usada para definir uma visualização personalizada de acessório do cabeçalho de navegação.

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 de rotas

Você pode fornecer rotas detalhadas no seu app. O exemplo a seguir mostra uma maneira de fazer isso. Essas etapas podem variar dependendo da sua própria implementação.

  1. Ativar um botão de ponto de entrada depois que setDestinations no GMSNavigator (navegador) for concluído e guidanceActive no navegador for ativado.
  2. Quando um usuário tocar no botão de ponto de entrada, crie um GMSNavigationDirectionsListController (controlador) com o navegador associado ao GMSMapView (mapView).
  3. Adicione o controlador a uma instância de UIViewController (controlador de visualização) e adicione o directionsListView como uma subvisualização do controlador de visualização. Os métodos reloadData e invalidateLayout no controlador precisam ser chamados da mesma forma que um UICollectionView.
  4. Envie o controlador de visualização para a hierarquia do controlador de visualizações do aplicativo.

O exemplo de código a seguir mostra como adicionar um 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];
  ...
}

...

Barra de progresso da viagem

Barra de progresso da viagem adicionada à navegação.

A barra de progresso da viagem é uma barra vertical que aparece na borda direita final do mapa quando a navegação é iniciada. Quando ativada, ela exibe uma visão geral de uma viagem inteira, com o destino e a posição atual do motorista.

Com isso, os motoristas podem prever rapidamente problemas futuros, como o trânsito, sem precisar aumentar o zoom. Eles podem redirecionar a viagem, se necessário. Quando o motorista redireciona a viagem, a barra de progresso é redefinida como se uma nova viagem começasse daquele ponto.

A barra de progresso da viagem mostra os seguintes indicadores de status:

  • Status do trânsito: o status do trânsito futuro.

  • Local atual: a localização atual do motorista na viagem.

  • Trajeto decorrido: a parte decorrido da viagem.

Ative a barra de progresso da viagem definindo a propriedade navigationTripProgressBarEnabled em GMSUISettings.

Swift

mapView.settings.isNavigationTripProgressBarEnabled = true

Objective-C

mapView.settings.navigationTripProgressBarEnabled = YES;

Semáforos e sinais de parada

Sinais de parada e semáforos mostrados durante a navegação.

Você pode ativar semáforos e placas de parada na mapView. Com esse recurso, o motorista pode ativar a exibição de semáforos ou ícones de sinais de parada ao longo do trajeto, oferecendo um contexto melhor para viagens mais eficientes e precisas.

Por padrão, semáforos e sinais de parada estão desativados no SDK do Navigation para iOS. Para ativar esse recurso, chame as configurações GMSMapView para cada opção de forma independente: showsTrafficLights e showsStopSigns.


Swift

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

Objective-C

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

Controle do velocímetro

Quando a navegação está ativada, o SDK do Navigation para iOS mostra um controle de limite de velocidade no canto inferior do mapa com o limite atual. Quando o motorista excede o limite de velocidade, o controle se expande para mostrar um segundo velocímetro com a velocidade atual do motorista.

Você pode definir níveis de alerta para mudar a formatação da tela do velocímetro quando o motorista excede o limite de velocidade em um determinado valor. Por exemplo, você pode especificar que a velocidade atual seja exibida em vermelho quando o motorista exceder o limite de velocidade em 8 km/h e com um fundo vermelho quando ele ultrapassar o limite em 16 km/h.

Para mostrar o controle de limite de velocidade, defina a propriedade shouldDisplaySpeedometer de GMSUISettings como YES. Para desativar a exibição do controle de limite de velocidade, defina shouldDisplaySpeedometer como NO.

Swift

mapView.shouldDisplaySpeedometer = true

Objective-C

mapView.shouldDisplaySpeedometer = YES;

Para mais informações sobre a definição de alertas do velocímetro, consulte Configurar alertas do velocímetro.

Marcadores de destino

Você pode mostrar ou ocultar os marcadores de destino de um trajeto específico definindo a propriedade showsDestinationMarkers de GMSUISettings. O exemplo a seguir mostra como desativar os marcadores de destino.

Swift

mapView.settings.showsDestinationMarkers = false

Objective-C

mapView.settings.showsDestinationMarkers = NO;

Recursos da experiência no mapa

O SDK do Navigation permite fazer mais personalizações na experiência de navegação dos usuários. As mudanças feitas na instância são refletidas na próxima atualização do driver do app.

Desativar gestos do mapa padrão

Para desativar os gestos padrão no mapa, defina as propriedades da classe GMSUISettings, que está disponível como uma propriedade de GMSMapView. Os gestos a seguir podem ser ativados e desativados programaticamente. Desativar o gesto não limita o acesso programático às configurações da câmera.

  • scrollGestures: controla se os gestos de rolagem estão ativados ou desativados. Se ativados, os usuários podem deslizar o dedo para deslocar a câmera.
  • zoomGestures: controla se os gestos de zoom estão ativados ou desativados. Se ativados, os usuários podem tocar duas vezes, tocar com dois dedos ou fazer gesto de pinça para aumentar o zoom da câmera. Tocar duas vezes ou fazer gesto de pinça quando scrollGestures estiver ativado pode mover a câmera até o ponto especificado.
  • tiltGestures: controla se os gestos de inclinação ficam ativados ou desativados. Se essa opção estiver ativada, os usuários poderão deslizar com dois dedos para baixo ou para cima para inclinar a câmera.
  • rotateGestures: controla se os gestos de rotação estão ativados ou desativados. Se ativada, os usuários podem usar um gesto de rotação com dois dedos para girar a câmera.

Neste exemplo, os gestos de movimento e de zoom foram desativados.

Swift

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

Objective-C

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

Controles de posição e elementos da interface

É possível posicionar controles e outros elementos da interface em relação à posição do cabeçalho e do rodapé de navegação usando as seguintes propriedades:

  • navigationHeaderLayoutGuide
  • navigationFooterLayoutGuide

O exemplo de código a seguir mostra o uso dos guias de layout para posicionar um par de etiquetas na visualização de mapa:

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;

Ocultar trajetos alternativos

Quando a interface do usuário fica desorganizada com muitas informações, é possível reduzir a sobrecarga mostrando menos rotas alternativas do que o padrão (duas) ou não mostrando rotas alternativas. É possível definir essa opção antes de buscar as rotas configurando GMSNavigationRoutingOptions e definindo alternateRoutesStrategy com um dos seguintes valores de enumeração:

Valor de enumeraçãoDescrição
GMSNavigationAlternativeRoutesStrategyAll Padrão. Mostra até duas rotas alternativas.
GMSNavigationAlternativeRoutesStrategyOne Mostra um trajeto alternativo (se houver um disponível).
GMSNavigationAlternateRoutesStrategyNone Oculta trajetos alternativos.

Exemplo

O exemplo de código a seguir demonstra como ocultar completamente rotas alternativas.

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