Marcadores

Los marcadores indican ubicaciones únicas en el mapa. Si deseas personalizar los marcadores, puedes cambiar el color predeterminado o reemplazar su ícono por una imagen personalizada. Las ventanas de información pueden proporcionarle contexto adicional a un marcador.

Muestras de código

El repositorio ApiDemos en GitHub incluye un ejemplo que muestra varias características de los marcadores:

Introducción

Los marcadores identifican ubicaciones en el mapa. El marcador predeterminado utiliza un ícono estándar, que refleja el estilo de Google Maps. Es posible cambiar el color, la imagen o el punto de anclaje del ícono a través de la API. Los marcadores son objetos de tipo Marker y se agregan al mapa con el método GoogleMap.addMarker(markerOptions).

Los marcadores están diseñados para ser interactivos. Reciben eventos de clic (click) de forma predeterminada y, a menudo, se utilizan con los objetos de escucha de eventos para mostrar ventanas de información. Si la propiedad draggable de un marcador se configura en true, el usuario podrá cambiar su posición. Para ello, deberás mantenerlo presionado y arrastrarlo.

De forma predeterminada, cuando un usuario presiona un marcador, aparece la barra de herramientas del mapa en la esquina inferior derecha. Esta barra de herramientas le proporciona al usuario un acceso rápido a la app para dispositivos móviles de Google Maps. Puedes inhabilitarla si lo deseas. Para obtener más información, consulta la guía de controles.

Cómo comenzar a utilizar marcadores

En este episodio de Maps Live, se comparte información básica sobre cómo agregar marcadores a tu mapa con Maps SDK for Android.

Agrega un marcador

En el siguiente ejemplo, se muestra cómo agregar un marcador a un mapa. El marcador se crea en las coordenadas 10,10 y muestra la string "Hola mundo" en una ventana de información cuando se hace clic en él.

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

Muestra información adicional sobre un marcador

Un requisito común es el de mostrar información adicional sobre un lugar o una ubicación cuando el usuario presiona un marcador en el mapa. Consulta la guía sobre ventanas de información.

Asocia datos a un marcador

Utiliza el método Marker.setTag() para almacenar un objeto de datos arbitrario con un marcador y el método Marker.getTag() para recuperar dicho objeto, como se muestra en este ejemplo:

/**
 * A demo class that stores and retrieves data objects with each marker.
 */
public class MarkerDemoActivity extends FragmentActivity implements
        OnMarkerClickListener,
        OnMapReadyCallback {

    private static final LatLng PERTH = new LatLng(-31.952854, 115.857342);
    private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);
    private static final LatLng BRISBANE = new LatLng(-27.47093, 153.0235);

    private Marker mPerth;
    private Marker mSydney;
    private Marker mBrisbane;

    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.marker_demo);

        SupportMapFragment mapFragment =
                (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    /** Called when the map is ready. */
    @Override
    public void onMapReady(GoogleMap map) {
        mMap = map;

        // Add some markers to the map, and add a data object to each marker.
        mPerth = mMap.addMarker(new MarkerOptions()
                .position(PERTH)
                .title("Perth"));
        mPerth.setTag(0);

        mSydney = mMap.addMarker(new MarkerOptions()
                .position(SYDNEY)
                .title("Sydney"));
        mSydney.setTag(0);

        mBrisbane = mMap.addMarker(new MarkerOptions()
                .position(BRISBANE)
                .title("Brisbane"));
        mBrisbane.setTag(0);

        // Set a listener for marker click.
        mMap.setOnMarkerClickListener(this);
    }

    /** Called when the user clicks a marker. */
    @Override
    public boolean onMarkerClick(final Marker marker) {

        // Retrieve the data from the marker.
        Integer clickCount = (Integer) marker.getTag();

        // Check if a click count was set, then display the click count.
        if (clickCount != null) {
            clickCount = clickCount + 1;
            marker.setTag(clickCount);
            Toast.makeText(this,
                           marker.getTitle() +
                           " has been clicked " + clickCount + " times.",
                           Toast.LENGTH_SHORT).show();
        }

        // Return false to indicate that we have not consumed the event and that we wish
        // for the default behavior to occur (which is for the camera to move such that the
        // marker is centered and for the marker's info window to open, if it has one).
        return false;
    }
}

