Objetos de mapas

En la API, las clases GoogleMap y MapFragment representan los mapas.

Muestras de código

El repositorio ApiDemos en GitHub incluye ejemplos que muestran el uso del objeto GoogleMap y el fragmento SupportMapFragment:

Agrega un mapa a una app para Android

Estos son los pasos básicos para agregar un mapa:

  1. (Solo debes realizar este paso una vez). Sigue los pasos de la guía de configuración del proyecto para obtener la API y una clave, y agregar los atributos necesarios a tu manifiesto de Android.
  2. Agrega un objeto Fragment a la actividad (Activity) que controlará el mapa. La manera más fácil de hacerlo es agregar un elemento <fragment> al archivo de diseño de la actividad (Activity).
  3. Implementa la interfaz OnMapReadyCallback y utiliza el método de devolución de llamada onMapReady(GoogleMap) para controlar el objeto GoogleMap. El objeto GoogleMap es la representación interna del mapa. Para establecer las opciones de vista de un mapa, modifica su objeto GoogleMap.
  4. Llama a getMapAsync() en el fragmento para registrar la devolución de llamada.

A continuación, se ofrece información más detallada sobre cada paso.

Agrega un fragmento

Agrega un elemento <fragment> al archivo de diseño de la actividad para definir un objeto Fragment. En este elemento, establece el atributo android:name en "com.google.android.gms.maps.MapFragment". Esto adjuntará automáticamente un objeto MapFragment a la actividad.

El siguiente archivo de diseño contiene un elemento <fragment>:

<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.google.android.gms.maps.MapFragment"
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

También puedes agregar un objeto MapFragment a una actividad (Activity) en el código. Para ello, crea una nueva instancia MapFragment y, luego, llama a FragmentTransaction.add() a fin de agregar el objeto Fragment a la actividad (Activity) actual.

 mMapFragment = MapFragment.newInstance();
 FragmentTransaction fragmentTransaction =
         getFragmentManager().beginTransaction();
 fragmentTransaction.add(R.id.my_container, mMapFragment);
 fragmentTransaction.commit();

Agrega un código de mapa

Para trabajar con el mapa dentro de tu app, debes implementar la interfaz OnMapReadyCallback y establecer una instancia de la devolución de llamada en un objeto MapFragment o MapView. En este instructivo, se utiliza un objeto MapFragment, ya que es la forma más común de agregar un mapa a una app. El primer paso es implementar la interfaz de devolución de llamada:

public class MainActivity extends FragmentActivity
    implements OnMapReadyCallback {
...
}

En el método onCreate() de tu actividad (Activity), establece el archivo de diseño como la vista de contenido. Por ejemplo, si el archivo de diseño tiene el nombre main.xml, utiliza este código:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ...
}

Para controlar el fragmento, llama a FragmentManager.findFragmentById() y pásale el ID de recurso de tu elemento <fragment>. Ten en cuenta que el ID de recurso R.id.map se agrega automáticamente al proyecto de Android cuando creas el archivo de diseño.

Luego, utiliza getMapAsync() para establecer la devolución de llamada en el fragmento.

MapFragment mapFragment = (MapFragment) getFragmentManager()
    .findFragmentById(R.id.map);
mapFragment.getMapAsync(this);

Utiliza el método de devolución de llamada onMapReady(GoogleMap) para controlar el objeto GoogleMap. La devolución de llamada se activa cuando el mapa está listo para utilizarse. Proporciona una instancia no nula de GoogleMap. Por ejemplo, puedes utilizar el objeto GoogleMap para establecer las opciones de vista del mapa o agregar un marcador.

@Override
public void onMapReady(GoogleMap map) {
    map.addMarker(new MarkerOptions()
        .position(new LatLng(0, 0))
        .title("Marker"));
}

El objeto de mapa

