Cómo modificar la IU de navegación

Con el SDK de Navigation para iOS, puedes modificar la experiencia del usuario con tu mapa si determinas qué controles y elementos integrados de la IU aparecerán en el mapa, y qué gestos permitirás. También puedes modificar la apariencia visual de la IU de Navigation. Consulta la página Políticas para obtener lineamientos sobre las modificaciones aceptables en la IU de Navigation.

Controles de la IU del mapa

El SDK de Navigation proporciona algunos controles de la IU integrados similares a los que se encuentran en la aplicación de Google Maps para iOS. Puedes activar o desactivar la visibilidad de estos controles con la clase GMSUISettings. Los cambios que realices en esta clase se reflejarán inmediatamente en el mapa.

Brújula

El SDK de Navigation proporciona un gráfico de brújula que aparece en la esquina superior derecha del mapa en ciertas circunstancias y solo cuando está habilitado. La brújula solo aparece cuando la cámara se orienta de modo que tiene un rumbo distinto del norte exacto (un rumbo distinto de cero). Cuando el usuario hace clic en la brújula, la cámara vuelve a animarse y se ubica en una posición con un rumbo igual a cero (es decir, la orientación predeterminada) y la brújula se atenúa poco después.

Si la navegación está habilitada y el modo de cámara está configurado en "Siguiendo", la brújula seguirá visible y si presionas la brújula para alternar entre las perspectivas de la cámara inclinada y de vista general.

La brújula viene desactivada de manera predeterminada. Para habilitar la brújula, establece la propiedad compassButton de GMSUISettings en YES. Sin embargo, no puedes forzar su aparición en todo momento.

Swift

mapView.settings.compassButton = true

Objective‑C

mapView.settings.compassButton = YES;

Botón Mi ubicación

El botón Mi ubicación aparece en la esquina inferior derecha de la pantalla solamente cuando está habilitado. Cuando un usuario hace clic en el botón, se anima la cámara para enfocarse en la ubicación actual del usuario si esta se conoce en ese momento. Para habilitar el botón, configura la propiedad myLocationButton de GMSUISettings como YES.

Swift

mapView.settings.myLocationButton = true

Objective‑C

mapView.settings.myLocationButton = YES;

Botón para volver a centrar

Cuando la navegación está habilitada, el botón para volver a centrar el mapa aparece cuando el usuario se desplaza por la vista de mapa y desaparece cuando el usuario presiona para volver a centrar el mapa. Para permitir que aparezca el botón de volver a centrar, establece la propiedad recenterButtonEnabled de GMSUISettings en YES. Para evitar que aparezca el botón de volver a centrar, establece recenterButtonEnabled en NO.

Swift

mapView.settings.isRecenterButtonEnabled = true

Objective‑C

mapView.settings.recenterButtonEnabled = YES;

Accesorios de IU de mapas

El SDK de Navigation proporciona accesorios de IU que aparecen durante la navegación de manera similar a los que se encuentran en la aplicación de Google Maps para iOS. Puedes ajustar la visibilidad o el aspecto visual de estos controles como se describe en esta sección. Los cambios que realices aquí se reflejarán durante el próximo viaje del conductor.

Durante la navegación, el encabezado de navegación aparece en la parte superior de la pantalla y el de navegación en la parte inferior. El encabezado de navegación muestra el nombre de la calle y la dirección del próximo giro en la ruta, así como la dirección del giro siguiente. En el pie de página de navegación, se muestran la hora y la distancia estimadas hasta el destino, así como la hora estimada de llegada.

Puedes activar o desactivar la visibilidad del encabezado y el pie de página de navegación, y establecer sus colores de manera programática con las siguientes propiedades:

  • navigationHeaderEnabled: Controla si el encabezado de navegación es visible (el valor predeterminado es true).
  • navigationFooterEnabled: Controla si el pie de página de navegación es visible (el valor predeterminado es true).
  • navigationHeaderPrimaryBackgroundColor: Establece el color de fondo principal para el encabezado de navegación.
  • navigationHeaderSecondaryBackgroundColor: Establece el color de fondo secundario para el encabezado de navegación.

En el siguiente ejemplo de código, se muestra cómo activar la visibilidad del encabezado y el pie de página, y luego configurar navigationHeaderPrimaryBackgroundColor en azul y navigationHeaderSecondaryBackgroundColor en rojo.

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