A continuación, se incluyen algunos ejemplos de situaciones en las que resulta útil almacenar y recuperar datos con marcadores:

  • Tu app proporciona distintos tipos de marcadores, y debes tratarlos de manera diferente cuando el usuario hace clic en ellos. Para ello, puedes almacenar una string (String) con el marcador y también indicar el tipo.
  • Interactúas con un sistema que tiene identificadores de registro únicos, y los marcadores representan registros específicos en ese sistema.
  • Los datos del marcador indican que se use una prioridad para determinar el índice z del marcador.

Configura un marcador para que sea arrastrable

Puedes cambiar la posición de un marcador tras agregarlo al mapa, siempre que su propiedad draggable esté configurada en true. Mantén presionado el marcador para habilitar la función de arrastre. Cuando quites el dedo de la pantalla, el marcador permanecerá en esa posición.

De forma predeterminada, los marcadores no son arrastrables. Debes configurarlos explícitamente como tales con el método MarkerOptions.draggable(boolean) antes de agregarlos al mapa o con el método Marker.setDraggable(boolean) después de agregarlos. Consulta Eventos de arrastre del marcador para obtener información sobre cómo escuchar estos eventos.

El siguiente fragmento de código agrega un marcador arrastrable en Perth, Australia.

static final LatLng PERTH = new LatLng(-31.90, 115.86);
Marker perth = mMap.addMarker(new MarkerOptions()
                          .position(PERTH)
                          .draggable(true));

Personaliza un marcador

En este video, se muestran diferentes maneras de utilizar marcadores para visualizar ubicaciones en un mapa.

Los marcadores se pueden configurar para mostrar una imagen personalizada en lugar del ícono predeterminado. Para ello, se debe establecer una serie de propiedades que afectan el comportamiento visual del marcador.

Los marcadores admiten la personalización a través de las siguientes propiedades:

Posición (propiedad obligatoria)
Es el valor LatLng correspondiente a la posición del marcador en el mapa. Es la única propiedad obligatoria de un objeto Marker.
Anclaje
Es el punto en la imagen que se colocará en la posición LatLng del marcador. La ubicación predeterminada es en el medio de la parte inferior de la imagen.
Alfa
Establece la opacidad del marcador. El valor predeterminado es 1.0.
Título
Es una string que se muestra en la ventana de información cuando el usuario presiona el marcador.
Fragmento
Es el texto adicional que se muestra debajo del título.
Ícono
Es un mapa de bits que se muestra en lugar de la imagen predeterminada del marcador.
Arrastrable
Establece esta propiedad en true si deseas permitir que el usuario mueva el marcador. La configuración predeterminada es false.
Visible
Establece esta propiedad en false para que el marcador sea invisible. La configuración predeterminada es true.
Marcadores planos y tipo billboard (orientación)
De forma predeterminada, los marcadores se orientan respecto de la pantalla, es decir, no se rotan ni se inclinan con la cámara. Los marcadores planos se orientan respecto de la superficie de la Tierra, por lo que rotan y se inclinan con la cámara. Ninguno de estos dos tipos de marcadores cambiará de tamaño según el nivel de zoom. Para lograr este efecto, debes utilizar superposiciones de suelo.
Rotación
Es la orientación del marcador, especificada en grados en sentido horario. La posición predeterminada cambia si el marcador es plano. La posición predeterminada de un marcador plano se alinea respecto del norte. Si se utiliza un marcador de otro tipo, la posición predeterminada es hacia arriba y la rotación hace que siempre apunte hacia la cámara.

El siguiente fragmento crea un marcador simple con el ícono predeterminado.

static final LatLng MELBOURNE = new LatLng(-37.813, 144.962);
Marker melbourne = mMap.addMarker(new MarkerOptions()
                          .position(MELBOURNE));

Personaliza el color del marcador

Para personalizar el color de la imagen predeterminada del marcador, pasa un objeto BitmapDescriptor al método icon(). Puedes utilizar un conjunto de colores predefinidos en el objeto BitmapDescriptorFactory o establecer un color de marcador personalizado con el método BitmapDescriptorFactory.defaultMarker(float hue). El matiz debe ser un valor entre 0 y 360, lo que representa un punto determinado en una paleta de colores.

