Overlays

An overlay is an element visually representing geographical information, which you can freely place on your map. The NAVER Maps SDK provides various types of overlays, such as markers, info windows and shapes. For more information, refer to the documentation of each overlay.

Add and remove overlays

Create objects

All overlays except location overlays can be created just like a general Java object.

The following code example creates a marker object.

Marker marker = new Marker();

Java

Marker marker = new Marker();

Kotlin

val marker = Marker()

You can get a location overlay object, with the locationOverlay property of NaverMap.

The following code example gets a location overlay object.

LocationOverlay locationOverlay = naverMap.getLocationOverlay();

Java

LocationOverlay locationOverlay = naverMap.getLocationOverlay();

Kotlin

val locationOverlay = naverMap.locationOverlay

Add overlays

All overlays except location overlays can be added to the map by specifying the map property. For information on how to add location overlays to the map, refer to Location Overlays.

The following code example adds a marker to the map.

marker.setMap(naverMap);

Java

marker.setMap(naverMap);

Kotlin

marker.map = naverMap

Besides the map property, you can also use the open() method, to open an info window for your map or markers.

The following code example adds an info window to a marker.

infoWindow.open(marker);

Java

infoWindow.open(marker);

Kotlin

infoWindow.open(marker)

As the map is the property of an overlay, one overlay cannot be displayed on two or more maps at the same time. If you newly set the map property to an overlay that is already on the map, the overlay disappears from the previous map and appears on the new map.

Remove overlays

All overlays except location overlays can be removed from the map by setting the map property to null. For information on how to remove location overlays from the map, refer to Location Overlays.

The following code example removes a marker from the map.

marker.setMap(null);

Java

marker.setMap(null);

Kotlin

marker.map = null

Besides the map property, you can also use the close() method to close an info window.

The following code example closes an info window.

infoWindow.close();

Java

infoWindow.close();

Kotlin

infoWindow.close()

Multithreading

An overlay object can be created by any thread. However, since an overlay’s properties are not thread-safe, it cannot be accessed simultaneously by multiple threads. Especially the properties of an overlay added to a map should be accessed by the main thread; otherwise, CalledFromWrongThreadException occurs. Note that the exception does not occur even if other threads access the properties of the overlay that is not added to a map.

Therefore, when handling a large number of overlays, you can use a background thread to create an object and set initial options while using the main thread only to add an overlay to the map for efficiency. The following code example creates 1,000 markers and set their properties in a background thread and adds them to the map.

Executor executor = ...
Handler handler = new Handler(Looper.getMainLooper());

executor.execute(() -> {
    // Background thread
    List<Marker> markers = new ArrayList<>();

    for (int i = 0; i < 1000; ++i) {
        Marker marker = new Marker();
        marker.setPosition(...);
        marker.setIcon(...);
        marker.setCaptionText(...);
        markers.add(marker);
    }

    handler.post(() -> {
        // Main thread
        for (Marker marker : markers) {
            marker.setMap(naverMap);
        }
    });
});

Java

Executor executor = ...
Handler handler = new Handler(Looper.getMainLooper());

executor.execute(() -> {
    // Background thread
    List<Marker> markers = new ArrayList<>();

    for (int i = 0; i < 1000; ++i) {
        Marker marker = new Marker();
        marker.setPosition(...);
        marker.setIcon(...);
        marker.setCaptionText(...);
        markers.add(marker);
    }

    handler.post(() -> {
        // Main thread
        for (Marker marker : markers) {
            marker.setMap(naverMap);
        }
    });
});

Kotlin

val executor: Executors = ...
val handler = Handler(Looper.getMainLooper())

executor.execute {
    // Background thread
    val markers = mutableListOf<Marker>()

    repeat(1000) {
        markers += Marker().apply {
            position = ...
            icon = ...
            captionText = ...
        }
    }

    handler.post {
        // Main thread
        markers.forEach { marker ->
            marker.map = naverMap
        }
    }
}

Bitmap

Most overlays including markers, info windows, location overlays, ground overlays and path overlays use bitmap images. To use bitmap images for your overlays, you should create an OverlayImage object.

Create OverlayImage objects

