Com o SDK Navigation para iOS, você pode modificar a experiência do usuário com seu mapa determinando quais elementos e controles integrados da interface aparecem no mapa e quais gestos são permitidos. Também é possível modificar a aparência visual da interface de navegação. Consulte a página de políticas para ver diretrizes sobre modificações aceitáveis na interface de navegação.
Controles da interface do mapa
O SDK Navigation oferece alguns controles de IU integrados
semelhantes aos encontrados no app Google Maps para iOS. É possível
alternar a visibilidade desses controles usando a classe GMSUISettings
.
As mudanças feitas nessa classe são aplicadas imediatamente ao mapa.
Bússola
O SDK de navegação fornece um gráfico de bússola que aparece no canto superior direito do mapa em determinadas circunstâncias e somente quando ativado. Quando o usuário clica na bússola, a câmera volta para uma posição com direção zero (orientação padrão), e a bússola desaparece pouco tempo depois.
Se a navegação estiver ativada e o modo de câmera estiver definido como "seguindo", a bússola vai permanecer visível e tocar nela alternará entre as perspectivas de câmera inclinada e de visão geral.
Para evitar distrações do motorista, a bússola permanece na mesma posição se o cabeçalho (no modo retrato) se expandir e entrar em conflito com a posição padrão da bússola. Se você adicionar um controle personalizado ou uma visualização de acessório de cabeçalho secundário, a bússola será oculta para evitar conflitos na interface.
A bússola oferece suporte aos modos diurno e noturno, além do modo escuro.
Por padrão, a bússola é desativada. Para ativar a bússola, defina a
propriedade compassButton
de GMSUISettings
como true
. No entanto, não é possível
forçar a exibição permanente da bússola.
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 ele está ativado. Quando um usuário clica no botão, a
câmera é animada para focar no local atual do usuário, se ele
for conhecido. É possível ativar o botão definindo a
propriedade myLocationButton
de GMSUISettings
como true
.
Swift
mapView.settings.myLocationButton = true
Objective-C
mapView.settings.myLocationButton = YES;
Botão "Recentralizar"
Quando a navegação está ativada, o botão de recentralização aparece quando o usuário rola
a visualização do mapa e desaparece quando o usuário toca para recentralizar o mapa. Para permitir
que o botão de recentração apareça, defina a propriedade recenterButtonEnabled
de
GMSUISettings
como true
. Para impedir que o botão de recentização apareça, defina
recenterButtonEnabled
como false
.
Swift
mapView.settings.isRecenterButtonEnabled = true
Objective-C
mapView.settings.recenterButtonEnabled = YES;
Acessórios da interface do mapa
O SDK Navigation oferece acessórios de interface que aparecem durante a navegação, semelhantes aos encontrados no app Google Maps para iOS. É possível 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 usuário.
Cabeçalho e rodapé de navegação
Durante a navegação, o cabeçalho de navegação 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 no trajeto, além da direção da curva seguinte. O rodapé de navegação mostra o tempo estimado e a distância até o destino, além do horário estimado 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 as seguintes 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 plano de fundo principal para o 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 do cabeçalho e
do rodapé, 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];
Visualização de cabeçalho do acessório de navegação
Você pode personalizar seu app substituindo a visualização de 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ê recebe o tamanho máximo disponível para sua visualização no mapView fornecido e precisa informar a altura necessária.
Em seguida, transmita essa visualização para o mapView chamando setHeaderAccessoryView:
.
O mapView anima as visualizações atuais e, em seguida, anima sua visualização
personalizada. O cabeçalho de navegação precisa estar visível para que a visualização personalizada seja
exibida.
Para remover a visualização de acessório de cabeçalho personalizado, transmita nil
para
setHeaderAccessoryView:
.
Se a visualização precisar mudar de tamanho a qualquer momento, chame
invalidateLayoutForAccessoryView:
, transmitindo a visualização que precisa mudar
de tamanho.
Exemplo
O exemplo de código a seguir demonstra uma visualização personalizada que implementa o
protocolo GMSNavigationAccessoryView
. Essa visualização personalizada é usada para definir uma
visualização de acessório de cabeçalho de navegação personalizada.
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];
Modo noturno
O método do listener GMSNavigatorListener.didChangeSuggestedLightingMode
é acionado quando as condições de iluminação estimadas são atualizadas, por exemplo, quando anoitece no local atual do dispositivo. É possível modificar o comportamento do modo noturno de maneira programática das seguintes maneiras:
- Escolha quando o modo normal e o modo de pouca luz (noite) são usados usando o tipo enumerado
GMSNavigationLightingMode
. - Selecione as cores de plano de fundo primária e secundária do modo noturno definindo valores para as propriedades
navigationHeaderPrimaryBackgroundColorNightMode
enavigationHeaderSecondaryBackgroundColorNightMode
.
Lista de direções
Você pode fornecer instruções detalhadas no seu app. O exemplo a seguir mostra uma maneira possível de fazer isso. Essas etapas podem variar de acordo com sua implementação.
- Ative um botão de ponto de entrada depois que
setDestinations
noGMSNavigator
(navegador) for concluído eguidanceActive
no navegador for ativado. - Quando um usuário tocar no botão de ponto de entrada, crie um
GMSNavigationDirectionsListController
(controlador) com o navegador associado aoGMSMapView
(mapView
). - Adicione o controlador a uma instância de
UIViewController
(controlador de visualização) e adicione odirectionsListView
como uma subvisualização do controlador de visualização. Os métodosreloadData
einvalidateLayout
no controlador precisam ser chamados como umUICollectionView
. - Empurre o controlador de visualização para a hierarquia de controladores de visualização do app.
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
A barra de progresso da viagem é uma barra vertical que aparece no lado inicial/principal do mapa quando a navegação começa. Quando ativado, ele mostra uma visão geral de uma viagem inteira, junto com o destino e a posição atual do usuário.
Isso permite que os usuários antecipem rapidamente qualquer problema futuro, como o tráfego, sem precisar dar zoom. O motorista pode mudar a rota da viagem, se necessário. Se o usuário mudar o trajeto, a barra de progresso será redefinida como se uma nova viagem tivesse começado a partir desse ponto.
A barra de progresso da viagem mostra os seguintes indicadores de status:
Status do trânsito: o status do trânsito que está por vir.
Localização atual: a localização do motorista na viagem.
Tempo da rota: o tempo 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;
Posicionamento da barra de progresso da viagem
- O lado esquerdo da barra se alinha aproximadamente com a esquerda do velocímetro, o logotipo do Google e o botão "Recentralizar" (quando visível). A largura é de 12 pontos.
- A barra de progresso da viagem responde dinamicamente ao espaço vertical na tela. A parte de baixo da barra está posicionada a 210 pt da parte de baixo da tela. A parte de cima da barra de progresso da viagem fica a pelo menos 170 pontos da parte de cima da tela, com uma altura máxima de 400 pontos.
- Se a barra de progresso da viagem se sobrepor ao card de direção ou a outros elementos da IU de navegação, ela vai aparecer abaixo desses elementos.
API Prompt Visibility (experimental)
A API Prompt Visibility permite evitar conflitos entre elementos de interface gerados pelo SDK de navegação e seus próprios elementos de interface personalizados, adicionando um listener para receber um callback antes que um elemento de interface do SDK de navegação esteja prestes a aparecer e assim que o elemento for removido. Para mais informações, incluindo exemplos de código, consulte a seção API Prompt Visibility da página Configurar interrupções em tempo real.
Semáforos e placas de pare
É possível ativar a exibição de semáforos e sinais de parada durante a
navegação ativa no mapView
, que fornece mais contexto para rotas
e manobras de viagem.
Por padrão, os 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 = true
mapView.settings.showsStopSigns = true
Objective-C
mapView.settings.showsTrafficLights = YES;
mapView.settings.showsStopSigns = YES;
Controle do velocímetro
Quando a navegação está ativada e o modo de viagem está definido como "Dirigir", o SDK de navegação para iOS mostra um controle de limite de velocidade no canto inferior do mapa que mostra o limite de velocidade 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.
É possível definir níveis de alerta para mudar a formatação da tela do velocímetro quando o motorista exceder o limite de velocidade em um valor especificado. Por exemplo, é possível especificar que a velocidade atual é exibida com uma cor de texto vermelha quando o motorista excede o limite de velocidade em 5 mph e com uma cor de plano de fundo vermelha quando o motorista excede o limite de velocidade em 10 mph.
Para mostrar o controle de limite de velocidade, defina a propriedade shouldDisplaySpeedometer
de
GMSUISettings
como true
. Para desativar a exibição do controle de limite de velocidade, defina
shouldDisplaySpeedometer
como false
.
Swift
mapView.shouldDisplaySpeedometer = true
Objective-C
mapView.shouldDisplaySpeedometer = YES;
Para mais informações sobre como definir alertas para o velocímetro, consulte Configurar alertas do velocímetro.
Marcadores de destino
É possível mostrar ou ocultar os marcadores de destino de uma determinada rota 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 do mapa
O SDK de navegação permite fazer outras 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 app do usuário.
Destaque e entradas do destino
Quando um destino é criado com um placeID
, o edifício de destino é destacado e um ícone de entrada é mostrado sempre que possível. Essas dicas visuais ajudam os usuários a distinguir e navegar até o destino pretendido.
Para criar um destino com um placeID
, use um dos inicializadores GMSNavigationWaypoint
que aceita um placeID
. Por exemplo, os destinos criados no tutorial de navegação de uma rota incluem destaque de destino e rótulos de entrada quando disponíveis.
Desativar os gestos padrão do mapa
É possível desativar os gestos padrão no mapa definindo propriedades da classe GMSUISettings
, que está disponível como uma propriedade de GMSMapView
.
Os gestos a seguir podem ser ativados e desativados programaticamente. A
desativação do 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 ativado, os usuários podem tocar duas vezes, tocar com dois dedos ou fazer pinça para ampliar a câmera. Toque duplo ou gesto de pinça quandoscrollGestures
estiver ativado pode mover a câmera para o ponto especificado.tiltGestures
: controla se os gestos de inclinação estão ativados ou desativados. Se ativado, os usuários podem usar um gesto de deslizar para cima ou para baixo com dois dedos para inclinar a câmera.rotateGestures
: controla se os gestos de rotação estão ativados ou desativados. Se ativado, os usuários podem usar um gesto de rotação com dois dedos para girar a câmera.
Neste exemplo, os gestos de movimentação e zoom foram desativados.
Swift
mapView.settings.scrollGestures = false
mapView.settings.zoomGestures = false
Objective-C
mapView.settings.scrollGestures = NO;
mapView.settings.zoomGestures = NO;
Posicionar controles 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
bottomTrailingButtonsLayoutGuide
O exemplo de código a seguir mostra como usar as guias de layout para posicionar um par de rótulos na visualização do 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;
Para conferir um exemplo de como usar um bottomTrailingButtonsLayoutGuide
para posicionar o botão de denúncia de interrupções em tempo real, consulte Configurar interrupções em tempo real.
Ocultar rotas alternativas
Quando a interface do usuário fica sobrecarregada com muitas informações, é possível
reduzir a desordem mostrando menos rotas alternativas do que o padrão (duas) ou
não mostrando nenhuma rota alternativa. É possível configurar essa opção antes de buscar as rotas definindo GMSNavigationRoutingOptions
e alternateRoutesStrategy
com um dos seguintes valores de enumeração:
Valor de enumeração | Descrição |
---|---|
GMSNavigationAlternateRoutesStrategyAll | Padrão. Mostra até duas rotas alternativas. |
GMSNavigationAlternateRoutesStrategyOne | Mostra uma rota alternativa (se disponível). |
GMSNavigationAlternateRoutesStrategyNone | Oculta as rotas alternativas. |
Exemplo
O exemplo de código abaixo demonstra como ocultar 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){...}];