static final LatLng MELBOURNE = new LatLng(-37.813, 144.962);
Marker melbourne = mMap.addMarker(new MarkerOptions()
                          .position(MELBOURNE)
                          .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));

Personaliza la opacidad del marcador

Puedes controlar la opacidad de un marcador con el método MarkerOptions.alpha(). Se debe especificar el valor alfa con un número de punto flotante entre 0.0 y 1.0, donde 0 es completamente transparente y 1 es completamente opaco.

static final LatLng MELBOURNE = new LatLng(-37.813, 144.962);
Marker melbourne = mMap.addMarker(new MarkerOptions()
                          .position(MELBOURNE)
                          .alpha(0.7f));

Personaliza la imagen del marcador

Puedes reemplazar la imagen predeterminada del marcador por una personalizada, que suele llamarse ícono. Los íconos personalizados siempre se configuran como un objeto BitmapDescriptor y se definen con uno de los métodos de la clase BitmapDescriptorFactory.

fromAsset(String assetName)
Crea un marcador personalizado con el nombre de una imagen de mapa de bits en el directorio de recursos.
fromBitmap(Bitmap image)
Crea un marcador personalizado a partir de una imagen de mapa de bits.
fromFile(String fileName)
Crea un ícono personalizado con el nombre de un archivo de imagen de mapa de bits ubicado en el almacenamiento interno.
fromPath(String absolutePath)
Crea un marcador personalizado a partir de una ruta de acceso absoluta a un archivo de imagen de mapa de bits.
fromResource(int resourceId)
Crea un marcador personalizado con el ID de recurso de una imagen de mapa de bits.

El siguiente fragmento crea un marcador con un ícono personalizado:

  private static final LatLng MELBOURNE = new LatLng(-37.813, 144.962);
  private Marker melbourne = mMap.addMarker(new MarkerOptions()
                            .position(MELBOURNE)
                            .title("Melbourne")
                            .snippet("Population: 4,137,400")
                            .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));

Configura un marcador plano

Los íconos de marcador suelen dibujarse orientados respecto de la pantalla. Esto significa que no se cambiará su orientación al rotar, inclinar, acercar o alejar el mapa. Puedes configurar marcadores planos para que su orientación cambie con la de la Tierra. De esta manera, los marcadores rotarán cuando se rote el mapa y cambiarán de perspectiva cuando se lo incline. Los marcadores planos conservarán su tamaño cuando se acerque o se aleje el mapa.

Para cambiar la orientación del marcador, configura la propiedad flat del marcador en true.

static final LatLng PERTH = new LatLng(-31.90, 115.86);
Marker perth = mMap.addMarker(new MarkerOptions()
                          .position(PERTH)
                          .flat(true));

Rota un marcador

Puedes rotar un marcador alrededor de su punto de anclaje con el método Marker.setRotation(). La rotación se mide en grados en sentido horario respecto de la posición predeterminada. Si se utiliza un marcador plano en el mapa, la posición predeterminada es el norte. Si se utiliza un marcador de otro tipo, la posición predeterminada es hacia arriba y la rotación hace que siempre apunte hacia la cámara.

En el siguiente ejemplo, el marcador rota 90°. Al configurar el punto de anclaje en 0.5,0.5, el marcador rota sobre su centro, en lugar de su base.

static final LatLng PERTH = new LatLng(-31.90, 115.86);
Marker perth = mMap.addMarker(new MarkerOptions()
                          .position(PERTH)
                          .anchor(0.5,0.5)
                          .rotation(90.0));

Índice z del marcador

El índice z especifica el orden en que se debe apilar este marcador respecto de otros en el mapa. Un marcador con un índice z alto se dibujará encima de aquellos con índices z más bajos. El valor predeterminado del índice z es 0.

Para establecer el índice z en el objeto de opciones del marcador, llama a MarkerOptions.zIndex(), como se muestra en el siguiente fragmento de código:

