Cómo modificar la IU de navegación

Con el SDK de Navigation para iOS, puedes modificar la experiencia del usuario con tu mapa determinando qué controles y elementos integrados de la IU aparecen en el mapa, y qué gestos permites. También puedes modificar el aspecto visual de la IU de Navigation. Consulta la página de políticas para obtener instrucciones sobre las modificaciones aceptables en la IU de navegación.

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 de inmediato 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. Cuando el usuario hace clic en la brújula, la cámara vuelve a una posición con un rumbo de cero (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 como "Seguir", la brújula permanece visible y, si la presionas, se alterna entre las perspectivas de cámara inclinada y de vista general.

Para evitar que el conductor se distraiga, la brújula permanece en la misma posición si el encabezado (en modo vertical) se expande y entra en conflicto con la posición predeterminada de la brújula. Si agregas un control personalizado de encabezado secundario o una vista de accesorio de encabezado, la brújula se oculta para evitar conflictos en la IU.

La brújula admite los modos diurno y nocturno, así como el modo oscuro.

La brújula viene desactivada de manera predeterminada. Puedes habilitar la brújula configurando la propiedad compassButton de GMSUISettings como true. 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 solo cuando está habilitado. Cuando un usuario hace clic en el botón, la cámara se anima para enfocarse en la ubicación actual del usuario si se conoce. Puedes habilitar el botón configurando la propiedad myLocationButton de GMSUISettings como true.

Swift

mapView.settings.myLocationButton = true

Objective-C

mapView.settings.myLocationButton = YES;

Botón para volver a centrar

Cuando se habilita la navegación, el botón para volver a centrar el mapa aparece cuando el usuario se desplaza por la vista del mapa y desaparece cuando el usuario presiona para volver a centrar el mapa. Para permitir que aparezca el botón de centrado, establece la propiedad recenterButtonEnabled de GMSUISettings en true. Para evitar que aparezca el botón de centrado, establece recenterButtonEnabled en false.

Swift

mapView.settings.isRecenterButtonEnabled = true

Objective-C

mapView.settings.recenterButtonEnabled = YES;

Accesorios de la IU del mapa

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

Durante la navegación, el encabezado de navegación aparece en la parte superior de la pantalla y el pie de página de navegación aparece 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. El pie de navegación muestra el tiempo y la distancia estimados hasta el destino, así como la hora de llegada estimada.

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

  • navigationHeaderEnabled: Controla si el encabezado de navegación está visible (el valor predeterminado es true).
  • navigationFooterEnabled: Controla si el pie de página de navegación está 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, establecer 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];

Puedes personalizar tu app reemplazando la vista del encabezado de navegación secundaria por tu propia vista de accesorio personalizada. 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 el mapa proporcionado, y debes indicar la altura que requiere tu vista.

Luego, puedes pasar esta vista a mapView llamando a setHeaderAccessoryView:. La vista de mapa muestra una animación de salida de las vistas actuales y, luego, muestra una animación de entrada de tu vista personalizada. El encabezado de navegación debe estar visible para que se muestre tu vista personalizada.

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

Si tu vista debe cambiar de tamaño en cualquier momento, puedes llamar a invalidateLayoutForAccessoryView: y pasar la vista que necesita 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];

Modo nocturno

El método de escucha GMSNavigatorListener.didChangeSuggestedLightingMode se activa cuando se actualizan las condiciones de iluminación estimadas. Por ejemplo, cuando cae la noche en la ubicación actual del dispositivo. Puedes modificar el comportamiento del modo nocturno de forma programática de las siguientes maneras:

Lista de instrucciones sobre cómo llegar

Puedes proporcionar instrucciones paso a paso en tu app. En el siguiente ejemplo, se muestra una forma 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 setDestinations en el GMSNavigator (navegador) se haya completado correctamente y se haya habilitado guidanceActive en el navegador.
  2. Cuando un usuario presiona el botón de punto de entrada, crea un GMSNavigationDirectionsListController (controlador) con el navegador asociado al GMSMapView (mapView).
  3. Agrega el controlador a una instancia de UIViewController (controlador de vista) y agrega el directionsListView como una subvista del controlador de vista. Los métodos reloadData y invalidateLayout del controlador se deben llamar como si se tratara de un UICollectionView.
  4. Envía el controlador de vista a la jerarquía de controladores de vista 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)
  // 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];
  ...
}

...

Barra de progreso del viaje

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

La barra de progreso del viaje es una barra vertical que aparece en el lado inicial o principal del mapa cuando se inicia la navegación. Cuando está habilitada, muestra un resumen de todo el viaje, junto con el destino y la posición actual del usuario.

Esto les permite a los usuarios anticipar rápidamente cualquier problema próximo, como el tráfico, sin necesidad de acercar la imagen. Luego, puede cambiar la ruta del viaje si es necesario. Si el usuario cambia la ruta del viaje, la barra de progreso se restablece como si se hubiera iniciado un viaje nuevo desde ese punto.

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

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

  • Ubicación actual: Es la ubicación actual del conductor durante el viaje.

  • Route elapsed: Es la parte transcurrida del viaje.

Habilita la barra de progreso del viaje configurando la propiedad navigationTripProgressBarEnabled en GMSUISettings.