OverlayImage is an immutable class representing a bitmap image that can be used as an icon. Using the factory methods defined in the OverlayImage class, you can create an instance from Drawable resources, assets and bitmaps. The list below describes some factory methods.

  • fromResource(): Creates an object from drawable resources.
  • fromAsset(): Creates an object from assets.
  • fromBitmap(): Creates an object from Bitmap.
  • fromView(): Creates an object from View. The view is rendered as soon as the method is called, and the rendered result is saved as a bitmap.

The following code example creates an OverlayImage object from drawable resources.

OverlayImage image = OverlayImage.fromResource(R.drawable.marker_icon);

Java

OverlayImage image = OverlayImage.fromResource(R.drawable.marker_icon);

Kotlin

val image = OverlayImage.fromResource(R.drawable.marker_icon)

Set the OverlayImage object to the property of the overlay that needs a bitmap, and the image is reflected. For more information, refer to the documentation of each overlay.

The following code example sets a marker icon.

OverlayImage image = OverlayImage.fromResource(R.drawable.marker_icon);
marker.setIcon(image);

Java

OverlayImage image = OverlayImage.fromResource(R.drawable.marker_icon);
marker.setIcon(image);

Kotlin

val image = OverlayImage.fromResource(R.drawable.marker_icon)
marker.icon = image

Memory management

Since the OverlayImage object handles bitmap images, you should carefully manage memory. If multiple overlays use the same image, only one OverlayImage instance is needed.

The following code example shows a bad case where marker1 and marker2 share one bitmap image but marker3 and marker4 each have the same bitmap image.

// Good: marker1 and 2 share the same bitmap.
OverlayImage image = OverlayImage.fromBitmap(bitmap)
marker1.setIcon(image);
marker2.setIcon(image);

// Bad: marker3 and 4 each have the same bitmap.
marker3.setIcon(OverlayImage.fromBitmap(bitmap));
marker4.setIcon(OverlayImage.fromBitmap(bitmap));

Java

// Good: marker1 and 2 share the same bitmap.
OverlayImage image = OverlayImage.fromBitmap(bitmap)
marker1.setIcon(image);
marker2.setIcon(image);

// Bad: marker3 and 4 each have the same bitmap.
marker3.setIcon(OverlayImage.fromBitmap(bitmap));
marker4.setIcon(OverlayImage.fromBitmap(bitmap));

Kotlin

// Good: marker1 and 2 share the same bitmap.
OverlayImage image = OverlayImage.fromBitmap(bitmap)
marker1.icon = image
marker2.icon = image

// Bad: marker3 and 4 each have the same bitmap.
marker3.icon = OverlayImage.fromBitmap(bitmap)
marker4.icon = OverlayImage.fromBitmap(bitmap)

Note that if OverlayImage objects are created from resources and assets, and the resource and asset represented by OverlayImage are the same, the instances share the same bitmap even if they are different.

The following code example shows a case where marker1, marker2, marker3, and marker4 share the same bitmap.

// Good: marker1 and 2 share the same bitmap.
OverlayImage image = OverlayImage.fromResource(R.drawable.marker_icon);
marker1.setIcon(image);
marker2.setIcon(image);

// OK: marker3 and 4 each use different OverlayImage objects but refer to the same resource, so they share the same bitmap.
marker3.setIcon(OverlayImage.fromResource(R.drawable.marker_icon));
marker4.setIcon(OverlayImage.fromResource(R.drawable.marker_icon));

Java

// Good: marker1 and 2 share the same bitmap.
OverlayImage image = OverlayImage.fromResource(R.drawable.marker_icon);
marker1.setIcon(image);
marker2.setIcon(image);

// OK: marker3 and 4 each use different OverlayImage objects but refer to the same resource, so they share the same bitmap.
marker3.setIcon(OverlayImage.fromResource(R.drawable.marker_icon));
marker4.setIcon(OverlayImage.fromResource(R.drawable.marker_icon));

Kotlin

// Good: marker1 and 2 share the same bitmap.
val image = OverlayImage.fromResource(R.drawable.marker_icon)
marker1.icon = image
marker2.icon = image

// OK: marker3 and 4 each use different OverlayImage objects but refer to the same resource, so they share the same bitmap.
marker3.icon = OverlayImage.fromResource(R.drawable.marker_icon)
marker4.icon = OverlayImage.fromResource(R.drawable.marker_icon)

If too many bitmap images are used for the map to handle, the map rendering becomes very slow with a log message saying "Overlay image atlas overflow" in Logcat. And if the memory usage is too high, the process will be terminated because of out of memory (OOM).