Maps SDK for Android te permite mostrar un mapa de Google Maps en tu aplicación para Android. Estos mapas lucen igual que aquellos que se ven en la app de Google Maps para dispositivos móviles (GMM), y la API expone muchas de las mismas funciones. Existen dos diferencias muy marcadas entre la aplicación de GMM y los mapas que muestra Maps SDK for Android:

  • Los mosaicos de mapa que muestra la API no incluyen ningún contenido personalizado, como íconos inteligentes personalizados.
  • No todos los íconos del mapa admiten la posibilidad de hacer clics. Por ejemplo, no se puede hacer clic en los íconos de estaciones de transporte público. Sin embargo, sí se puede hacer clic en los marcadores que agregas al mapa, y la API tiene una interfaz de devolución de llamada que permite escuchar varias interacciones con los marcadores.

Además de la funcionalidad de mapeo, la API admite una variedad completa de interacciones coherentes con el modelo de IU de Android. Por ejemplo, puedes configurar interacciones con un mapa. Para ello, debes definir objetos de escucha que respondan a gestos del usuario.

Al trabajar con un objeto de mapa, la clase fundamental es GoogleMap. GoogleMap modela el objeto de mapa en tu aplicación. En tu IU, se representará un mapa mediante un objeto MapFragment o MapView.

GoogleMap controla las siguientes operaciones automáticamente:

  • Conexión al servicio de Google Maps
  • Descarga de mosaicos de mapa
  • Visualización de mosaicos en la pantalla del dispositivo
  • Visualización de varios controles, como el desplazamiento lateral y el zoom
  • Respuesta a gestos de desplazamiento lateral y zoom a través del movimiento del mapa y su acercamiento o alejamiento

Además de estas operaciones automáticas, puedes controlar el comportamiento de los mapas con objetos y métodos de la API. Por ejemplo, el objeto GoogleMap tiene métodos de devolución de llamada que responden a la pulsación de teclas y gestos táctiles en el mapa. También puedes configurar íconos de marcadores en tu mapa y agregarle superposiciones con los objetos que proporciones en GoogleMap.

MapFragment

El objeto MapFragment, una subclase de la clase Fragment de Android, te permite colocar un mapa en un fragmento de Android. Los objetos MapFragment actúan como contenedores del mapa y proporcionan acceso al objeto GoogleMap.

A diferencia de View, el objeto Fragment representa un comportamiento o una parte de la interfaz de usuario en una actividad. Puedes combinar varios fragmentos en una sola actividad para compilar una IU de varios paneles y reutilizar un fragmento en varias actividades. Consulta la documentación de Android sobre fragmentos para obtener más información.

MapView

El objeto MapView, una subclase de la clase View de Android, te permite colocar un mapa en un objeto View de Android. Un objeto View representa una sección rectangular de la pantalla y es un componente fundamental de las aplicaciones y los widgets para Android. De manera similar a un fragmento MapFragment, el objeto MapView actúa como un contenedor del mapa, lo que expone la funcionalidad del mapa principal a través del objeto GoogleMap.

Cuando se utiliza la API en el modo completamente interactivo, los usuarios de la clase MapView deben reenviar los siguientes métodos de ciclo de vida de la actividad a los métodos correspondientes de la clase MapView: onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy(), onSaveInstanceState() y onLowMemory(). El repositorio ApiDemos en GitHub incluye un ejemplo que muestra cómo reenviar los métodos de ciclo de vida de la actividad. Cuando se utiliza la API en el modo lite, el reenvío de eventos de ciclo de vida es opcional. Para obtener más información, consulta la documentación sobre el modo lite.

Tipos de mapas

Existen muchos tipos de mapas disponibles en Maps SDK for Android. El tipo de mapa rige la representación general de este. Por ejemplo, los atlas suelen contener mapas políticos cuyo objetivo es mostrar las fronteras, mientras que los mapas de ruta muestran todas las rutas de una ciudad o región.

Maps SDK for Android ofrece cuatro tipos de mapas, así como la opción de no incluir ninguno:

