En el artículo anterior del curso vimos cómo realizar todos los preparativos necesarios para comenzar a utilizar la nueva versión de Google Maps para Android (Google Maps Android API v2): descargar las librerías necesarias, obtener la API Key y configurar un nuevo proyecto en Eclipse.
En esta segunda entrega vamos a hacer un repaso de las opciones básicas de los nuevos mapas: elegir el tipo de mapa a mostrar, movernos por él de forma programática, y obtener los datos de la posición actual. Como aplicación de ejemplo (que podéis descargar al final de este artículo), tomaremos como base la ya creada en el artículo anterior, a la que añadiremos varias opciones de menú para demostrar el funcionamiento de algunas funciones del mapa.
Si hacemos un poco de memoria, recordaremos cómo en la antigua versión de la API de Google Maps era bastante poco homogéneo el acceso y modificación de determinados datos del mapa. Por ejemplo, la consulta de la posición actual o la configuración del tipo de mapa se hacían directamente sobre el control MapView, mientras que la manipulación de la posición y el zoom se hacían a través del controlador asociado al mapa (MapController). Además, el tratamiento de las coordenadas y las unidades utilizadas eran algo peculiares, teniendo estar continuamente convirtiendo de grados a microgrados y de estos a objetos GeoPoint, etc.
Con la nueva API, todas las operaciones se realizarán directamente sobre un objeto GoogleMap, el componente base de la API. Accederemos a este componente llamando al método getMap() del fragmento MapFragment que contenga nuestro mapa. Podríamos hacerlo de la siguiente forma:
import com.google.android.gms.maps.GoogleMap;
...
GoogleMap mapa = ((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map)).getMap();
Una vez obtenida esta referencia a nuestro objeto GoogleMap podremos realizar sobre él la mayoría de las acciones básicas del mapa.
Así, por ejemplo, para modificar el tipo de mapa mostrado podremos utilizar una llamada a su método setMapType(), pasando como parámetro el tipo de mapa:
- MAP_TYPE_NORMAL
- MAP_TYPE_HYBRID
- MAP_TYPE_SATELLITE
- MAP_TYPE_TERRAIN
Para nuestro ejemplo voy a utilizar una variable que almacene el tipo de mapa actual (del 0 al 3) y habilitaremos una opción de menú para ir alternando entre las distintas opciones. Quedaría de la siguiente forma:
private void alternarVista()
{
vista = (vista + 1) % 4;
switch(vista)
{
case 0:
mapa.setMapType(GoogleMap.MAP_TYPE_NORMAL);
break;
case 1:
mapa.setMapType(GoogleMap.MAP_TYPE_HYBRID);
break;
case 2:
mapa.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
break;
case 3:
mapa.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
break;
}
}
En cuanto al movimiento sobre el mapa, con esta nueva versión de la API vamos a tener mucha más libertad que con la anterior versión, ya que podremos mover libremente nuestro punto de vista (o cámara, como lo han llamado los chicos de Android) por un espacio 3D. De esta forma, ya no sólo podremos hablar de latitud-longitud (target) y zoom, sino también de orientación (bearing) y ángulo de visión (tilt). La manipulación de los 2 últimos parámetros unida a posibilidad actual de ver edificios en 3D de muchas ciudades nos abren un mundo de posibilidades.
El movimiento de la cámara se va a realizar siempre mediante la construcción de un objeto CameraUpdate con los parámetros necesarios. Para los movimientos más básicos como la actualización de la latitud y longitud o el nivel de zoom podremos utilizar la clase CameraUpdateFactory y sus métodos estáticos que nos facilitará un poco el trabajo.
Así por ejemplo, para cambiar sólo el nivel de zoom podremos utilizar los siguientes métodos para crear nuestro CameraUpdate:
- CameraUpdateFactory.zoomIn(). Aumenta en 1 el nivel de zoom.
- CameraUpdateFactory.zoomOut(). Disminuye en 1 el nivel de zoom.
- CameraUpdateFactory.zoomTo(nivel_de_zoom). Establece el nivel de zoom.
Por su parte, para actualizar sólo la latitud-longitud de la cámara podremos utilizar:
- CameraUpdateFactory.newLatLng(lat, long). Establece la lat-lng expresadas en grados.
Si queremos modificar los dos parámetros anteriores de forma conjunta, también tendremos disponible el método siguiente:
- CameraUpdateFactory.newLatLngZoom(lat, long, zoom). Establece la lat-lng y el zoom.
Para movernos lateralmente por el mapa (panning) podríamos utilizar los métodos de scroll:
- CameraUpdateFactory.scrollBy(scrollHorizontal, scrollVertical). Scroll expresado en píxeles.
Tras construir el objeto CameraUpdate con los parámetros de posición tendremos que llamar a los métodos moveCamera() o animateCamera() de nuestro objeto GoogleMap, dependiendo de si queremos que la actualización de la vista se muestre directamente o de forma animada.
Con esto en cuenta, si quisiéramos por ejemplo centrar la vista en España con un zoom de 5 podríamos hacer lo siguiente:
CameraUpdate camUpd1 = CameraUpdateFactory.newLatLng(new LatLng(40.41, -3.69)); mapa.moveCamera(camUpd1);
Además de los movimientos básicos que hemos comentado, si queremos modificar los demás parámetros de la cámara o varios de ellos simultaneamente tendremos disponible el método más general CameraUpdateFactory.newCameraPosition() que recibe como parámetro un objeto de tipo CameraPosition. Este objeto los construiremos indicando todos los parámetros de la posición de la cámara a través de su método Builder() de la siguiente forma:
LatLng madrid = new LatLng(40.417325, -3.683081); CameraPosition camPos = new CameraPosition.Builder() .target(madrid) //Centramos el mapa en Madrid .zoom(19) //Establecemos el zoom en 19 .bearing(45) //Establecemos la orientación con el noreste arriba .tilt(70) //Bajamos el punto de vista de la cámara 70 grados .build(); CameraUpdate camUpd3 = CameraUpdateFactory.newCameraPosition(camPos); mapa.animateCamera(camUpd3);
Como podemos comprobar, mediante este mecanismo podemos modificar todos los parámetros de posición de la cámara (o sólo algunos de ellos) al mismo tiempo. En nuestro caso de ejemplo hemos centrado la vista del mapa sobre el parque de El Retiro de Madrid, con un nivel de zoom de 19, una orientación de 45 grados para que el noreste esté hacia arriba y un ángulo de visión de 70 grados de forma que veamos en 3D el monumento a Alfonso XII en la vista de mapa NORMAL. En la siguiente imagen vemos el resultado:
Como podéis ver, en esta nueva versión de la API se facilita bastante el posicionamiento dentro del mapa, y el uso de las clases CameraUpdate y CameraPosition resulta bastante intuitivo.
Bien, pues ya hemos hablado de cómo modificar nuestro punto de vista sobre el mapa, pero si el usuario se mueve de forma manual por él, ¿cómo podemos conocer en un momento dado la posición de la cámara?
Pues igual de fácil, mediante el método getCameraPosition(), que nos devuelve un objeto CameraPosition como el que ya conocíamos. Accediendo a los distintos métodos y propiedades de este objeto podemos conocer con exactitud la posición de la cámara, la orientación y el nivel de zoom.
CameraPosition camPos = mapa.getCameraPosition(); LatLng coordenadas = camPos.target; double latitud = coordenadas.latitude; double longitud = coordenadas.longitude; float zoom = camPos.zoom; float orientacion = camPos.bearing; float angulo = camPos.titl;
En nuestra aplicación de ejemplo, que podéis descargar al final del artículo, he añadido una nueva opción de menú que muestra en un mensaje toast la latitud y longitud actual de la vista de mapa.
Y con esto habríamos terminado de describir las acciones básicas de configuración y movimiento sobre el mapa. En los próximos artículos veremos más opciones, como la forma de añadir marcadores o dibujar sobre el mapa.
Puedes consultar y/o descargar el código completo de los ejemplos desarrollados en este artículo accediendo a la pagina del curso en GitHub.