@Override
public void onMapReady(GoogleMap map) {
    map.addMarker(new MarkerOptions()
        .position(new LatLng(10, 10))
        .title("Marker z1")
        .zIndex(1.0f));
}

Para acceder al índice z del marcador, llama a Marker.getZIndex() y, para cambiarlo, llama a Marker.setZIndex().

Los marcadores siempre se dibujan encima de las capas de mosaicos y otras superposiciones que no corresponden a marcadores (superposiciones de suelo, polilíneas, polígonos y otras formas), sin importar el índice z de las demás superposiciones. Se considera que los marcadores pertenecen efectivamente a un grupo de índice z aparte respecto de otras superposiciones.

Obtén información acerca del efecto del índice z sobre los eventos de clic más abajo.

Controla los eventos de marcador

La API de Google Maps te permite escuchar eventos de marcador y responder a ellos. Para escuchar estos eventos, debes configurar el objeto de escucha correspondiente en el objeto GoogleMap al que pertenecen los marcadores. Cuando se produzca el evento en uno de los marcadores del mapa, se invocará la devolución de llamada del objeto de escucha y se pasará el objeto Marker correspondiente como parámetro. Para comparar este objeto Marker con tu propia referencia a un objeto Marker, debes utilizar equals() y no ==.

Puedes escuchar los siguientes eventos:

Eventos de clic en el marcador

Puedes utilizar un objeto OnMarkerClickListener a fin de escuchar los eventos de clic en el marcador. Para configurar este objeto de escucha en el mapa, llama a GoogleMap.setOnMarkerClickListener(OnMarkerClickListener). Cuando un usuario haga clic en un marcador, se llamará a onMarkerClick(Marker) y se pasará el marcador como argumento. Este método muestra un valor booleano que indica si consumiste el evento (es decir, si deseas suprimir el comportamiento predeterminado). Si muestra false, se sumará el comportamiento predeterminado al comportamiento personalizado. El comportamiento predeterminado de un evento de clic en el marcador es mostrar la ventana de información relevante (si corresponde) y mover la cámara para que el marcador quede centrado en el mapa.

Efecto del índice z en los eventos de clic:

  • Cuando un usuario hace clic en un clúster de marcadores, se activa el evento de clic para el marcador con el índice z más alto.
  • Como máximo, se activará un evento por clic. En otras palabras, el clic no se pasa a los marcadores ni a otras superposiciones con valores del índice z más bajos.
  • Al hacer clic en un clúster de marcadores, se generan distintos clics para cada elemento del clúster de forma cíclica a fin de seleccionar cada uno de ellos. Para determinar el orden del ciclo, primero se prioriza el índice z y, luego, la proximidad al punto del clic.
  • Si el usuario hace clic fuera de la proximidad del clúster, la API vuelve a calcular el clúster y restablece el estado del ciclo de clics para que comience desde el principio.
  • Antes de que se reinicie el ciclo, el evento de clic pasa de los clústeres de marcadores a otras formas y superposiciones.
  • Se considera que los marcadores pertenecen efectivamente a un grupo de índice z aparte respecto de otras superposiciones o formas (polilíneas, polígonos, círculos o superposiciones de suelo), sin considerar el índice z de las demás superposiciones. Si varios marcadores, superposiciones o formas se apilan unos sobre otros, el evento de clic primero pasará por el clúster de marcadores y, luego, se activará para otras superposiciones o formas en las que se pueda hacer clic según sus valores del índice z.

Eventos de arrastre del marcador

Puedes utilizar un objeto OnMarkerDragListener para escuchar los eventos de arrastre de un marcador. Para configurar este objeto de escucha en el mapa, llama a GoogleMap.setOnMarkerDragListener. Para arrastrar un marcador, el usuario debe mantenerlo presionado. Cuando quite el dedo de la pantalla, el marcador permanecerá en esa posición. Cuando se comienza a arrastrar un marcador, primero se llama a onMarkerDragStart(Marker). Mientras se lo arrastra, se llama a onMarkerDrag(Marker) de forma constante. Y cuando se termina de arrastrar, se llama a onMarkerDragEnd(Marker). Para obtener la posición del marcador en cualquier momento, llama a Marker.getPosition().