Para personalizar tu app, reemplaza la vista del encabezado de navegación secundaria por tu propia vista personalizada de accesorios. Para ello, crea una vista que implemente el protocolo GMSNavigationAccessoryView. Este protocolo tiene un método obligatorio: -heightForAccessoryViewConstrainedToSize:onMapView:. Se te proporciona el tamaño máximo disponible para tu vista en una vista de mapa determinada y debes proporcionar la altura que requiere tu vista.

Luego, puedes pasar esta vista a mapView llamando a setHeaderAccessoryView:. MapView anima cualquier vista actual y, luego, anima en tu vista personalizada. El encabezado de navegación debe ser visible para que se pueda mostrar tu vista personalizada.

Para quitar la vista de accesorio de encabezado personalizado, pasa nil a setHeaderAccessoryView:.

Si la vista debe cambiar de tamaño en cualquier momento, puedes llamar a invalidateLayoutForAccessoryView: y pasar la vista que debe cambiar de tamaño.

Ejemplo

En el siguiente ejemplo de código, se muestra una vista personalizada que implementa el protocolo GMSNavigationAccessoryView. Luego, esta vista personalizada se usa para establecer una vista de accesorio de encabezado de navegación 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];

Lista de instrucciones sobre cómo llegar

Puedes proporcionar instrucciones paso a paso en tu app. En el siguiente ejemplo, se muestra una manera posible de hacerlo. Estos pasos pueden variar según tu propia implementación.

  1. Habilita un botón de punto de entrada después de que se haya completado correctamente setDestinations en GMSNavigator (navegador) y se haya habilitado guidanceActive en el navegador.
  2. Cuando un usuario presione el botón de punto de entrada, crea un GMSNavigationDirectionsListController (controlador) con el navegador asociado con GMSMapView (mapView).
  3. Agrega el controlador a una instancia de UIViewController (controlador de vista) y agrega directionsListView como una subvista del controlador de vista. Los métodos reloadData y invalidateLayout del controlador deben llamarse como se haría con un UICollectionView.
  4. Envía el controlador de vista a la jerarquía de estos controladores de la app.

En el siguiente ejemplo de código, se muestra cómo agregar un 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 progreso del viaje

La barra de progreso del viaje se agregó a la navegación.

La barra de progreso del viaje es una barra vertical que aparece en el borde derecho final del mapa cuando comienza la navegación. Cuando se habilita, muestra una descripción general de todo el viaje, junto con el destino del conductor y su posición actual.

Proporciona a los conductores la capacidad de anticipar con rapidez cualquier problema futuro, como el tráfico, sin necesidad de acercar la imagen. Luego, pueden redirigir el viaje si es necesario. Si el conductor redirecciona el viaje, la barra de progreso se restablece como si comenzara un nuevo viaje desde ese punto.

La barra de progreso del viaje muestra los siguientes indicadores de estado:

  • Estado del tráfico: El estado del tráfico próximo.

  • Ubicación actual: La ubicación actual del conductor en el viaje.

  • Ruta transcurrida: La parte transcurrida del viaje.

Para habilitar la barra de progreso del viaje, configura la propiedad navigationTripProgressBarEnabled en GMSUISettings.

Swift

mapView.settings.isNavigationTripProgressBarEnabled = true

Objective‑C

mapView.settings.navigationTripProgressBarEnabled = YES;

Semáforos y señales de alto

Las señales de alto y los semáforos se muestran durante la navegación.

Puedes habilitar los semáforos y las señales de alto en mapView. Con esta función, el conductor puede habilitar la visualización de semáforos o íconos de señales de alto a lo largo de su ruta, lo que proporciona un mejor contexto para viajes más eficientes y precisos.

De forma predeterminada, los semáforos y señales de alto están inhabilitados en el SDK de Navigation para iOS. Para habilitar esta función, llama a la configuración de GMSMapView para cada opción de forma independiente: showsTrafficLights y showsStopSigns.


Swift

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

Objective‑C

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

Control del velocímetro

Cuando la navegación está habilitada, el SDK de Navigation para iOS muestra un control de límite de velocidad en la esquina inferior del mapa que muestra el límite de velocidad actual. Cuando el conductor supera el límite de velocidad, el control se expande para mostrar un segundo velocímetro con la velocidad actual del conductor.