Fántasticos tutoriales sobre Map Fragment. Me han venido genial!
Te felicito por el gran trabajo realizado en el curso de Android.
Hola, se que no tiene nada que ver con el tema, pero no sabía como contactar con usted, no tengo ni idea de programar pero diseño juegos de mesa y me gustaría compartir contigo un proyecto para un juego de cartas coleccionables el cual esta pensado y diseñado para ser jugado en un móvil, es decir cómodo, sencillo y rápido, haciendo que la interfaz no necesite de zoom o aparatosos cambios de vista para ser jugado, sino que apenas el jugador solo debe arrastrar la carta. Aviso que si buscas dinero conseguiras pues lo que el juego pueda sacar en un mercado sin competencia alguno, que será repartido entre los dos como socios iguales, yo me encargaría del diseño y testeo de la edición y juego. Un saludo y gracias por su tiempo si le interesa mas sobre el juego contacte a dortiz90 @gmail.com (todo junto)
Atentamente: Daniel Ortiz
una cosa importante la linea de “getSupportFragmentManager” no jala, creo que falta definición de algún objeto o algo, si puedes ayudarme sería excelente
Hola,
Gracias a tu ejemplo he podido arreglar un error al carga el mapa.
No estaba utilizando la versión de android-support-v4.jar que tocaba. Vaya dolor de cabeza >_<
Saludos!
Magnífico artículo.
Hola, ante todo felicidades por la entrada, muy útil.
Estoy intentado reproducir el ejemplo y al intentar acceder al mapa de la siguiente manera:
SupportMapFragment mapFrag = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
mapa = mapFrag.getMap();
Observo que el objeto mapFrag está inicializado, pero el objeto “mapa” viene a null, no sé si será por la versión de android-supportV4, como indica el compañero.
No sé como comprobar si la versión de android-supportV4 es la correcta….
El caso es que en mi aplicación estoy usando la libreria de ActionBarSherlock, y esta trae el android-support, no sé si irá por ahí la cosa.
Saludos!
Muy b ueno sigue asi soy tu fan!! yeah muy bien muchacho sigue asi!