Cómo modificar la IU de navegación

Con el SDK de Navigation para iOS, puedes modificar la experiencia del usuario con tu mapa. Para ello, determina qué controles y elementos de la IU integrados aparecerán en el mapa y qué gestos permitirás. 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 IU integrados similares a los de 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 determinadas circunstancias y solo cuando está habilitado. La brújula solo aparece cuando la cámara se orienta de modo que tenga 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 de cero (la orientación predeterminada), y la brújula se desvanece poco después.

Si la navegación está habilitada y el modo de cámara está configurado en "siguiendo", el compás permanece visible y, si lo presionas, se alterna entre las perspectivas de la cámara inclinada y general.

La brújula viene desactivada de manera predeterminada. Puedes habilitar la brújula configurando la propiedad compassButton de GMSUISettings en 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 solamente cuando se habilita el botón correspondiente. Cuando un usuario hace clic en el botón, la cámara se anima para enfocar la ubicación actual del usuario si esta ubicación se conoce en el momento. 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 el mapa

Cuando la navegación está habilitada, 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 recentrar, establece la propiedad recenterButtonEnabled de GMSUISettings en true. Para evitar que aparezca el botón de recentrar, 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 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 siguiente giro. El pie de página de navegación muestra la hora estimada y la distancia 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 configurar 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 del 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];

Para personalizar tu app, reemplaza la vista del encabezado de navegación secundario con 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 mapView determinado y debes proporcionar la altura que requiere tu vista.

Luego, puedes pasar esta vista a mapView llamando a setHeaderAccessoryView:. mapView anima las vistas actuales y, luego, anima tu vista personalizada. El encabezado de navegación debe ser visible para que se muestre tu vista personalizada.

Para quitar la vista del accesorio de 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];

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 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 presiona el botón de punto de entrada, crea un GMSNavigationDirectionsListController (controlador) con el navegador asociado con el GMSMapView (mapView).
  3. Agrega el controlador a una instancia de UIViewController (controlador de vista) y agrega el directionsListView como una vista secundaria del controlador de vista. Se debe llamar a los métodos reloadData y invalidateLayout del controlador como lo harías 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)
  // 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

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 borde derecho del mapa cuando comienza la navegación. Cuando está habilitado, muestra un resumen de un viaje completo, junto con el destino y la posición actual del usuario.

Les permite a los usuarios anticipar rápidamente cualquier problema, como el tráfico, sin necesidad de acercar la imagen. Luego, puede redireccionar el 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.

  • Recorrido transcurrido: Es la parte del viaje transcurrido.

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 detención

Señales de detención y semáforos que se muestran durante la navegación.

Puedes habilitar los semáforos y las señales de detención en mapView. Con esta función, el usuario puede habilitar la visualización de semáforos o íconos de señales de detención 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 los carteles 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 la navegación está habilitada y el modo de viaje está configurado en conducir, 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 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 8 km/h y con un color de fondo rojo cuando supere el límite de velocidad 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 del mapa

El SDK de Navigation te permite realizar más personalizaciones en la experiencia de navegación de tus usuarios. Los cambios que realizas en tu instancia se reflejan durante la próxima actualización de la app por parte del usuario.

Inhabilita los gestos predeterminados del mapa

Puedes deshabilitar los gestos predeterminados en el mapa configurando las propiedades de la clase GMSUISettings, que se encuentra disponible como 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 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 habilitan, los usuarios pueden aplicar dos toques, toques con dos dedos o usar dos dedos para aplicar zoom a la cámara. Ten en cuenta que, cuando están habilitados los scrollGestures, el toque doble o el acercamiento de dedos pueden desplazar la cámara hasta el punto especificado.
  • tiltGestures: Controla si los gestos de inclinación están habilitados o inhabilitados. Si se habilitan, los usuarios pueden deslizar dos dedos hacia arriba o abajo para inclinar la cámara.
  • rotateGestures: Controla si los gestos de rotación están habilitados o inhabilitados. Si se habilitan, los usuarios pueden realizar gestos de rotación con dos dedos para girar la cámara.

En este ejemplo, se desactivaron 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 posicionar 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 mediante 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 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;

Cómo ocultar las 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 ruta alternativa. Puedes configurar esta opción antes de recuperar las rutas. Para ello, configura GMSNavigationRoutingOptions y 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){...}];