Stacking order of overlays

When multiple overlays are overlapped on the screen, an overlay with a higher stack order is displayed on top of those with lower stack orders. The stack order is specified depending on the type of an overlay by default, but can be changed.

Global z-index

The globalZIndex property specifies the stack order of an overlay. If globalZIndex is 0 or bigger, the overlay is drawn on top of symbols; if the property is smaller than 0, it is drawn beneath symbols. Note that an overlay is always drawn on top of the map background no matter how small globalZIndex is. The default globalZIndex values for each overlay type are as follows.

  • Info window: 400000
  • Location overlay: 300000
  • Marker: 200000
  • Arrowhead path overlay: 100000
  • (Map symbols)
  • Path overlay: -100000
  • Shape (polygon, polyline, circle): -200000
  • Ground overlay: -300000
  • (Map background)

For example, a path is drawn on top of a shape, and beneath a symbol on the map by default. However, if the globalZIndex property of a path is set to 250000, it is drawn on top of markers and beneath a location overlay.

The following code example specifies the stacking order of three overlays, as polygon -> path -> marker.

polygon.setGlobalZIndex(150000);
path.setGlobalZIndex(50000);
marker.setGlobalZIndex(-50000);

Java

polygon.setGlobalZIndex(150000);
path.setGlobalZIndex(50000);
marker.setGlobalZIndex(-50000);

Kotlin

polygon.globalZIndex = 150000
path.globalZIndex = 50000
marker.globalZIndex = -50000

Global z-indexes specified

Local z-index

The zIndex property specifies the stack order of overlays with the same globalZIndex. If two overlays have the same globalZIndex value, an overlay with the higher zIndex is displayed on top of the other. For example, even if the zIndex of a marker is set to 1, and the zIndex of a ground overlay is set to 2, the marker is drawn on top of the ground overlay because the marker’s default globalZIndex is 200000, and that of the ground overlay is -300000. Since the default value of the zIndex property is 0 regardless of the type of an overlay, zIndex can be used more intuitively than globalZIndex to specify the stack order of overlays with the same type.

The following code example specifies the stacking order of three markers as yellow -> green -> blue.

yellowMarker.setZIndex(100);
greenMarker.setZIndex(0);
blueMarker.setZIndex(-10);

Java

yellowMarker.setZIndex(100);
greenMarker.setZIndex(0);
blueMarker.setZIndex(-10);

Kotlin

yellowMarker.zIndex = 100
greenMarker.zIndex = 0
blueMarker.zIndex = -10

Markers with z-indexes specified

Show and hide overlays

All overlays have the visibility and maximum/minimum zoom level properties. To hide an overlay temporarily or in a certain situation, use these properties, rather than the map property.

Visibility

Set isVisible to false to hide an overlay. The relation between the overlay and the map still remains the same.

The following code example hides an overlay.

overlay.setVisible(false);

Java

overlay.setVisible(false);

Kotlin

overlay.isVisible = false

Minimum and maximum zoom levels

Use minZoom and maxZoom to show an overlay at a specified zoom level. If the camera’s zoom level is out of the range between the minZoom and the maxZoom, the overlay is hidden.

The following code example sets an overlay to be shown only at the levels, between 12 and 16.

overlay.setMinZoom(12);
overlay.setMaxZoom(16);

Java

overlay.setMinZoom(12);
overlay.setMaxZoom(16);

Kotlin

overlay.minZoom = 12.0
overlay.maxZoom = 16.0

Event

All overlays can receive and consume click events. A click event listener for overlays should be added to each overlay, not the map.

Click event

Add Overlay.OnClickListener with the setOnClickListener() method to receive a click event for the overlay. When the overlay is clicked, the onClick() callback method is called with the clicked overlay object passed as a parameter.

The following code example adds a click event listener to display a toast message saying “Overlay is clicked” whenever an overlay is clicked.

overlay.setOnClickListener(o -> {
    Toast.makeText(context, "Overlay is clicked", Toast.LENGTH_SHORT).show();
    return true;
});

Java

overlay.setOnClickListener(o -> {
    Toast.makeText(context, "Overlay is clicked", Toast.LENGTH_SHORT).show();
    return true;
});

Kotlin