Normal
Es un mapa de ruta típico. Muestra rutas, algunos elementos creados por el hombre y elementos naturales importantes, como ríos. También muestra etiquetas de rutas y elementos.
Híbrido
Muestra datos de fotos satelitales, además de los mapas de ruta. También muestra etiquetas de rutas y elementos.
Satelital
Muestra datos de fotos satelitales. No muestra etiquetas de rutas y características.
De terreno
Muestra datos topográficos. El mapa incluye colores, isolíneas y etiquetas relacionadas, y sombras que agregan perspectiva. También muestra algunas rutas y etiquetas.
Ninguno
No muestra ningún mosaico. El mapa se renderiza como una cuadrícula vacía sin mosaicos cargados.

Cambia el tipo de mapa

Para determinar el tipo de mapa, llama al método setMapType() del objeto GoogleMap. Para ello, pasa una de las constantes de tipo definidas en el objeto GoogleMap. Por ejemplo, utiliza el siguiente código para mostrar un mapa satelital:

GoogleMap map;
...
// Sets the map type to be "hybrid"
map.setMapType(GoogleMap.MAP_TYPE_HYBRID);

En la siguiente imagen, se comparan tres tipos de mapas de la misma ubicación, uno normal, uno híbrido y uno de terreno:

Comparación de MapType

Mapas de interiores

Cuando se utilizan altos niveles de zoom en espacios cerrados, como aeropuertos, centros comerciales, grandes tiendas minoristas y estaciones de transporte público, el mapa muestra el plano del edificio. Estos planos de edificios, llamados mapas de interiores, solo están disponibles en los tipos de mapas "normal" y "satelital" (GoogleMap.MAP_TYPE_NORMAL y GoogleMap.MAP_TYPE_SATELLITE). Se habilitan automáticamente cuando el usuario acerca la imagen y desaparecen cuando la alejan.

Aviso de baja: En una versión posterior, los mapas de interiores solo estarán disponibles en el tipo de mapa normal. A partir de esa versión, los mapas de interiores dejarán de ser compatibles con los mapas satellite, hybrid y terrain. Aun cuando los mapas de interiores no sean compatibles, el método isIndoorEnabled() seguirá mostrando el valor establecido a través del método setIndoorEnabled(), como sucede actualmente. El valor predeterminado de setIndoorEnabled es true. Se te informará mediante las notas de la versión cuando los mapas de interiores dejen de ser compatibles con esos tipos de mapas.

Ejemplo de mapa de interiores

Trabaja con mapas de interiores en la API

A continuación, se muestra un resumen de la funcionalidad de mapas de interiores de la API:

  • Para inhabilitar los mapas de interiores, debes llamar a GoogleMap.setIndoorEnabled(false), ya que estos mapas están habilitados de forma predeterminada. Además, los mapas de interiores se muestran en un mapa a la vez. De forma predeterminada, este es el primer mapa que se agrega a tu app. Si deseas mostrar mapas de interiores en otro mapa, inhabilítalos en el primero y, luego, llama a setIndoorEnabled(true) en el segundo.
  • Para inhabilitar el selector de piso (o de nivel) predeterminado, llama a GoogleMap.getUiSettings().setIndoorLevelPickerEnabled(false). Para obtener más detalles, consulta Cómo interactuar con el mapa.
  • Una interfaz en GoogleMap, OnIndoorStateChangeListener, te permite establecer un objeto de escucha que se llamará cuando se enfoque un nuevo edificio o se active un nuevo piso en un edificio. Para obtener más detalles, consulta Cómo interactuar con el mapa.
  • El método GoogleMap.getFocusedBuilding() te muestra el edificio que está actualmente en foco. Luego, puedes llamar a IndoorBuilding.getActiveLevelIndex() para encontrar el piso activo en ese momento. Consulta la documentación de referencia para ver toda la información disponible en los objetos IndoorBuilding y IndoorLevel.

El diseño del Mapa base no afecta los mapas de interiores.

Agrega planos del edificio

Los mapas de interiores (planos de edificios) solo están disponibles en ubicaciones seleccionadas. Si no hay datos disponibles para el plano de un edificio que deseas destacar en tu aplicación, puedes hacer lo siguiente:

Capa de tráfico

