From 836e1c730acf3d2a208ba037497262e717f4a710 Mon Sep 17 00:00:00 2001 From: Masashi Katsumata Date: Sat, 7 Nov 2026 23:55:27 -0800 Subject: [PATCH] Map zIndex into the overlay bands Google Maps orders tile overlays, ground overlays, polygons, circles and polylines by one zIndex (markers always above). Ground overlays had no zIndex (0, same as polygons, order undefined), rasters used their own zIndex (0, so they covered polylines and ground images), and circles defaulted to the latitude-based zIndex (about -35 000 000 in Tokyo), which put them under everything, including rasters. Every kind now goes through OverlayStacking.flatZIndex(kind, zIndex): each band gets its own interval and zIndex orders within it. Marker tiles sit at the bottom of the marker band (above polylines). Stacking order (all providers, all platforms), bottom to top: raster layers < ground images < polygons < circles < polylines < markers. Needs android-sdk-core with OverlayStacking (fix/overlay-stacking-order). --- .../circle/GoogleMapCircleOverlayRenderer.kt | 10 ++++++++-- .../groundimage/GoogleMapGroundImageOverlayRenderer.kt | 4 ++++ .../polygon/GoogleMapPolygonOverlayRenderer.kt | 6 ++++-- .../polyline/GoogleMapPolylineOverlayRenderer.kt | 6 ++++-- .../raster/GoogleMapRasterLayerOverlayRenderer.kt | 10 +++++++--- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/mapconductor/googlemaps/circle/GoogleMapCircleOverlayRenderer.kt b/src/main/java/com/mapconductor/googlemaps/circle/GoogleMapCircleOverlayRenderer.kt index aef70b5..33f116f 100644 --- a/src/main/java/com/mapconductor/googlemaps/circle/GoogleMapCircleOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/googlemaps/circle/GoogleMapCircleOverlayRenderer.kt @@ -7,6 +7,8 @@ import com.mapconductor.core.calculateZIndex import com.mapconductor.core.circle.AbstractCircleOverlayRenderer import com.mapconductor.core.circle.CircleEntityInterface import com.mapconductor.core.circle.CircleState +import com.mapconductor.core.controller.OverlayKind +import com.mapconductor.core.controller.OverlayStacking import com.mapconductor.core.features.GeoPoint import com.mapconductor.core.geometry.circleToRing import com.mapconductor.core.geometry.closeRing @@ -37,7 +39,7 @@ class GoogleMapCircleOverlayRenderer( .fillColor(state.fillColor.toArgb()) .clickable(false) .geodesic(state.geodesic) - .zIndex((state.zIndex ?: calculateZIndex(state.center)).toFloat()) + .zIndex(OverlayStacking.flatZIndex(OverlayKind.Circle, state.zIndex ?: calculateZIndex(state.center))) holder.map.addPolygon(options).also { it.tag = state.id } @@ -82,7 +84,11 @@ class GoogleMapCircleOverlayRenderer( circle.fillColor = current.state.fillColor.toArgb() } if (finger.zIndex != prevFinger.zIndex) { - circle.zIndex = (current.state.zIndex ?: calculateZIndex(current.state.center)).toFloat() + circle.zIndex = + OverlayStacking.flatZIndex( + OverlayKind.Circle, + current.state.zIndex ?: calculateZIndex(current.state.center), + ) } circle } diff --git a/src/main/java/com/mapconductor/googlemaps/groundimage/GoogleMapGroundImageOverlayRenderer.kt b/src/main/java/com/mapconductor/googlemaps/groundimage/GoogleMapGroundImageOverlayRenderer.kt index 67c71cf..3c262d8 100644 --- a/src/main/java/com/mapconductor/googlemaps/groundimage/GoogleMapGroundImageOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/googlemaps/groundimage/GoogleMapGroundImageOverlayRenderer.kt @@ -3,6 +3,8 @@ package com.mapconductor.googlemaps.groundimage import androidx.core.graphics.drawable.toBitmap import com.google.android.gms.maps.model.BitmapDescriptorFactory import com.google.android.gms.maps.model.GroundOverlayOptions +import com.mapconductor.core.controller.OverlayKind +import com.mapconductor.core.controller.OverlayStacking import com.mapconductor.core.groundimage.AbstractGroundImageOverlayRenderer import com.mapconductor.core.groundimage.GroundImageEntityInterface import com.mapconductor.core.groundimage.GroundImageState @@ -28,6 +30,8 @@ class GoogleMapGroundImageOverlayRenderer( .image(image) .positionFromBounds(bounds) .transparency(1.0f - opacity) + // GroundImage の帯(タイルの上、ポリゴンの下)。Google は種類をまたいで zIndex で重ねる。 + .zIndex(OverlayStacking.flatZIndex(OverlayKind.GroundImage, 0)) holder.map.addGroundOverlay(options)?.also { it.tag = state.id } diff --git a/src/main/java/com/mapconductor/googlemaps/polygon/GoogleMapPolygonOverlayRenderer.kt b/src/main/java/com/mapconductor/googlemaps/polygon/GoogleMapPolygonOverlayRenderer.kt index c7bedf5..92cee63 100644 --- a/src/main/java/com/mapconductor/googlemaps/polygon/GoogleMapPolygonOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/googlemaps/polygon/GoogleMapPolygonOverlayRenderer.kt @@ -4,6 +4,8 @@ import androidx.compose.ui.graphics.toArgb import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.PolygonOptions import com.mapconductor.core.ResourceProvider +import com.mapconductor.core.controller.OverlayKind +import com.mapconductor.core.controller.OverlayStacking import com.mapconductor.core.features.GeoPoint import com.mapconductor.core.features.GeoPointInterface import com.mapconductor.core.geometry.densifyPolygonRing @@ -91,7 +93,7 @@ internal class GoogleMapPolygonOverlayRenderer( .strokeColor(resolved.strokeColor.toArgb()) .strokeWidth(ResourceProvider.dpToPx(resolved.strokeWidth).toFloat()) .fillColor(resolved.fillColor.toArgb()) - .zIndex(resolved.zIndex.toFloat()) + .zIndex(OverlayStacking.flatZIndex(OverlayKind.Polygon, resolved.zIndex)) .clickable(false) holder.map.addPolygon(options).also { it.tag = state.id @@ -126,7 +128,7 @@ internal class GoogleMapPolygonOverlayRenderer( polygon.fillColor = current.state.fillColor.toArgb() } if (finger.zIndex != prevFinger.zIndex) { - polygon.zIndex = current.state.zIndex.toFloat() + polygon.zIndex = OverlayStacking.flatZIndex(OverlayKind.Polygon, current.state.zIndex) } polygon } diff --git a/src/main/java/com/mapconductor/googlemaps/polyline/GoogleMapPolylineOverlayRenderer.kt b/src/main/java/com/mapconductor/googlemaps/polyline/GoogleMapPolylineOverlayRenderer.kt index 38c220f..43ad344 100644 --- a/src/main/java/com/mapconductor/googlemaps/polyline/GoogleMapPolylineOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/googlemaps/polyline/GoogleMapPolylineOverlayRenderer.kt @@ -5,6 +5,8 @@ import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.Polyline import com.google.android.gms.maps.model.PolylineOptions import com.mapconductor.core.ResourceProvider +import com.mapconductor.core.controller.OverlayKind +import com.mapconductor.core.controller.OverlayStacking import com.mapconductor.core.features.GeoPoint import com.mapconductor.core.features.GeoPointInterface import com.mapconductor.core.polyline.AbstractPolylineOverlayRenderer @@ -57,7 +59,7 @@ class GoogleMapPolylineOverlayRenderer( .color(state.strokeColor.toArgb()) .width(ResourceProvider.dpToPx(state.strokeWidth).toFloat()) .geodesic(state.geodesic) - .zIndex(state.zIndex.toFloat()) + .zIndex(OverlayStacking.flatZIndex(OverlayKind.Polyline, state.zIndex)) .clickable(false) holder.map.addPolyline(options).also { @@ -95,7 +97,7 @@ class GoogleMapPolylineOverlayRenderer( } if (finger.zIndex != prevFinger.zIndex) { - polyline.zIndex = current.state.zIndex.toFloat() + polyline.zIndex = OverlayStacking.flatZIndex(OverlayKind.Polyline, current.state.zIndex) } polyline diff --git a/src/main/java/com/mapconductor/googlemaps/raster/GoogleMapRasterLayerOverlayRenderer.kt b/src/main/java/com/mapconductor/googlemaps/raster/GoogleMapRasterLayerOverlayRenderer.kt index c561856..75c7c4b 100644 --- a/src/main/java/com/mapconductor/googlemaps/raster/GoogleMapRasterLayerOverlayRenderer.kt +++ b/src/main/java/com/mapconductor/googlemaps/raster/GoogleMapRasterLayerOverlayRenderer.kt @@ -5,6 +5,8 @@ import com.google.android.gms.maps.model.TileOverlay import com.google.android.gms.maps.model.TileOverlayOptions import com.google.android.gms.maps.model.TileProvider import com.google.android.gms.maps.model.TileProvider.NO_TILE +import com.mapconductor.core.controller.OverlayKind +import com.mapconductor.core.controller.OverlayStacking import com.mapconductor.core.raster.RasterLayerEntityInterface import com.mapconductor.core.raster.RasterLayerOverlayRendererInterface import com.mapconductor.core.raster.RasterLayerSource @@ -92,12 +94,14 @@ class GoogleMapRasterLayerOverlayRenderer( private fun isMarkerTileRaster(state: RasterLayerState): Boolean = state.id.startsWith(MARKER_TILE_RASTER_ID_PREFIX) + // Google は TileOverlay・GroundOverlay・Polygon・Circle・Polyline を 1 本の zIndex で重ねる + // (Marker は常にその上)。帯の順(OverlayStacking)に沿って値を割り当てる。 private fun resolveOverlayZIndex(state: RasterLayerState): Float = if (isMarkerTileRaster(state)) { - // Backward-compatible behavior: marker tiles stay above most overlays. - 999f + // マーカーのタイルはマーカーの帯(ポリラインより上)。 + OverlayStacking.flatZIndex(OverlayKind.Marker, Int.MIN_VALUE) } else { - state.zIndex.toFloat() + OverlayStacking.flatZIndex(OverlayKind.RasterLayer, state.zIndex) } override suspend fun onAdd(data: List): List =