Swift

mapView.settings.isNavigationTripProgressBarEnabled = true

Objective-C

mapView.settings.navigationTripProgressBarEnabled = YES;

Posicionamiento de la barra de progreso del viaje

  • El lado izquierdo de la barra se alinea aproximadamente con el lado izquierdo del velocímetro, el logotipo de Google y el botón Volver a centrar (cuando está visible). El ancho es de 12 pt.
  • La barra de progreso del viaje responde de forma dinámica al espacio vertical de la pantalla. La parte inferior de la barra se ubica a 210 pt de la parte inferior de la pantalla. La parte superior de la barra de progreso del viaje permanece a al menos 170 pt de la parte superior de la pantalla, con una altura máxima de la barra de 400 pt.
  • Si la barra de progreso del viaje se superpone con la tarjeta de giros o con otros elementos de la IU de Navegación, aparecerá debajo de esos otros elementos.

API de Prompt Visibility (experimental)

La API de Prompt Visibility te permite evitar conflictos entre los elementos de la IU generados por el SDK de Navigation y tus propios elementos de la IU personalizados agregando un objeto de escucha para recibir una devolución de llamada antes de que aparezca un elemento de la IU del SDK de Navigation y tan pronto como se quite el elemento. Para obtener más información, incluidas muestras de código, consulta la sección de la API de Prompt Visibility en la página Configura interrupciones en tiempo real.

Semáforos y señales de alto

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

Puedes habilitar la visualización de semáforos y señales de alto durante la navegación activa en mapView, lo que proporciona contexto adicional para las rutas y las maniobras del viaje.

De forma predeterminada, los semáforos y las 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 = true
mapView.settings.showsStopSigns = true

Objective-C

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

Control del velocímetro

Cuando se habilita la navegación y el modo de viaje se establece en conducción, 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 establecer niveles de alerta para cambiar el formato de la pantalla del velocímetro cuando el conductor exceda el límite de velocidad en una cantidad específica. Por ejemplo, puedes especificar que la velocidad actual se muestre con un color de texto rojo cuando el conductor supere el límite de velocidad en 8 km/h y con un color de fondo rojo cuando lo supere en 16 km/h.

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

Swift

mapView.shouldDisplaySpeedometer = true

Objective-C

mapView.shouldDisplaySpeedometer = YES;

Para obtener más información sobre cómo configurar alertas para el velocímetro, consulta Cómo configurar alertas del velocímetro.

Marcadores de destino

Puedes mostrar u ocultar los marcadores de destino de una ruta determinada configurando la propiedad showsDestinationMarkers de GMSUISettings. 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 el mapa

El SDK de Navigation te permite personalizar aún más la experiencia de navegación para tus usuarios. Los cambios que realices en tu instancia se reflejarán en la próxima actualización de tu app por parte del usuario.

Destacado de destinos y entradas

Destacado de destinos y entradas

Cuando se crea un destino con un placeID, se destacará el edificio del destino y se mostrará un ícono de entrada siempre que sea posible. Estas señales visuales ayudan a los usuarios a distinguir su destino y navegar hacia él.

Para crear un destino con un placeID, usa uno de los inicializadores de GMSNavigationWaypoint que acepte un placeID. Por ejemplo, los destinos creados en el instructivo sobre cómo navegar por una ruta incluyen el resaltado del destino y las etiquetas de entrada cuando están disponibles.

Inhabilita los gestos predeterminados del mapa

Puedes inhabilitar los gestos predeterminados en el mapa configurando 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 acercar la cámara. Ten en cuenta que, si presionas dos veces o pellizcas la pantalla cuando scrollGestures están habilitados, es posible que la cámara se desplace horizontalmente 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 verticalmente hacia arriba o hacia abajo 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 podrán usar un gesto de rotación con dos dedos para rotar la cámara.

En este ejemplo, se inhabilitaron los gestos de desplazamiento 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 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 con las siguientes propiedades:

  • navigationHeaderLayoutGuide
  • navigationFooterLayoutGuide
  • bottomTrailingButtonsLayoutGuide

En el siguiente ejemplo de código, se muestra el uso de las guías de diseño para posicionar un par de etiquetas en la vista del 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 ver un ejemplo de cómo usar un bottomTrailingButtonsLayoutGuide para colocar el botón de informes de interrupciones en tiempo real, consulta Configura las interrupciones en tiempo real.

Cómo ocultar rutas alternativas

Cuando la interfaz de usuario se sobrecarga con demasiada información, puedes reducir el desorden mostrando menos rutas alternativas que las predeterminadas (dos) o no mostrando ninguna ruta alternativa. Puedes configurar esta opción antes de recuperar las rutas configurando GMSNavigationRoutingOptions y estableciendo alternateRoutesStrategy con uno de los siguientes valores de enumeración:

Valor de enumeraciónDescripción
GMSNavigationAlternateRoutesStrategyAll Predeterminado. Muestra hasta dos rutas alternativas.
GMSNavigationAlternateRoutesStrategyOne Muestra una ruta alternativa (si hay una disponible).
GMSNavigationAlternateRoutesStrategyNone Oculta las 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){...}];