Puedes darles a tus usuarios la posibilidad de ver el mapa con información superpuesta sobre la densidad del tráfico. Esto les proporcionará un resumen visual de la situación del tráfico local. Llama al método setTrafficEnabled() para activar y desactivar la capa de tráfico, y al método isTrafficEnabled() a fin de determinar si actualmente está activa. En el siguiente ejemplo, se ve cómo podría mostrarse la capa de tráfico en un mapa.

Mapa de Google Maps con la capa de tráfico activa

Configura el estado inicial

La API de Google Maps te permite configurar el estado inicial del mapa para adaptarlo a las necesidades de tu aplicación. Puedes especificar lo siguiente:

  • Cómo posicionar la cámara, lo que incluye la ubicación, el zoom, el rumbo y la inclinación (consulta Cámara y vista para obtener más detalles sobre el posicionamiento de la cámara)
  • Qué tipo de mapa mostrar
  • Si mostrar o no los botones de zoom y la brújula en pantalla
  • Qué gestos puede emplear un usuario para manipular la cámara
  • Si habilitar o no el modo lite El modo lite muestra una imagen de mapa de bits correspondiente a un mapa que admite un subconjunto de las funcionalidades proporcionadas por la API completa.

Puedes configurar el estado inicial del mapa por medio de un archivo XML, si agregaste el mapa al archivo de diseño de tu actividad, o bien de manera programática, si agregaste el mapa de esa manera.

Cómo usar atributos XML

En esta sección, se describe cómo establecer el estado inicial del mapa si lo agregaste a tu aplicación mediante un archivo de diseño XML.

La API de Google Maps define un conjunto de atributos XML personalizados para un objeto MapFragment o MapView que puedes utilizar a fin de configurar el estado inicial del mapa directamente desde el archivo de diseño. Actualmente, se definen los siguientes atributos:

  • mapType. Te permite especificar el tipo de mapa que se mostrará. Los valores válidos son ninguno (none), normal (normal), híbrido (hybrid), satelital (satellite) y de terreno (terrain).
  • cameraTargetLat, cameraTargetLng, cameraZoom, cameraBearing y cameraTilt. Te permiten especificar la posición inicial de la cámara. Consulta aquí para obtener más detalles sobre la posición de la cámara y sus propiedades.
  • uiZoomControls y uiCompass. Te permiten especificar si mostrar o no los controles de zoom y la brújula en el mapa. Consulta UiSettings para obtener más detalles.
  • uiZoomGestures, uiScrollGestures, uiRotateGestures y uiTiltGestures. Te permiten especificar qué gestos están habilitados o inhabilitados para interactuar con el mapa. Consulta UiSettings para obtener más detalles.
  • zOrderOnTop. Controla si la superficie de la vista de mapa se dispone sobre la ventana. Consulta SurfaceView.setZOrderOnTop(boolean) para obtener más detalles. Ten en cuenta que esto abarcará todas las demás vistas que podrían aparecer en el mapa (p. ej., los controles de zoom o el botón Mi ubicación).
  • useViewLifecycle. Solo es válido con un objeto MapFragment. Este atributo especifica si el ciclo de vida del mapa debe vincularse a la vista del fragmento o al fragmento en sí. Consulta aquí para obtener más detalles.
  • liteMode. El valor true establece el mapa en modo lite. El modo lite muestra una imagen de mapa de bits correspondiente a un mapa que admite un subconjunto de las funcionalidades proporcionadas por la API completa. El valor predeterminado de este atributo es false.

Para utilizar estos atributos personalizados en tu archivo de diseño XML, primero debes agregar la siguiente declaración de espacio de nombres. No es necesario que el espacio de nombres sea map, sino que puedes elegir cualquiera:

xmlns:map="http://schemas.android.com/apk/res-auto"

Luego, puedes agregar los atributos con un prefijo map: en tus componentes de diseño, como lo harías con los atributos estándares de Android.