Puedes configurar niveles de alerta para cambiar el formato de la pantalla del velocímetro cuando el conductor excede el límite de velocidad en una cantidad específica. Por ejemplo, puedes especificar que la velocidad actual se muestre con un texto de color rojo cuando el conductor exceda el límite de velocidad en 8 km/h y con un color de fondo rojo cuando el conductor lo supere en 16 km/h.

Para mostrar el control de límite de velocidad, establece la propiedad shouldDisplaySpeedometer de GMSUISettings en YES. Para inhabilitar la visualización del control de límite de velocidad, establece shouldDisplaySpeedometer en NO.

Swift

mapView.shouldDisplaySpeedometer = true

Objective‑C

mapView.shouldDisplaySpeedometer = YES;

Si quieres obtener más información para configurar alertas del velocímetro, consulta Configura alertas del velocímetro.

Marcadores de destino

Puedes configurar la propiedad showsDestinationMarkers de GMSUISettings para mostrar u ocultar los marcadores de destino de una ruta determinada. En el siguiente ejemplo, se muestra cómo desactivar los marcadores de destino.

Swift

mapView.settings.showsDestinationMarkers = false

Objective‑C

mapView.settings.showsDestinationMarkers = NO;

Funciones de la experiencia en Maps

El SDK de Navigation te permite personalizar aún más la experiencia de navegación de tus usuarios. Los cambios que realizas en tu instancia se reflejan durante la próxima actualización del controlador de tu app.

Cómo inhabilitar los gestos de mapa predeterminados

Puedes inhabilitar los gestos predeterminados en el mapa si configuras las propiedades de la clase GMSUISettings, que está disponible como propiedad de GMSMapView. Los siguientes gestos pueden habilitarse y deshabilitarse de manera programática. Ten en cuenta que inhabilitar el gesto no limitará el acceso programático a la configuración de la cámara.

  • scrollGestures: Controla si los gestos de desplazamiento están habilitados o inhabilitados. Si se habilitan, los usuarios pueden deslizar el dedo para desplazar la cámara.
  • zoomGestures: Controla si los gestos de zoom están habilitados o inhabilitados. Si se habilita esta opción, los usuarios pueden presionar dos veces, presionar con dos dedos o pellizcar para hacer zoom en la cámara. Ten en cuenta que presionar dos veces o pellizcar cuando los scrollGestures están habilitados puede desplazar la cámara hasta el punto especificado.
  • tiltGestures: Controla si los gestos de inclinación están habilitados o inhabilitados. Si se habilita esta opción, los usuarios pueden deslizar dos dedos hacia abajo o hacia arriba para inclinar la cámara.
  • rotateGestures: Controla si los gestos de rotación están habilitados o inhabilitados. Si se habilita esta opción, los usuarios pueden usar un gesto de rotación con dos dedos para rotar la cámara.

En este ejemplo, se inhabilitaron los gestos de desplazamiento lateral y zoom.

Swift

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

Objective‑C

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

Controles de posición y elementos de la IU

Puedes colocar los controles y otros elementos de la IU en relación con la posición del encabezado y el pie de página de navegación usando las siguientes propiedades:

  • navigationHeaderLayoutGuide
  • navigationFooterLayoutGuide

En el siguiente ejemplo de código, se muestra cómo usar las guías de diseño para posicionar un par de etiquetas en la vista 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 rutas alternativas

Cuando la interfaz de usuario se satura con demasiada información, puedes reducir la sobrecarga si muestras menos rutas alternativas que las predeterminadas (dos) o no muestras ninguna ruta alternativa. Puedes configurar esta opción antes de recuperar las rutas. Para ello, configura GMSNavigationRoutingOptions y establece alternateRoutesStrategy con uno de los siguientes valores de enumeración:

Valor de enumeraciónDescripción
GMSNavegaciónAlternativaDeRutasEstrategiaTodo Predeterminado. Muestra hasta dos rutas alternativas.
GMSNavegaciónAlternativaDeRutasEstrategiaOne Muestra una ruta alternativa (si hay una disponible).
GMSNavigationAlternateRoutesStrategyNone Oculta rutas alternativas.

Ejemplo

En el siguiente ejemplo de código, se muestra cómo ocultar las rutas alternativas por completo.

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