Select platform: [Android](https://developers.google.com/maps/documentation/android-sdk/groundoverlay.md.txt "View this page for the Android platform docs.") [iOS](https://developers.google.com/maps/documentation/ios-sdk/overlays.md.txt "View this page for the iOS platform docs.") [JavaScript](https://developers.google.com/maps/documentation/javascript/groundoverlays.md.txt "View this page for the JavaScript platform docs.")

<br />

![](https://developers.google.com/static/maps/documentation/android-sdk/images/android-groundoverlay.png)

Ground overlays are image overlays that are tied to latitude/longitude
coordinates, so they move when you drag or zoom the map.

## Code samples

The [ApiDemos repository](https://github.com/googlemaps-samples/android-samples/blob/main/ApiDemos) on GitHub includes a
sample that demonstrates ground overlays:

- [GroundOverlayDemoActivity - Java](https://github.com/googlemaps-samples/android-samples/blob/main/ApiDemos/project/java-app/src/main/java/com/example/mapdemo/GroundOverlayDemoActivity.java): Ground overlay features and listeners in Java
- [GroundOverlayDemoActivity - Kotlin](https://github.com/googlemaps-samples/android-samples/blob/main/ApiDemos/project/kotlin-app/src/main/java/com/example/kotlindemos/GroundOverlayDemoActivity.kt): Ground overlay features and listeners in Kotlin

## Introduction

A ground overlay is an image that is fixed to a map. Unlike [markers](https://developers.google.com/maps/documentation/android-sdk/marker.md.txt), ground
overlays are oriented against the Earth's surface rather than the screen, so
rotating, tilting or zooming the map will change the orientation of the image.
Ground overlays are useful when you wish to fix a single image at one area on
the map. If you want to add extensive imagery that covers a large portion of the
map, you should consider a [Tile overlay](https://developers.google.com/maps/documentation/android-sdk/tileoverlay.md.txt).

## Add an overlay

To add a [`GroundOverlay`](https://developers.google.com/android/reference/com/google/android/gms/maps/model/GroundOverlay.md.txt), create a
[`GroundOverlayOptions`](https://developers.google.com/android/reference/com/google/android/gms/maps/model/GroundOverlayOptions.md.txt) object that defines both an
image and a position. You can optionally specify additional settings that will
affect the positioning of the image on the map. Once you've defined the
necessary options, pass the object to the `GoogleMap.addGroundOverlay()`
method to add the image to the map. The `addGroundOverlay()` method returns a
[`GroundOverlay`](https://developers.google.com/android/reference/com/google/android/gms/maps/model/GroundOverlay.md.txt) object; you should retain a reference to
this object if you want to modify it later.

> [!NOTE]
> **Note:** When the image is added to the map it will be converted to an image with sides that are powers of two. You can avoid this conversion by using an original image with dimensions that are powers of two --- for example, 128x512 or 1024x1024.

Step by step:

1. Instantiate a new `GroundOverlayOptions` object
2. Specify the image as a `BitmapDescriptor`.
3. Set the position of the image using one of the available methods:
   - `position(LatLng location, float width, float height)`
   - `position(LatLng location, float width)`
   - `positionFromBounds(LatLngBounds bounds)`
4. Set any optional properties, such as `transparency`, as desired.
5. Call `GoogleMap.addGroundOverlay()` to add the image to the map.

The below example demonstrates how to add a ground overlay to an existing
`GoogleMap` object.


### Kotlin

```kotlin
val newarkLatLng = LatLng(40.714086, -74.228697)
val newarkMap = GroundOverlayOptions()
    .image(BitmapDescriptorFactory.fromResource(R.drawable.newark_nj_1922))
    .position(newarkLatLng, 8600f, 6500f)
map.addGroundOverlay(newarkMap)

      
```

### Java

```java
LatLng newarkLatLng = new LatLng(40.714086, -74.228697);

GroundOverlayOptions newarkMap =
        new GroundOverlayOptions()
                .image(BitmapDescriptorFactory.fromResource(R.drawable.newark_nj_1922))
                .position(newarkLatLng, 8600f, 6500f);
map.addGroundOverlay(newarkMap);

      
```

<br />

If you wish to change or remove a ground overlay after you've added it to
the map, ensure that you keep hold of the `GroundOverlay` object. You can
modify the overlay later by making changes to this object.


### Kotlin

```kotlin
// Add an overlay to the map, retaining a handle to the GroundOverlay object.
val imageOverlay = map.addGroundOverlay(newarkMap)

      
```

### Java

```java
// Add an overlay to the map, retaining a handle to the GroundOverlay object.
GroundOverlay imageOverlay = map.addGroundOverlay(newarkMap);

      
```

<br />

## Remove an overlay

You can remove a ground overlay with the
[`GroundOverlay.remove()`](https://developers.google.com/android/reference/com/google/android/gms/maps/model/GroundOverlay.md.txt#remove()) method.


### Kotlin

```kotlin
imageOverlay?.remove()

      
```

### Java

```java
imageOverlay.remove();

      
```

<br />

## Change an overlay

You can change the ground overlay image after it's been added to the map with
the `GroundOverlay.setImage(BitmapDescriptor)` method.


### Kotlin

```kotlin
// Update the GroundOverlay with a new image of the same dimension
imageOverlay?.setImage(BitmapDescriptorFactory.fromResource(R.drawable.newark_nj_1922))

      
```

### Java

```java
// Update the GroundOverlay with a new image of the same dimension
imageOverlay.setImage(BitmapDescriptorFactory.fromResource(R.drawable.newark_nj_1922));

      
```

<br />

The `setImage()` method will replace the existing image with another image of
the same dimensions.

## Position a Ground Overlay

There are two ways to specify the position of the ground overlay:

- Using a `LatLng` to center the overlay, and dimensions in meters to specify the size of the image.
- Using a `LatLngBounds` to specify the north east and south west corners of the image.

You must specify the position of the ground overlay before it is added to the
map.

### Use location to position an image

When you add the image you specify a LatLng to which the anchor will be fixed
and the width of the overlay (in meters). The
[`anchor`](https://developers.google.com/android/reference/com/google/android/gms/maps/model/GroundOverlayOptions.md.txt#anchor(float,float)) defaults to the center of the
image. You can optionally provide the height of the overlay (in meters). If
you do not provide the height of the overlay, it will be automatically
calculated to preserve the proportions of the image.

The below code places an image at position `40.714086, -74.228697`
that is 8.6km wide by 6.5km high. The image is anchored at the bottom left.


### Kotlin

```kotlin
val newarkMap = GroundOverlayOptions()
    .image(BitmapDescriptorFactory.fromResource(R.drawable.newark_nj_1922))
    .anchor(0f, 1f)
    .position(LatLng(40.714086, -74.228697), 8600f, 6500f)

      
```

### Java

```java
GroundOverlayOptions newarkMap =
        new GroundOverlayOptions()
                .image(BitmapDescriptorFactory.fromResource(R.drawable.newark_nj_1922))
                .anchor(0, 1)
                .position(new LatLng(40.714086, -74.228697), 8600f, 6500f);

      
```

<br />

### Use LatLngBounds to position an image

You provide a [`LatLngBounds`](https://developers.google.com/android/reference/com/google/android/gms/maps/model/LatLngBounds.md.txt) which contains the image. The
`LatLngBounds` sets the north east, and south west corners of the image. When
the image is drawn on the map it will be rotated to fit the bounds. If the
bounds do not match the original aspect ratio, the image will be skewed.

The below code places an image on the map with its South West corner bound to
`40.712216,-74.22655` and its North East corner bound to
`40.773941, -74.12544`.


### Kotlin

```kotlin
val newarkBounds = LatLngBounds(
    LatLng(40.712216, -74.22655), // South west corner
    LatLng(40.773941, -74.12544), // North east corner
)
val newarkMap = GroundOverlayOptions()
    .image(BitmapDescriptorFactory.fromResource(R.drawable.newark_nj_1922))
    .positionFromBounds(newarkBounds)

      
```

### Java

```java
LatLngBounds newarkBounds =
        new LatLngBounds(
                new LatLng(40.712216, -74.22655), // South west corner
                new LatLng(40.773941, -74.12544)); // North east corner
GroundOverlayOptions newarkMap =
        new GroundOverlayOptions()
                .image(BitmapDescriptorFactory.fromResource(R.drawable.newark_nj_1922))
                .positionFromBounds(newarkBounds);

      
```

<br />

## Associate data with a ground overlay

You can call [`GroundOverlay.setTag()`](https://developers.google.com/android/reference/com/google/android/gms/maps/model/GroundOverlay.md.txt#setTag(java.lang.Object)) to store an
arbitrary data object with a ground overlay, and retrieve the data
object using [`GroundOverlay.getTag()`](https://developers.google.com/android/reference/com/google/android/gms/maps/model/GroundOverlay.md.txt#getTag()).

The following code sample stores a string description with a ground overlay:


### Kotlin

```kotlin
val sydneyGroundOverlay = map.addGroundOverlay(
    GroundOverlayOptions()
        .image(BitmapDescriptorFactory.fromResource(R.drawable.harbour_bridge))
        .position(LatLng(-33.873, 151.206), 100f)
        .clickable(true),
)
sydneyGroundOverlay?.tag = "Sydney"

      
```

### Java

```java
GroundOverlay sydneyGroundOverlay =
        map.addGroundOverlay(
                new GroundOverlayOptions()
                        .image(
                                BitmapDescriptorFactory.fromResource(
                                        R.drawable.harbour_bridge))
                        .position(new LatLng(-33.873, 151.206), 100)
                        .clickable(true));

sydneyGroundOverlay.setTag("Sydney");

      
```

<br />

Here are some examples of scenarios when it's useful to store and retrieve data
with ground overlays:

- Your app may cater for different ground overlays, and you want to treat them differently when the user clicks them.
- You may be interfacing with a system that has unique record identifiers, where the overlays represent specific records in that system.
- The overlay data may indicate a priority to determine the z-index for the overlay.

## Handle ground overlay events

By default, ground overlays are
not clickable. You can enable and disable the clickability by calling
`GroundOverlay.setClickable(boolean)`.

Use an [`OnGroundOverlayClickListener`](https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.OnGroundOverlayClickListener.md.txt)
to listen to click events on a clickable ground overlay. To set this listener on
the map, call
`GoogleMap.setOnGroundOverlayClickListener(OnGroundOverlayClickListener)`.
When a user clicks on a ground overlay, you will receive an
`onGroundOverlayClick(GroundOverlay)` callback.

> [!NOTE]
> **Note:** If multiple overlays or shapes (markers, polylines, polygons, circles and/or ground overlays) are overlaid on top of each other, the click event is cycled through the cluster of markers first, then triggered for other clickable overlays or shapes based on their z-index values. At most one event is triggered per click. In other words, the click is not passed down to the overlays or shapes with lower z-index values. Read more about [marker z-index
> and click events](https://developers.google.com/maps/documentation/android-sdk/marker#click-index).