En el siguiente fragmento de código XML, se muestra cómo configurar un objeto MapFragment con algunas opciones personalizadas. También se pueden aplicar los mismos atributos a un objeto MapView.

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:map="http://schemas.android.com/apk/res-auto"
  android:name="com.google.android.gms.maps.SupportMapFragment"
  android:id="@+id/map"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  map:cameraBearing="112.5"
  map:cameraTargetLat="-33.796923"
  map:cameraTargetLng="150.922433"
  map:cameraTilt="30"
  map:cameraZoom="13"
  map:mapType="normal"
  map:uiCompass="false"
  map:uiRotateGestures="true"
  map:uiScrollGestures="false"
  map:uiTiltGestures="true"
  map:uiZoomControls="false"
  map:uiZoomGestures="true"/>

Cómo configurar el estado inicial de manera programática

En esta sección, se describe cómo configurar el estado inicial del mapa si lo agregaste a tu aplicación de manera programática.

Si agregaste un objeto MapFragment (o MapView) de manera programática, puedes configurar su estado inicial si pasas un objeto GoogleMapOptions con las opciones que especifiques. Las opciones disponibles son exactamente las mismas que para los atributos XML. Puedes crear un objeto GoogleMapOptions como este:

GoogleMapOptions options = new GoogleMapOptions();

Y, luego, configurarlo de la siguiente manera:

options.mapType(GoogleMap.MAP_TYPE_SATELLITE)
    .compassEnabled(false)
    .rotateGesturesEnabled(false)
    .tiltGesturesEnabled(false);

Para aplicar estas opciones cuando creas un mapa, realiza una de estas acciones:

Mapas con padding

En este video, se muestra un ejemplo de un mapa con padding.

Los mapas de Google Maps están diseñados para ocupar toda la región definida en su elemento contenedor, que suele ser un objeto MapView o MapFragment. Hay varios aspectos relacionados con el modo en que aparece y se comporta el mapa que se definen según las dimensiones de su contenedor:

  • El objetivo de la cámara representa el centro de la región con padding.
  • La posición de los controles de mapa se define respecto de los bordes del mapa.
  • La información legal, como las declaraciones de derechos de autor o el logotipo de Google, aparecen en el borde inferior del mapa.

Puedes agregar padding en los bordes del mapa con el método GoogleMap.setPadding(). El mapa seguirá ocupando todo el contenedor, pero la posición del texto y los controles, los gestos del mapa y los movimientos de la cámara se comportarán como si estuvieran en un espacio más pequeño. Esto provocará los siguientes cambios:

  • Los movimientos de la cámara generados mediante llamadas a la API o al presionar un botón (p. ej., botones de zoom, brújula o Mi ubicación) se harán teniendo en cuenta la región con padding.
  • getCameraPosition() mostrará el centro de la región con padding.
  • Projection.getVisibleRegion() mostrará la región con padding.
  • Los controles de la IU se ubicarán a cierta distancia (cantidad de píxeles especificada) del borde del contenedor.

El padding puede resultar útil cuando se diseñan IU que se superponen con alguna parte del mapa. Por ejemplo, en la siguiente imagen, se muestra un mapa con padding a lo largo de los bordes superior y derecho. Los controles del mapa y el texto legal visibles aparecerán en los bordes de la región con padding, que se muestra en verde, mientras que el mapa seguirá ocupando todo el contenedor, que se muestra en azul. En este ejemplo, puedes utilizar un menú flotante en el lado derecho del mapa sin oscurecer los controles.

Mapas con padding

Localiza tu mapa

Cuando agregas un objeto MapView o MapFragment a tu app, los elementos de texto del mapa se muestran en el idioma adecuado según la ubicación y la configuración del dispositivo del usuario. Puedes restringir los idiomas que usa tu app a un subconjunto de todos los idiomas compatibles. Para ello, agrega un elemento resConfigs a tu archivo Gradle. Esta función resulta útil para quitar los idiomas innecesarios y también reduce el tamaño del objeto binario de tu app. Por ejemplo:

defaultConfig {
    resConfigs "en", "fr", "es", "zh", "de", "ja", "ru", "ko", "pt", "in"
}

Obtén más información sobre cómo localizar tu app para Android.