overlay.setOnClickListener { o ->
    Toast.makeText(context, "Overlay is clicked", Toast.LENGTH_SHORT).show()
    true
}

Only one click event listener can be added to an overlay. To remove the click event listener, set the onClickListener property to null.

The following code example removes the click event listener of an overlay.

overlay.setOnClickListener(null);

Java

overlay.setOnClickListener(null);

Kotlin

overlay.onClickListener = null

An event listener should be added to every overlay which needs to receive events. If an overlay has no event listener added, a click on the overlay is ignored. For example, if there are two overlays overlapped with each other and the one on top of the other does not have an event listener added, the other one receives a click event. If there is no overlapped overlay or an event listener is not added, it is considered that the map is clicked.

Propagate and consume events

An overlay click event can be propagated to the map. To propagate the event to the map, you should make Overlay.OnClickListener’s onClick() return false. After the onClick() returns false, the OnClickListener.onClick() of the map is called. On the contrary, if the onClick() returns true, it is considered that the symbol consumes the event and thus the map’s OnClickListener.onClick() is not called.

In the following code example, marker1 propagates click events and marker2 consumes them. Whereas both toast messages, “Marker is clicked” and “Map is clicked” are displayed when the marker1 is clicked, only the toast message, “Marker 2 is clicked” is displayed when the marker2 is clicked.

marker1.setOnClickListener(overlay -> {
    Toast.makeText(context, "Marker 1 is clicked", Toast.LENGTH_SHORT).show();
    // Propagates the event.
    return false;
});

marker2.setOnClickListener(overlay -> {
    Toast.makeText(context, "Marker 2 is clicked", Toast.LENGTH_SHORT).show();
    // Consumes the event.
    return true;
});

naverMap.setOnMapClickListener((point, coord) -> {
    Toast.makeText(context, "Map is clicked", Toast.LENGTH_SHORT).show();
});

Java

marker1.setOnClickListener(overlay -> {
    Toast.makeText(context, "Marker 1 is clicked", Toast.LENGTH_SHORT).show();
    // Propagates the event.
    return false;
});

marker2.setOnClickListener(overlay -> {
    Toast.makeText(context, "Marker 2 is clicked", Toast.LENGTH_SHORT).show();
    // Consumes the event.
    return true;
});

naverMap.setOnMapClickListener((point, coord) -> {
    Toast.makeText(context, "Map is clicked", Toast.LENGTH_SHORT).show();
});

Kotlin

marker1.setOnClickListener {
    Toast.makeText(context, "Marker 1 is clicked", Toast.LENGTH_SHORT).show()
    // Propagates the event.
    false
}

marker2.setOnClickListener {
    Toast.makeText(context, "Marker 2 is clicked", Toast.LENGTH_SHORT).show()
    // Consumes the event.
    true
}

naverMap.setOnMapClickListener {
    Toast.makeText(context, "Map is clicked", Toast.LENGTH_SHORT).show()
}

Overlays can propagate an event only to the map. That is, even if there are multiple overlays or symbols overlapped under the overlay that triggers an event, it is not propagated to those overlays or symbols.

Tag

The tag property specifies additional information for an overlay. This property is useful especially when combined with a click event listener. Since you can use the tag to check which overlay is clicked in the onClick() method, you can let multiple overlays share an event listener.

The following code example adds the tag property to marker1 and marker2 to share a click event listener.

Overlay.OnClickListener listener = overlay -> {
    Toast.makeText(context, "Marker " + overlay.getTag() + " is clicked",
        Toast.LENGTH_SHORT).show();
    return false;
};

marker1.setTag(1);
marker2.setTag(2);

marker1.setOnClickListener(listener);
marker2.setOnClickListener(listener);

Java

Overlay.OnClickListener listener = overlay -> {
    Toast.makeText(context, "Marker " + overlay.getTag() + " is clicked",
        Toast.LENGTH_SHORT).show();
    return false;
};

marker1.setTag(1);
marker2.setTag(2);

marker1.setOnClickListener(listener);
marker2.setOnClickListener(listener);

Kotlin

val listener = Overlay.OnClickListener { overlay ->
    Toast.makeText(context, "Marker ${overlay.tag} is clicked",
            Toast.LENGTH_SHORT).show()
    false
}

marker1.tag = 1
marker2.tag = 2

marker1.onClickListener = listener
marker2.onClickListener = listener

results matching ""

    No results matching ""