Cómo modificar la IU de navegación

Con el SDK de Navigation para iOS, puedes modificar la experiencia del usuario con tu mapa, ya que te ofrece la posibilidad de determinar qué controles y elementos integrados en la IU aparecerán en el mapa y qué gestos estarán permitidos. También puedes modificar el aspecto visual de la IU de Navigation. Consulta la página de políticas para obtener lineamientos sobre las modificaciones aceptables de la IU de Navigation.

Controles de la IU del mapa

El SDK de Navigation proporciona algunos controles de la IU incorporados 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, en ciertas circunstancias, aparece en la esquina superior derecha del mapa y solo cuando está habilitado. Cuando el usuario presiona la brújula, la cámara adopta una posición en la que el rumbo equivale 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 permanece visible y, si la presionas, se alterna entre las perspectivas de cámara inclinada y general.

Para evitar la distracción del conductor, la brújula permanece en la misma posición si el encabezado (en modo Retrato) 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 ocultará para evitar conflictos en la IU.

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

La brújula está habilitada de forma predeterminada en la versión 11.0.0 y posteriores. Para inhabilitar la brújula, configura la propiedad compassButton de GMSUISettings como false.

Swift

mapView.settings.compassButton = false

Objective-C

mapView.settings.compassButton = NO;

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, la cámara se anima para enfocar la ubicación actual del usuario, si se conoce. Para habilitar el botón, configura la propiedad myLocationButton de GMSUISettings como true.

Swift

mapView.settings.myLocationButton = true

Objective-C

mapView.settings.myLocationButton = YES;

Botón Volver a centrar

Cuando la navegación está habilitada, el botón para volver a centrar 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 para volver a centrar, establece la propiedad recenterButtonEnabled de GMSUISettings en true. Para evitar que aparezca el botón para volver a centrar, 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 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 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, 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 el tiempo y la distancia estimados 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:

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 secundario por tu propia vista de accesorios personalizada. Para ello, crea una vista que implemente el protocolo GMSNavigationAccessoryView. Este protocolo tiene un método obligatorio: -heightForAccessoryViewConstrainedToSize:onMapView:. Se te otorga el tamaño máximo disponible para tu vista en la mapView determinada, y debes proporcionar la altura que requiere tu vista.

Luego, puedes pasar esta vista a mapView llamando a setHeaderAccessoryView:. La mapView anima las vistas actuales y, luego, anima 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 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];

Colores del encabezado del modo de poca luz

El SDK de Navigation para iOS calcula el modo de iluminación sugerido según la hora del día y la ubicación actual del dispositivo, y llama al método de objeto de escucha GMSNavigatorListener.didChangeSuggestedLightingMode cuando cambia el modo sugerido (como al amanecer o al atardecer). Puedes modificar de manera programática el comportamiento del modo de poca luz 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 GMSNavigator (navegador) se haya completado correctamente y se haya habilitado guidanceActive en el navegador.
  2. Cuando un usuario presione el botón del 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 directionsListView como una vista secundaria del controlador de vista. Los métodos reloadData y invalidateLayout del controlador se deben llamar como se haría con 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

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

La barra de progreso del viaje es una barra vertical que aparece en el lado de inicio o de avance del mapa cuando comienza la navegación. Cuando se habilita, muestra un resumen de todo el viaje, junto con el destino y la posición actual del usuario.

Esto permite que los usuarios anticipen cualquier problema próximo, como el tráfico, sin necesidad de acercar la imagen. Luego, pueden 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 que se aproxima.

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

  • Ruta transcurrida: Es la parte transcurrida del viaje.

Para habilitar la barra de progreso del viaje, establece 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 coloca a 210 pt de la parte inferior de la pantalla. La parte superior de la barra de progreso del viaje permanece al menos a 170 pt de la parte superior de la pantalla, y la altura máxima de la barra es de 400 pt.
  • Si la barra de progreso del viaje se superpone con el encabezado de navegación 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 que genera el SDK de Navigation y tus propios elementos de la IU personalizados. Para ello, agrega un objeto de escucha que reciba una devolución de llamada antes de que aparezca un elemento de la IU del SDK de Navigation y en cuanto se quite el elemento. Para obtener más información, incluidas muestras de código, consulta la sección API de Prompt Visibility de la página Configura interrupciones en tiempo real.

Control del velocímetro

Cuando la navegación está habilitada 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 indica 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 supere el límite de velocidad en una cantidad especificada. 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 5 km/h y con un color de fondo rojo cuando el conductor supere el límite de velocidad en 10 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.settings.shouldDisplaySpeedometer = true

Objective-C

mapView.settings.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 de mapas

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

Entradas y destinos destacados

Entradas y destinos destacados

Cuando se crea un destino con un placeID, se destacará el edificio de destino y, siempre que sea posible, se mostrará un ícono de entrada. Estas indicaciones visuales ayudan a los usuarios a distinguir y navegar hasta el destino deseado.

Para crear un destino con un placeID, usa uno de los inicializadores GMSNavigationWaypoint que aceptan un placeID. Por ejemplo, los destinos creados en el instructivo para navegar por una ruta incluyen el destacado de destinos y las etiquetas de entrada cuando están disponibles.

Visualización de edificios en 3D durante la navegación

Visualización de edificios en 3D durante la navegación

Los edificios 3D se muestran durante la navegación de forma predeterminada. Para inhabilitar esta función, establece buildingsEnabled en false (Swift) o NO (Objective-C).

Inhabilitar los gestos predeterminados del mapa

Puedes inhabilitar los gestos predeterminados en el mapa configurando las propiedades de la clase GMSUISettings, que está disponible como una propiedad de GMSMapView. Los siguientes gestos pueden habilitarse y deshabilitarse de manera programática. Ten en cuenta que, si inhabilitas el gesto, no se 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 habilita, 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, los usuarios pueden presionar dos veces, presionar con dos dedos o pellizcar para acercar o alejar la cámara. Ten en cuenta que, si presionas dos veces o pellizcas la pantalla cuando los scrollGestures están habilitados, es posible que la cámara se desplace hasta el punto especificado.
  • tiltGestures: Controla si los gestos de inclinación están habilitados o inhabilitados. Si se habilita, los usuarios pueden deslizar dos dedos verticalmente 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, 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 y zoom.

Swift

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

Objective-C

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

Cómo posicionar controles y elementos de la IU

Puedes posicionar 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 con las siguientes propiedades:

  • navigationHeaderLayoutGuide
  • navigationFooterLayoutGuide
  • bottomTrailingButtonsLayoutGuide

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;

Para ver un ejemplo de cómo usar un bottomTrailingButtonsLayoutGuide para posicionar el botón de informe de interrupciones en tiempo real, consulta Configura las interrupciones en tiempo real.

Ocultar rutas alternativas

Cuando la interfaz de usuario se llena de demasiada información, puedes reducir el desorden mostrando menos rutas alternativas que las predeterminadas (dos) o no mostrando ninguna. 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
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 por completo las rutas 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){...}];