diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 64c2afe6b..3cef29b74 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -46,4 +46,4 @@ jobs:
run: echo "MAPS_API_KEY=dummy" > secrets.properties
- name: Build modules
- run: ./gradlew build koverXmlReportDebug --stacktrace
+ run: ./gradlew build apiCheck koverXmlReportDebug --stacktrace
diff --git a/MIGRATION.md b/MIGRATION.md
index 1deaca3a6..d41565daa 100644
--- a/MIGRATION.md
+++ b/MIGRATION.md
@@ -109,3 +109,13 @@ geoJsonLayer.setOnFeatureClickListener { feature ->
}
```
Unlike the previous version, this SAM conversion is fully supported for native Kotlin callers without requiring anonymous object syntax (`object : Layer.OnFeatureClickListener { ... }`).
+
+---
+
+## 4. Data Renderer Model Style Updates (v6.0.0)
+
+In `v6.0.0`, the `com.google.maps.android.data.renderer.model.Style` hierarchy was expanded to support complete feature styling and heterogeneous multi-geometries:
+
+- **`PointStyle`**, **`LineStyle`**, and **`PolygonStyle`**: Added default-valued constructor properties (`title`, `snippet`, `draggable`, `flat`, `visible`, `infoWindowAnchorU`, and `infoWindowAnchorV` on `PointStyle`; `clickable` and `visible` on `LineStyle` and `PolygonStyle`). Source calls with named or positional arguments continue to compile unchanged, though recompilation is required against the updated data class `copy()` and constructor signatures.
+- **`CompositeStyle`**: Added `CompositeStyle(pointStyle, lineStyle, polygonStyle)` as a new subtype of the `sealed interface Style` to support heterogeneous `MultiGeometry` features. Exhaustive `when (style)` expressions over `Style` in consumer code should add a `is CompositeStyle ->` branch (or an `else ->` branch).
+
diff --git a/README.md b/README.md
index 5b22a01ea..7334026f4 100644
--- a/README.md
+++ b/README.md
@@ -30,8 +30,10 @@ upgrading from 4.x, see the [migration guide](MIGRATION.md).
- **Spherical geometry** — for example: computeDistance, computeHeading,
computeArea
- **Street View metadata** — checks if a Street View panorama exists at a given location
+- **Reactive Kotlin Extensions & Builders** — coroutine suspensions (`awaitMap()`), reactive `Flow` observers (`mapClickEvents()`), and option builder DSLs (`addMarker { ... }`) consolidated directly into `com.google.maps.android.*`.
-You can also find Kotlin extensions for this library in [Maps Android KTX][android-maps-ktx].
+> [!IMPORTANT]
+> **KTX Consolidation Notice (`v6.0.0+`)**: All Kotlin extensions (`maps-ktx` and `maps-utils-ktx` from `android-maps-ktx`) are now built directly into `android-maps-utils` under the canonical `com.google.maps.android.*` packages. Separate dependencies on `android-maps-ktx` or `maps-utils-ktx` are no longer needed and should be removed. Legacy calls to `com.google.maps.android.ktx.*` packages remain supported via `@Deprecated(level = DeprecationLevel.WARNING)` bridges that forward directly to canonical implementations.

@@ -46,9 +48,7 @@ You can also find Kotlin extensions for this library in [Maps Android KTX][andro
```kotlin
dependencies {
- // Utilities for Maps SDK for Android (requires Google Play Services)
- // You do not need to add a separate dependency for the Maps SDK for Android
- // since this library builds in the compatible version of the Maps SDK.
+ // Utilities and consolidated Kotlin Extensions for Maps SDK for Android
// The aggregator artifact transitively pulls in all submodules below.
implementation("com.google.maps.android:android-maps-utils:5.2.0") // x-release-please-version
}
@@ -167,6 +167,65 @@ Full guides for using the utilities are published in
+
+ Reactive Kotlin Extensions & Builders (Consolidated in v6.0.0)
+
+### Reactive Kotlin Extensions & Builders
+
+All Kotlin extensions formerly provided by `android-maps-ktx` (`maps-ktx` and `maps-utils-ktx`) are now integrated into `android-maps-utils` (`v6.0.0+`) under canonical packages (`com.google.maps.android.*`, `com.google.maps.android.clustering.*`, etc.).
+
+#### 1. Coroutine Suspensions (`awaitMapsSdkInitialized()`, `awaitMap()`, `awaitAnimateCamera()`)
+```kotlin
+import com.google.android.gms.maps.MapsInitializer
+import com.google.maps.android.awaitMapsSdkInitialized
+import com.google.maps.android.awaitMap
+import com.google.maps.android.awaitAnimateCamera
+
+// Suspend until Maps SDK is initialized
+val renderer: MapsInitializer.Renderer = context.awaitMapsSdkInitialized(MapsInitializer.Renderer.LATEST)
+
+// Suspend until GoogleMap is ready on MapView / MapFragment
+val googleMap: GoogleMap = mapView.awaitMap()
+
+// Suspend until camera animation completes
+googleMap.awaitAnimateCamera(CameraUpdateFactory.newLatLngZoom(sydney, 12f))
+```
+
+#### 2. Option Builders DSL (`addMarker`, `addPolyline`, `addPolygon`)
+```kotlin
+import com.google.maps.android.addMarker
+import com.google.maps.android.addCircle
+
+googleMap.addMarker {
+ position(LatLng(-33.852, 151.211))
+ title("Sydney Opera House")
+}
+
+googleMap.addCircle {
+ center(LatLng(-33.870, 151.200))
+ radius(500.0)
+ strokeWidth(2f)
+}
+```
+
+#### 3. Reactive `Flow` Observers (`mapClickEvents`, `cameraMoveEvents`)
+```kotlin
+import com.google.maps.android.mapClickEvents
+
+lifecycleScope.launch {
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
+ googleMap.mapClickEvents().collect { latLng ->
+ Log.d("MapClick", "Clicked: $latLng")
+ }
+ }
+}
+```
+
+#### Backward Compatibility & Deprecation
+Existing references to `com.google.maps.android.ktx.*` continue to work through `@Deprecated(level = DeprecationLevel.WARNING)` forwarding wrappers. You can safely migrate your code incrementally to `com.google.maps.android.*`.
+
+
+
Street View metadata utility
diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts
index 244d1adc9..0ae62850f 100644
--- a/build-logic/convention/build.gradle.kts
+++ b/build-logic/convention/build.gradle.kts
@@ -30,6 +30,7 @@ dependencies {
implementation(libs.dokka.gradle.plugin)
implementation(libs.kover.gradle.plugin)
implementation(libs.gradle.maven.publish.plugin)
+ implementation(libs.binary.compatibility.validator)
}
gradlePlugin {
diff --git a/build-logic/convention/src/main/kotlin/PublishingConventionPlugin.kt b/build-logic/convention/src/main/kotlin/PublishingConventionPlugin.kt
index 7b681a2be..ebf8318ea 100644
--- a/build-logic/convention/src/main/kotlin/PublishingConventionPlugin.kt
+++ b/build-logic/convention/src/main/kotlin/PublishingConventionPlugin.kt
@@ -18,8 +18,11 @@
import com.vanniktech.maven.publish.AndroidSingleVariantLibrary
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import kotlinx.kover.gradle.plugin.dsl.KoverProjectExtension
+import kotlinx.validation.KotlinApiBuildTask
+import kotlinx.validation.KotlinApiCompareTask
import org.gradle.api.Plugin
import org.gradle.api.Project
+import org.gradle.api.tasks.Copy
import org.gradle.kotlin.dsl.*
class PublishingConventionPlugin : Plugin {
@@ -28,6 +31,7 @@ class PublishingConventionPlugin : Plugin {
applyPlugins()
configureKover()
configureVanniktechPublishing()
+ configureBinaryCompatibilityValidator()
}
}
@@ -106,4 +110,65 @@ class PublishingConventionPlugin : Plugin {
}
}
}
+
+ private fun Project.configureBinaryCompatibilityValidator() {
+ val ignoredProjects = setOf("demo", "visual-testing", "lint-checks", "maps-utils")
+ if (name in ignoredProjects) return
+
+ val projectName = name
+ val apiFile = layout.projectDirectory.file("api/$projectName.api")
+ val buildApiFile = layout.buildDirectory.file("api/$projectName.api")
+
+ afterEvaluate {
+ val bundleTask = tasks.findByName("bundleLibCompileToJarRelease") ?: return@afterEvaluate
+ val classesJar = layout.buildDirectory.file(
+ "intermediates/compile_library_classes_jar/release/bundleLibCompileToJarRelease/classes.jar"
+ )
+
+ val apiBuild = tasks.register("apiBuild") {
+ group = "verification"
+ description = "Builds public API declaration for $projectName."
+ inputJar.set(classesJar)
+ outputApiFile.set(buildApiFile)
+ ignoredClasses.addAll(
+ "com.google.maps.android.R",
+ "com.google.maps.android.clustering.R",
+ "com.google.maps.android.data.R",
+ "com.google.maps.android.heatmaps.R",
+ "com.google.maps.android.ui.R",
+ "com.google.maps.android.BuildConfig",
+ "com.google.maps.android.clustering.BuildConfig",
+ "com.google.maps.android.data.BuildConfig",
+ "com.google.maps.android.heatmaps.BuildConfig",
+ "com.google.maps.android.ui.BuildConfig",
+ )
+ dependsOn(bundleTask)
+ }
+
+ val apiDump = tasks.register("apiDump") {
+ group = "verification"
+ description = "Syncs public API declarations of $projectName to the project api/ directory."
+ from(apiBuild.flatMap { it.outputApiFile })
+ into(apiFile.asFile.parentFile)
+ dependsOn(apiBuild)
+ }
+
+ val apiCheck = tasks.register("apiCheck") {
+ group = "verification"
+ description = "Checks public API declarations of $projectName against the committed api/$projectName.api."
+ projectApiFile.set(apiFile)
+ generatedApiFile.set(apiBuild.flatMap { it.outputApiFile })
+ dependsOn(apiBuild)
+ }
+
+ tasks.findByName("check")?.dependsOn(apiCheck)
+
+ rootProject.tasks.matching { it.name == "apiDump" }.configureEach {
+ dependsOn(apiDump)
+ }
+ rootProject.tasks.matching { it.name == "apiCheck" }.configureEach {
+ dependsOn(apiCheck)
+ }
+ }
+ }
}
diff --git a/build.gradle.kts b/build.gradle.kts
index 6f3aa73a3..9c9b07388 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -14,8 +14,26 @@
* limitations under the License.
*/
+import java.nio.file.Files
+import java.util.Properties
+
plugins {
id("com.vanniktech.maven.publish") version libs.versions.gradleMavenPublishPlugin.get() apply false
+ alias(libs.plugins.binary.compatibility.validator)
+}
+
+apiValidation {
+ ignoredProjects += listOf("demo", "visual-testing", "lint-checks", "maps-utils")
+}
+
+val apiDump = tasks.register("apiDump") {
+ group = "verification"
+ description = "Dumps public API declarations for all library modules."
+}
+
+val apiCheck = tasks.register("apiCheck") {
+ group = "verification"
+ description = "Checks that public API declarations match the committed .api files."
}
buildscript {
@@ -59,4 +77,27 @@ allprojects {
}
}
}
+
+ tasks.withType().configureEach {
+ val testHome = rootProject.layout.buildDirectory.dir("test-home").get().asFile
+ testHome.mkdirs()
+ val m2Link = File(testHome, ".m2")
+ if (!m2Link.exists()) {
+ val realM2 = File(System.getProperty("user.home"), ".m2")
+ if (realM2.exists()) {
+ try {
+ Files.createSymbolicLink(m2Link.toPath(), realM2.toPath())
+ } catch (_: Exception) {}
+ }
+ }
+ systemProperty("user.home", testHome.absolutePath)
+ val androidSdkDir = System.getenv("ANDROID_HOME")
+ ?: System.getenv("ANDROID_SDK_ROOT")
+ ?: rootProject.file("local.properties").takeIf { it.isFile }?.let { localPropsFile ->
+ Properties().apply { localPropsFile.inputStream().use(::load) }.getProperty("sdk.dir")
+ }
+ if (androidSdkDir != null) {
+ environment("ANDROID_HOME", androidSdkDir)
+ }
+ }
}
diff --git a/clustering/api/clustering.api b/clustering/api/clustering.api
new file mode 100644
index 000000000..a6a39422e
--- /dev/null
+++ b/clustering/api/clustering.api
@@ -0,0 +1,449 @@
+public abstract interface class com/google/maps/android/clustering/Cluster {
+ public abstract fun getItems ()Ljava/util/Collection;
+ public abstract fun getPosition ()Lcom/google/android/gms/maps/model/LatLng;
+ public abstract fun getSize ()I
+}
+
+public abstract interface class com/google/maps/android/clustering/ClusterItem {
+ public abstract fun getPosition ()Lcom/google/android/gms/maps/model/LatLng;
+ public abstract fun getSnippet ()Ljava/lang/String;
+ public abstract fun getTitle ()Ljava/lang/String;
+ public abstract fun getZIndex ()Ljava/lang/Float;
+}
+
+public class com/google/maps/android/clustering/ClusterManager : com/google/android/gms/maps/GoogleMap$OnCameraIdleListener, com/google/android/gms/maps/GoogleMap$OnInfoWindowClickListener, com/google/android/gms/maps/GoogleMap$OnMarkerClickListener {
+ public fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;)V
+ public fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/collections/MarkerManager;)V
+ public synthetic fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/collections/MarkerManager;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public fun addItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun addItems (Ljava/util/Collection;)Z
+ public fun clearItems ()V
+ public fun cluster ()V
+ public fun diff (Ljava/util/Collection;Ljava/util/Collection;Ljava/util/Collection;)V
+ public fun getAlgorithm ()Lcom/google/maps/android/clustering/algo/Algorithm;
+ public final fun getClusterMarkerCollection ()Lcom/google/maps/android/collections/MarkerManager$Collection;
+ public final fun getMarkerCollection ()Lcom/google/maps/android/collections/MarkerManager$Collection;
+ public final fun getMarkerManager ()Lcom/google/maps/android/collections/MarkerManager;
+ public fun getRenderer ()Lcom/google/maps/android/clustering/view/ClusterRenderer;
+ public fun onCameraIdle ()V
+ public fun onInfoWindowClick (Lcom/google/android/gms/maps/model/Marker;)V
+ public fun onMarkerClick (Lcom/google/android/gms/maps/model/Marker;)Z
+ public fun removeItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun removeItems (Ljava/util/Collection;)Z
+ public fun setAlgorithm (Lcom/google/maps/android/clustering/algo/Algorithm;)V
+ public fun setAlgorithm (Lcom/google/maps/android/clustering/algo/ScreenBasedAlgorithm;)V
+ public fun setAnimation (Z)V
+ public fun setOnClusterClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterClickListener;)V
+ public fun setOnClusterInfoWindowClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowClickListener;)V
+ public fun setOnClusterInfoWindowLongClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowLongClickListener;)V
+ public fun setOnClusterItemClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemClickListener;)V
+ public fun setOnClusterItemInfoWindowClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowClickListener;)V
+ public fun setOnClusterItemInfoWindowLongClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowLongClickListener;)V
+ public fun setRenderer (Lcom/google/maps/android/clustering/view/ClusterRenderer;)V
+ public fun updateItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+}
+
+public abstract interface class com/google/maps/android/clustering/ClusterManager$OnClusterClickListener {
+ public abstract fun onClusterClick (Lcom/google/maps/android/clustering/Cluster;)Z
+}
+
+public abstract interface class com/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowClickListener {
+ public abstract fun onClusterInfoWindowClick (Lcom/google/maps/android/clustering/Cluster;)V
+}
+
+public abstract interface class com/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowLongClickListener {
+ public abstract fun onClusterInfoWindowLongClick (Lcom/google/maps/android/clustering/Cluster;)V
+}
+
+public abstract interface class com/google/maps/android/clustering/ClusterManager$OnClusterItemClickListener {
+ public abstract fun onClusterItemClick (Lcom/google/maps/android/clustering/ClusterItem;)Z
+}
+
+public abstract interface class com/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowClickListener {
+ public abstract fun onClusterItemInfoWindowClick (Lcom/google/maps/android/clustering/ClusterItem;)V
+}
+
+public abstract interface class com/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowLongClickListener {
+ public abstract fun onClusterItemInfoWindowLongClick (Lcom/google/maps/android/clustering/ClusterItem;)V
+}
+
+public final class com/google/maps/android/clustering/ClusterManagerFlowsKt {
+ public static final fun clusterClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+ public static final fun clusterInfoWindowClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+ public static final fun clusterInfoWindowLongClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+ public static final fun clusterItemClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+ public static final fun clusterItemInfoWindowClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+ public static final fun clusterItemInfoWindowLongClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+}
+
+public abstract class com/google/maps/android/clustering/algo/AbstractAlgorithm : com/google/maps/android/clustering/algo/Algorithm {
+ public fun ()V
+ public fun lock ()V
+ public fun unlock ()V
+}
+
+public abstract interface class com/google/maps/android/clustering/algo/Algorithm {
+ public abstract fun addItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public abstract fun addItems (Ljava/util/Collection;)Z
+ public abstract fun clearItems ()V
+ public abstract fun getClusters (F)Ljava/util/Set;
+ public abstract fun getItems ()Ljava/util/Collection;
+ public abstract fun getMaxDistanceBetweenClusteredItems ()I
+ public abstract fun lock ()V
+ public abstract fun removeItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public abstract fun removeItems (Ljava/util/Collection;)Z
+ public abstract fun setMaxDistanceBetweenClusteredItems (I)V
+ public abstract fun unlock ()V
+ public abstract fun updateItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+}
+
+public class com/google/maps/android/clustering/algo/CentroidNonHierarchicalDistanceBasedAlgorithm : com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm {
+ public fun ()V
+ protected final fun computeCentroid (Ljava/util/Collection;)Lcom/google/android/gms/maps/model/LatLng;
+ public fun getClusters (F)Ljava/util/Set;
+}
+
+public class com/google/maps/android/clustering/algo/ContinuousZoomEuclideanCentroidAlgorithm : com/google/maps/android/clustering/algo/CentroidNonHierarchicalDistanceBasedAlgorithm {
+ public fun ()V
+ public fun getClusters (F)Ljava/util/Set;
+}
+
+public class com/google/maps/android/clustering/algo/GridBasedAlgorithm : com/google/maps/android/clustering/algo/AbstractAlgorithm {
+ public static final field Companion Lcom/google/maps/android/clustering/algo/GridBasedAlgorithm$Companion;
+ public fun ()V
+ public fun addItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun addItems (Ljava/util/Collection;)Z
+ public fun clearItems ()V
+ public fun getClusters (F)Ljava/util/Set;
+ public fun getItems ()Ljava/util/Collection;
+ public fun getMaxDistanceBetweenClusteredItems ()I
+ public fun removeItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun removeItems (Ljava/util/Collection;)Z
+ public fun setMaxDistanceBetweenClusteredItems (I)V
+ public fun updateItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+}
+
+public final class com/google/maps/android/clustering/algo/GridBasedAlgorithm$Companion {
+}
+
+public class com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm : com/google/maps/android/clustering/algo/AbstractAlgorithm {
+ public static final field Companion Lcom/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm$Companion;
+ protected final field mItems Ljava/util/Collection;
+ protected final field mQuadTree Lcom/google/maps/android/quadtree/PointQuadTree;
+ public fun ()V
+ public fun addItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun addItems (Ljava/util/Collection;)Z
+ public fun clearItems ()V
+ protected final fun createBoundsFromSpan (Lcom/google/maps/android/geometry/Point;D)Lcom/google/maps/android/geometry/Bounds;
+ protected final fun distanceSquared (Lcom/google/maps/android/geometry/Point;Lcom/google/maps/android/geometry/Point;)D
+ protected fun getClusteringItems (Lcom/google/maps/android/quadtree/PointQuadTree;F)Ljava/util/Collection;
+ public fun getClusters (F)Ljava/util/Set;
+ public fun getItems ()Ljava/util/Collection;
+ protected final fun getMItemMap ()Ljava/util/Map;
+ public fun getMaxDistanceBetweenClusteredItems ()I
+ public fun removeItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun removeItems (Ljava/util/Collection;)Z
+ public fun setMaxDistanceBetweenClusteredItems (I)V
+ public fun updateItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+}
+
+public final class com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm$Companion {
+}
+
+protected final class com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm$QuadItem : com/google/maps/android/clustering/Cluster, com/google/maps/android/quadtree/PointQuadTree$Item {
+ public final field mClusterItem Lcom/google/maps/android/clustering/ClusterItem;
+ public fun (Lcom/google/maps/android/clustering/ClusterItem;)V
+ public fun equals (Ljava/lang/Object;)Z
+ public fun getItems ()Ljava/util/Collection;
+ public fun getPoint ()Lcom/google/maps/android/geometry/Point;
+ public fun getPosition ()Lcom/google/android/gms/maps/model/LatLng;
+ public fun getSize ()I
+ public fun hashCode ()I
+}
+
+public class com/google/maps/android/clustering/algo/NonHierarchicalViewBasedAlgorithm : com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm, com/google/maps/android/clustering/algo/ScreenBasedAlgorithm {
+ public static final field Companion Lcom/google/maps/android/clustering/algo/NonHierarchicalViewBasedAlgorithm$Companion;
+ public fun (II)V
+ protected fun getClusteringItems (Lcom/google/maps/android/quadtree/PointQuadTree;F)Ljava/util/Collection;
+ public fun onCameraChange (Lcom/google/android/gms/maps/model/CameraPosition;)V
+ public fun shouldReclusterOnMapMovement ()Z
+ public final fun updateViewSize (II)V
+}
+
+public final class com/google/maps/android/clustering/algo/NonHierarchicalViewBasedAlgorithm$Companion {
+}
+
+public class com/google/maps/android/clustering/algo/PreCachingAlgorithmDecorator : com/google/maps/android/clustering/algo/AbstractAlgorithm {
+ public fun (Lcom/google/maps/android/clustering/algo/Algorithm;)V
+ public fun addItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun addItems (Ljava/util/Collection;)Z
+ public fun clearItems ()V
+ public fun getClusters (F)Ljava/util/Set;
+ public fun getItems ()Ljava/util/Collection;
+ public fun getMaxDistanceBetweenClusteredItems ()I
+ public fun removeItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun removeItems (Ljava/util/Collection;)Z
+ public fun setMaxDistanceBetweenClusteredItems (I)V
+ public fun updateItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+}
+
+public abstract interface class com/google/maps/android/clustering/algo/ScreenBasedAlgorithm : com/google/maps/android/clustering/algo/Algorithm {
+ public abstract fun onCameraChange (Lcom/google/android/gms/maps/model/CameraPosition;)V
+ public abstract fun shouldReclusterOnMapMovement ()Z
+}
+
+public class com/google/maps/android/clustering/algo/ScreenBasedAlgorithmAdapter : com/google/maps/android/clustering/algo/AbstractAlgorithm, com/google/maps/android/clustering/algo/ScreenBasedAlgorithm {
+ public fun (Lcom/google/maps/android/clustering/algo/Algorithm;)V
+ public fun addItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun addItems (Ljava/util/Collection;)Z
+ public fun clearItems ()V
+ public fun getClusters (F)Ljava/util/Set;
+ public fun getItems ()Ljava/util/Collection;
+ public fun getMaxDistanceBetweenClusteredItems ()I
+ public fun onCameraChange (Lcom/google/android/gms/maps/model/CameraPosition;)V
+ public fun removeItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun removeItems (Ljava/util/Collection;)Z
+ public fun setMaxDistanceBetweenClusteredItems (I)V
+ public fun shouldReclusterOnMapMovement ()Z
+ public fun updateItem (Lcom/google/maps/android/clustering/ClusterItem;)Z
+}
+
+public class com/google/maps/android/clustering/algo/StaticCluster : com/google/maps/android/clustering/Cluster {
+ public fun (Lcom/google/android/gms/maps/model/LatLng;)V
+ public final fun add (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun equals (Ljava/lang/Object;)Z
+ public fun getItems ()Ljava/util/Collection;
+ public fun getPosition ()Lcom/google/android/gms/maps/model/LatLng;
+ public fun getSize ()I
+ public fun hashCode ()I
+ public final fun remove (Lcom/google/maps/android/clustering/ClusterItem;)Z
+ public fun toString ()Ljava/lang/String;
+}
+
+public abstract interface class com/google/maps/android/clustering/view/ClusterRenderer {
+ public abstract fun getClusterTextAppearance (I)I
+ public abstract fun getColor (I)I
+ public abstract fun onAdd ()V
+ public abstract fun onClustersChanged (Ljava/util/Set;)V
+ public abstract fun onRemove ()V
+ public abstract fun setAnimation (Z)V
+ public abstract fun setAnimationDuration (J)V
+ public abstract fun setOnClusterClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterClickListener;)V
+ public abstract fun setOnClusterInfoWindowClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowClickListener;)V
+ public abstract fun setOnClusterInfoWindowLongClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowLongClickListener;)V
+ public abstract fun setOnClusterItemClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemClickListener;)V
+ public abstract fun setOnClusterItemInfoWindowClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowClickListener;)V
+ public abstract fun setOnClusterItemInfoWindowLongClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowLongClickListener;)V
+}
+
+public class com/google/maps/android/clustering/view/ClusterRendererMultipleItems : com/google/maps/android/clustering/view/ClusterRenderer {
+ public static final field Companion Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$Companion;
+ public fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/clustering/ClusterManager;)V
+ public fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/clustering/ClusterManager;Ljava/util/concurrent/Executor;)V
+ public synthetic fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/clustering/ClusterManager;Ljava/util/concurrent/Executor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ protected final fun getBucket (Lcom/google/maps/android/clustering/Cluster;)I
+ public fun getCluster (Lcom/google/android/gms/maps/model/Marker;)Lcom/google/maps/android/clustering/Cluster;
+ public fun getClusterItem (Lcom/google/android/gms/maps/model/Marker;)Lcom/google/maps/android/clustering/ClusterItem;
+ protected final fun getClusterText (I)Ljava/lang/String;
+ public fun getClusterTextAppearance (I)I
+ public fun getColor (I)I
+ protected final fun getDescriptorForCluster (Lcom/google/maps/android/clustering/Cluster;)Lcom/google/android/gms/maps/model/BitmapDescriptor;
+ public fun getMarker (Lcom/google/maps/android/clustering/Cluster;)Lcom/google/android/gms/maps/model/Marker;
+ public fun getMarker (Lcom/google/maps/android/clustering/ClusterItem;)Lcom/google/android/gms/maps/model/Marker;
+ public fun getMinClusterSize ()I
+ public fun onAdd ()V
+ protected fun onBeforeClusterItemRendered (Lcom/google/maps/android/clustering/ClusterItem;Lcom/google/android/gms/maps/model/MarkerOptions;)V
+ protected fun onBeforeClusterRendered (Lcom/google/maps/android/clustering/Cluster;Lcom/google/android/gms/maps/model/MarkerOptions;)V
+ protected final fun onClusterItemRendered (Lcom/google/maps/android/clustering/ClusterItem;Lcom/google/android/gms/maps/model/Marker;)V
+ protected fun onClusterItemUpdated (Lcom/google/maps/android/clustering/ClusterItem;Lcom/google/android/gms/maps/model/Marker;)V
+ protected final fun onClusterRendered (Lcom/google/maps/android/clustering/Cluster;Lcom/google/android/gms/maps/model/Marker;)V
+ protected fun onClusterUpdated (Lcom/google/maps/android/clustering/Cluster;Lcom/google/android/gms/maps/model/Marker;)V
+ public fun onClustersChanged (Ljava/util/Set;)V
+ public fun onRemove ()V
+ public fun setAnimation (Z)V
+ public fun setAnimationDuration (J)V
+ public final fun setAnimationInterpolator (Landroid/animation/TimeInterpolator;)V
+ public final fun setAnimationType (Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;)V
+ public final fun setLoggingEnabled (Z)V
+ public fun setMinClusterSize (I)V
+ public fun setOnClusterClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterClickListener;)V
+ public fun setOnClusterInfoWindowClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowClickListener;)V
+ public fun setOnClusterInfoWindowLongClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowLongClickListener;)V
+ public fun setOnClusterItemClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemClickListener;)V
+ public fun setOnClusterItemInfoWindowClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowClickListener;)V
+ public fun setOnClusterItemInfoWindowLongClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowLongClickListener;)V
+ protected fun shouldRenderAsCluster (Lcom/google/maps/android/clustering/Cluster;)Z
+ public final fun stopAnimation ()V
+}
+
+public final class com/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType : java/lang/Enum {
+ public static final field ACCELERATE Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;
+ public static final field BOUNCE Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;
+ public static final field DECELERATE Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;
+ public static final field EASE_IN Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;
+ public static final field EASE_IN_OUT Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;
+ public static final field EASE_OUT Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;
+ public static final field FAST_OUT_SLOW_IN Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;
+ public static final field LINEAR Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;
+ public static fun getEntries ()Lkotlin/enums/EnumEntries;
+ public static fun valueOf (Ljava/lang/String;)Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;
+ public static fun values ()[Lcom/google/maps/android/clustering/view/ClusterRendererMultipleItems$AnimationType;
+}
+
+public final class com/google/maps/android/clustering/view/ClusterRendererMultipleItems$Companion {
+}
+
+public class com/google/maps/android/clustering/view/DefaultAdvancedMarkersClusterRenderer : com/google/maps/android/clustering/view/ClusterRenderer {
+ public static final field Companion Lcom/google/maps/android/clustering/view/DefaultAdvancedMarkersClusterRenderer$Companion;
+ public fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/clustering/ClusterManager;)V
+ public fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/clustering/ClusterManager;Ljava/util/concurrent/Executor;)V
+ public synthetic fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/clustering/ClusterManager;Ljava/util/concurrent/Executor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ protected fun getBucket (Lcom/google/maps/android/clustering/Cluster;)I
+ public fun getCluster (Lcom/google/android/gms/maps/model/Marker;)Lcom/google/maps/android/clustering/Cluster;
+ public fun getClusterItem (Lcom/google/android/gms/maps/model/Marker;)Lcom/google/maps/android/clustering/ClusterItem;
+ protected fun getClusterText (I)Ljava/lang/String;
+ public fun getClusterTextAppearance (I)I
+ public fun getColor (I)I
+ protected fun getDescriptorForCluster (Lcom/google/maps/android/clustering/Cluster;)Lcom/google/android/gms/maps/model/BitmapDescriptor;
+ public fun getMarker (Lcom/google/maps/android/clustering/Cluster;)Lcom/google/android/gms/maps/model/Marker;
+ public fun getMarker (Lcom/google/maps/android/clustering/ClusterItem;)Lcom/google/android/gms/maps/model/Marker;
+ public fun getMinClusterSize ()I
+ public fun onAdd ()V
+ protected fun onBeforeClusterItemRendered (Lcom/google/maps/android/clustering/ClusterItem;Lcom/google/android/gms/maps/model/AdvancedMarkerOptions;)V
+ protected fun onBeforeClusterRendered (Lcom/google/maps/android/clustering/Cluster;Lcom/google/android/gms/maps/model/AdvancedMarkerOptions;)V
+ protected fun onClusterItemRendered (Lcom/google/maps/android/clustering/ClusterItem;Lcom/google/android/gms/maps/model/Marker;)V
+ protected fun onClusterItemUpdated (Lcom/google/maps/android/clustering/ClusterItem;Lcom/google/android/gms/maps/model/Marker;)V
+ protected fun onClusterRendered (Lcom/google/maps/android/clustering/Cluster;Lcom/google/android/gms/maps/model/Marker;)V
+ protected fun onClusterUpdated (Lcom/google/maps/android/clustering/Cluster;Lcom/google/android/gms/maps/model/AdvancedMarker;)V
+ public fun onClustersChanged (Ljava/util/Set;)V
+ public fun onRemove ()V
+ public fun setAnimation (Z)V
+ public fun setAnimationDuration (J)V
+ public fun setMinClusterSize (I)V
+ public fun setOnClusterClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterClickListener;)V
+ public fun setOnClusterInfoWindowClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowClickListener;)V
+ public fun setOnClusterInfoWindowLongClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowLongClickListener;)V
+ public fun setOnClusterItemClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemClickListener;)V
+ public fun setOnClusterItemInfoWindowClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowClickListener;)V
+ public fun setOnClusterItemInfoWindowLongClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowLongClickListener;)V
+ protected fun shouldRender (Ljava/util/Set;Ljava/util/Set;)Z
+ protected fun shouldRenderAsCluster (Lcom/google/maps/android/clustering/Cluster;)Z
+}
+
+public final class com/google/maps/android/clustering/view/DefaultAdvancedMarkersClusterRenderer$Companion {
+}
+
+public class com/google/maps/android/clustering/view/DefaultClusterRenderer : com/google/maps/android/clustering/view/ClusterRenderer {
+ public static final field Companion Lcom/google/maps/android/clustering/view/DefaultClusterRenderer$Companion;
+ public fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/clustering/ClusterManager;)V
+ public fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/clustering/ClusterManager;Ljava/util/concurrent/Executor;)V
+ public synthetic fun (Landroid/content/Context;Lcom/google/android/gms/maps/GoogleMap;Lcom/google/maps/android/clustering/ClusterManager;Ljava/util/concurrent/Executor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ protected fun getBucket (Lcom/google/maps/android/clustering/Cluster;)I
+ public fun getCluster (Lcom/google/android/gms/maps/model/Marker;)Lcom/google/maps/android/clustering/Cluster;
+ public fun getClusterItem (Lcom/google/android/gms/maps/model/Marker;)Lcom/google/maps/android/clustering/ClusterItem;
+ protected fun getClusterText (I)Ljava/lang/String;
+ public fun getClusterTextAppearance (I)I
+ public fun getColor (I)I
+ protected fun getDescriptorForCluster (Lcom/google/maps/android/clustering/Cluster;)Lcom/google/android/gms/maps/model/BitmapDescriptor;
+ public fun getMarker (Lcom/google/maps/android/clustering/Cluster;)Lcom/google/android/gms/maps/model/Marker;
+ public fun getMarker (Lcom/google/maps/android/clustering/ClusterItem;)Lcom/google/android/gms/maps/model/Marker;
+ public fun getMinClusterSize ()I
+ public fun onAdd ()V
+ protected fun onBeforeClusterItemRendered (Lcom/google/maps/android/clustering/ClusterItem;Lcom/google/android/gms/maps/model/MarkerOptions;)V
+ protected fun onBeforeClusterRendered (Lcom/google/maps/android/clustering/Cluster;Lcom/google/android/gms/maps/model/MarkerOptions;)V
+ protected fun onClusterItemRendered (Lcom/google/maps/android/clustering/ClusterItem;Lcom/google/android/gms/maps/model/Marker;)V
+ protected fun onClusterItemUpdated (Lcom/google/maps/android/clustering/ClusterItem;Lcom/google/android/gms/maps/model/Marker;)V
+ protected fun onClusterRendered (Lcom/google/maps/android/clustering/Cluster;Lcom/google/android/gms/maps/model/Marker;)V
+ protected fun onClusterUpdated (Lcom/google/maps/android/clustering/Cluster;Lcom/google/android/gms/maps/model/Marker;)V
+ public fun onClustersChanged (Ljava/util/Set;)V
+ public fun onRemove ()V
+ public fun setAnimation (Z)V
+ public fun setAnimationDuration (J)V
+ public fun setMinClusterSize (I)V
+ public fun setOnClusterClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterClickListener;)V
+ public fun setOnClusterInfoWindowClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowClickListener;)V
+ public fun setOnClusterInfoWindowLongClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterInfoWindowLongClickListener;)V
+ public fun setOnClusterItemClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemClickListener;)V
+ public fun setOnClusterItemInfoWindowClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowClickListener;)V
+ public fun setOnClusterItemInfoWindowLongClickListener (Lcom/google/maps/android/clustering/ClusterManager$OnClusterItemInfoWindowLongClickListener;)V
+ protected fun shouldRender (Ljava/util/Set;Ljava/util/Set;)Z
+ protected fun shouldRenderAsCluster (Lcom/google/maps/android/clustering/Cluster;)Z
+}
+
+public final class com/google/maps/android/clustering/view/DefaultClusterRenderer$Companion {
+}
+
+public final class com/google/maps/android/geometry/Bounds {
+ public final field maxX D
+ public final field maxY D
+ public final field midX D
+ public final field midY D
+ public final field minX D
+ public final field minY D
+ public fun (DDDD)V
+ public final fun contains (DD)Z
+ public final fun contains (Lcom/google/maps/android/geometry/Bounds;)Z
+ public final fun contains (Lcom/google/maps/android/geometry/Point;)Z
+ public final fun intersects (DDDD)Z
+ public final fun intersects (Lcom/google/maps/android/geometry/Bounds;)Z
+}
+
+public class com/google/maps/android/geometry/Point {
+ public final field x D
+ public final field y D
+ public fun (DD)V
+ public final fun copy (DD)Lcom/google/maps/android/geometry/Point;
+ public static synthetic fun copy$default (Lcom/google/maps/android/geometry/Point;DDILjava/lang/Object;)Lcom/google/maps/android/geometry/Point;
+ public fun equals (Ljava/lang/Object;)Z
+ public fun hashCode ()I
+ public fun toString ()Ljava/lang/String;
+}
+
+public final class com/google/maps/android/geometry/PointExtensionsKt {
+ public static final fun component1 (Lcom/google/maps/android/geometry/Point;)D
+ public static final fun component2 (Lcom/google/maps/android/geometry/Point;)D
+}
+
+public final class com/google/maps/android/ktx/utils/clustering/ClusterManagerKt {
+ public static final fun clusterClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+ public static final fun clusterInfoWindowClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+ public static final fun clusterInfoWindowLongClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+ public static final fun clusterItemClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+ public static final fun clusterItemInfoWindowClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+ public static final fun clusterItemInfoWindowLongClickEvents (Lcom/google/maps/android/clustering/ClusterManager;)Lkotlinx/coroutines/flow/Flow;
+}
+
+public final class com/google/maps/android/ktx/utils/geometry/PointKt {
+ public static final fun component1 (Lcom/google/maps/android/geometry/Point;)D
+ public static final fun component2 (Lcom/google/maps/android/geometry/Point;)D
+}
+
+public final class com/google/maps/android/projection/Point : com/google/maps/android/geometry/Point {
+ public fun (DD)V
+}
+
+public final class com/google/maps/android/projection/SphericalMercatorProjection {
+ public fun (D)V
+ public final fun toLatLng (Lcom/google/maps/android/geometry/Point;)Lcom/google/android/gms/maps/model/LatLng;
+ public final fun toPoint (Lcom/google/android/gms/maps/model/LatLng;)Lcom/google/maps/android/geometry/Point;
+}
+
+public final class com/google/maps/android/quadtree/PointQuadTree {
+ public static final field Companion Lcom/google/maps/android/quadtree/PointQuadTree$Companion;
+ public fun (DDDD)V
+ public fun (Lcom/google/maps/android/geometry/Bounds;)V
+ public fun (Lcom/google/maps/android/geometry/Bounds;I)V
+ public synthetic fun (Lcom/google/maps/android/geometry/Bounds;IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public final fun add (Lcom/google/maps/android/quadtree/PointQuadTree$Item;)V
+ public final fun clear ()V
+ public final fun remove (Lcom/google/maps/android/quadtree/PointQuadTree$Item;)Z
+ public final fun search (Lcom/google/maps/android/geometry/Bounds;)Ljava/util/Collection;
+}
+
+public final class com/google/maps/android/quadtree/PointQuadTree$Companion {
+}
+
+public abstract interface class com/google/maps/android/quadtree/PointQuadTree$Item {
+ public abstract fun getPoint ()Lcom/google/maps/android/geometry/Point;
+}
+
diff --git a/clustering/build.gradle.kts b/clustering/build.gradle.kts
index a17bcc2f1..c0a30741b 100644
--- a/clustering/build.gradle.kts
+++ b/clustering/build.gradle.kts
@@ -48,6 +48,7 @@ android {
}
kotlin {
+ explicitApi()
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
}
@@ -67,6 +68,7 @@ dependencies {
implementation(project(":library"))
implementation(project(":data"))
api(libs.play.services.maps)
+ api(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.appcompat)
implementation(libs.core.ktx)
@@ -78,11 +80,8 @@ dependencies {
testImplementation(libs.kotlin.test)
testImplementation(libs.truth)
implementation(libs.kotlin.stdlib.jdk8)
-
- testImplementation(libs.mockk)
testImplementation(libs.kotlinx.coroutines.test)
- testImplementation(libs.robolectric)
- testImplementation(libs.mockito.core)
+ testImplementation(libs.mockito.kotlin)
}
tasks.register("instrumentTest") {
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/Cluster.kt b/clustering/src/main/java/com/google/maps/android/clustering/Cluster.kt
index e239cec37..244292ae3 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/Cluster.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/Cluster.kt
@@ -20,10 +20,10 @@ import com.google.android.gms.maps.model.LatLng
/**
* A collection of ClusterItems that are nearby each other.
*/
-interface Cluster {
- val position: LatLng
+public interface Cluster {
+ public val position: LatLng
- val items: Collection
+ public val items: Collection
- val size: Int
+ public val size: Int
}
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/ClusterItem.kt b/clustering/src/main/java/com/google/maps/android/clustering/ClusterItem.kt
index e3409f893..ae2fc307a 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/ClusterItem.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/ClusterItem.kt
@@ -20,24 +20,24 @@ import com.google.android.gms.maps.model.LatLng
/**
* ClusterItem represents a marker on the map.
*/
-interface ClusterItem {
+public interface ClusterItem {
/**
* The position of this marker. This must always return the same value.
*/
- val position: LatLng
+ public val position: LatLng
/**
* The title of this marker.
*/
- val title: String?
+ public val title: String?
/**
* The description of this marker.
*/
- val snippet: String?
+ public val snippet: String?
/**
* The z-index of this marker.
*/
- val zIndex: Float?
+ public val zIndex: Float?
}
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/ClusterManager.kt b/clustering/src/main/java/com/google/maps/android/clustering/ClusterManager.kt
index 38f7c6e72..3071daed7 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/ClusterManager.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/ClusterManager.kt
@@ -46,17 +46,17 @@ import kotlin.jvm.JvmSuppressWildcards
* - [com.google.android.gms.maps.GoogleMap.OnCameraIdleListener]
* - [com.google.android.gms.maps.GoogleMap.OnMarkerClickListener]
*/
-open class ClusterManager
+public open class ClusterManager
@JvmOverloads
- constructor(
+ public constructor(
context: Context,
private val mMap: GoogleMap,
- val markerManager: MarkerManager = MarkerManager(mMap),
+ public val markerManager: MarkerManager = MarkerManager(mMap),
) : OnCameraIdleListener,
OnMarkerClickListener,
OnInfoWindowClickListener {
- val markerCollection: MarkerManager.Collection = markerManager.newCollection()
- val clusterMarkerCollection: MarkerManager.Collection = markerManager.newCollection()
+ public val markerCollection: MarkerManager.Collection = markerManager.newCollection()
+ public val clusterMarkerCollection: MarkerManager.Collection = markerManager.newCollection()
private var mAlgorithm: ScreenBasedAlgorithm
private var mRenderer: ClusterRenderer
@@ -85,7 +85,7 @@ open class ClusterManager
mRenderer.onAdd()
}
- open var renderer: ClusterRenderer
+ public open var renderer: ClusterRenderer
get() = mRenderer
set(value) {
mRenderer.setOnClusterClickListener(null)
@@ -104,7 +104,7 @@ open class ClusterManager
cluster()
}
- open var algorithm: Algorithm
+ public open var algorithm: Algorithm
get() = mAlgorithm
set(value) {
if (value is ScreenBasedAlgorithm<*>) {
@@ -114,7 +114,7 @@ open class ClusterManager
}
}
- open fun setAlgorithm(algorithm: ScreenBasedAlgorithm) {
+ public open fun setAlgorithm(algorithm: ScreenBasedAlgorithm) {
algorithm.lock()
try {
val oldAlgorithm = this.algorithm
@@ -137,7 +137,7 @@ open class ClusterManager
cluster()
}
- open fun setAnimation(animate: Boolean) {
+ public open fun setAnimation(animate: Boolean) {
mRenderer.setAnimation(animate)
}
@@ -145,7 +145,7 @@ open class ClusterManager
* Removes all items from the cluster manager. After calling this method you must invoke
* [.cluster] for the map to be cleared.
*/
- open fun clearItems() {
+ public open fun clearItems() {
val algorithm = algorithm
algorithm.lock()
try {
@@ -161,7 +161,7 @@ open class ClusterManager
* @param items items to add to clusters
* @return true if the cluster manager contents changed as a result of the call
*/
- open fun addItems(items: Collection<@JvmSuppressWildcards T>?): Boolean {
+ public open fun addItems(items: Collection<@JvmSuppressWildcards T>?): Boolean {
val algorithm = algorithm
algorithm.lock()
try {
@@ -177,7 +177,7 @@ open class ClusterManager
* @param myItem item to add to clusters
* @return true if the cluster manager contents changed as a result of the call
*/
- open fun addItem(myItem: T): Boolean {
+ public open fun addItem(myItem: T): Boolean {
val algorithm = algorithm
algorithm.lock()
try {
@@ -187,7 +187,7 @@ open class ClusterManager
}
}
- open fun diff(
+ public open fun diff(
add: Collection<@JvmSuppressWildcards T>?,
remove: Collection<@JvmSuppressWildcards T>?,
modify: Collection<@JvmSuppressWildcards T>?,
@@ -224,7 +224,7 @@ open class ClusterManager
* @param items items to remove from clusters
* @return true if the cluster manager contents changed as a result of the call
*/
- open fun removeItems(items: Collection<@JvmSuppressWildcards T>?): Boolean {
+ public open fun removeItems(items: Collection<@JvmSuppressWildcards T>?): Boolean {
val algorithm = algorithm
algorithm.lock()
try {
@@ -240,7 +240,7 @@ open class ClusterManager
* @param item item to remove from clusters
* @return true if the item was removed from the cluster manager as a result of this call
*/
- open fun removeItem(item: T): Boolean {
+ public open fun removeItem(item: T): Boolean {
val algorithm = algorithm
algorithm.lock()
try {
@@ -257,7 +257,7 @@ open class ClusterManager
* @return true if the item was updated in the cluster manager, false if the item is not
* contained within the cluster manager and the cluster manager contents are unchanged
*/
- open fun updateItem(item: T): Boolean {
+ public open fun updateItem(item: T): Boolean {
val algorithm = algorithm
algorithm.lock()
try {
@@ -271,7 +271,7 @@ open class ClusterManager
* Force a re-cluster on the map. You should call this after adding, removing, updating,
* or clearing item(s).
*/
- open fun cluster() {
+ public open fun cluster() {
mClusterTaskLock.writeLock().lock()
try {
// Attempt to cancel the in-flight request.
@@ -327,7 +327,7 @@ open class ClusterManager
* Sets a callback that's invoked when a Cluster is tapped. Note: For this listener to function,
* the ClusterManager must be added as a click listener to the map.
*/
- open fun setOnClusterClickListener(listener: OnClusterClickListener?) {
+ public open fun setOnClusterClickListener(listener: OnClusterClickListener?) {
mOnClusterClickListener = listener
mRenderer.setOnClusterClickListener(listener)
}
@@ -336,7 +336,7 @@ open class ClusterManager
* Sets a callback that's invoked when a Cluster info window is tapped. Note: For this listener to function,
* the ClusterManager must be added as a info window click listener to the map.
*/
- open fun setOnClusterInfoWindowClickListener(listener: OnClusterInfoWindowClickListener?) {
+ public open fun setOnClusterInfoWindowClickListener(listener: OnClusterInfoWindowClickListener?) {
mOnClusterInfoWindowClickListener = listener
mRenderer.setOnClusterInfoWindowClickListener(listener)
}
@@ -345,7 +345,7 @@ open class ClusterManager
* Sets a callback that's invoked when a Cluster info window is long-pressed. Note: For this listener to function,
* the ClusterManager must be added as a info window click listener to the map.
*/
- open fun setOnClusterInfoWindowLongClickListener(listener: OnClusterInfoWindowLongClickListener?) {
+ public open fun setOnClusterInfoWindowLongClickListener(listener: OnClusterInfoWindowLongClickListener?) {
mOnClusterInfoWindowLongClickListener = listener
mRenderer.setOnClusterInfoWindowLongClickListener(listener)
}
@@ -354,7 +354,7 @@ open class ClusterManager
* Sets a callback that's invoked when an individual ClusterItem is tapped. Note: For this
* listener to function, the ClusterManager must be added as a click listener to the map.
*/
- open fun setOnClusterItemClickListener(listener: OnClusterItemClickListener?) {
+ public open fun setOnClusterItemClickListener(listener: OnClusterItemClickListener?) {
mOnClusterItemClickListener = listener
mRenderer.setOnClusterItemClickListener(listener)
}
@@ -363,7 +363,7 @@ open class ClusterManager
* Sets a callback that's invoked when an individual ClusterItem's Info Window is tapped. Note: For this
* listener to function, the ClusterManager must be added as a info window click listener to the map.
*/
- open fun setOnClusterItemInfoWindowClickListener(listener: OnClusterItemInfoWindowClickListener?) {
+ public open fun setOnClusterItemInfoWindowClickListener(listener: OnClusterItemInfoWindowClickListener?) {
mOnClusterItemInfoWindowClickListener = listener
mRenderer.setOnClusterItemInfoWindowClickListener(listener)
}
@@ -372,7 +372,7 @@ open class ClusterManager
* Sets a callback that's invoked when an individual ClusterItem's Info Window is long-pressed. Note: For this
* listener to function, the ClusterManager must be added as a info window click listener to the map.
*/
- open fun setOnClusterItemInfoWindowLongClickListener(listener: OnClusterItemInfoWindowLongClickListener?) {
+ public open fun setOnClusterItemInfoWindowLongClickListener(listener: OnClusterItemInfoWindowLongClickListener?) {
mOnClusterItemInfoWindowLongClickListener = listener
mRenderer.setOnClusterItemInfoWindowLongClickListener(listener)
}
@@ -380,33 +380,33 @@ open class ClusterManager
/**
* Called when a Cluster is clicked.
*/
- fun interface OnClusterClickListener {
+ public fun interface OnClusterClickListener {
/**
- * Called when cluster is clicked.
- * Return true if click has been handled
- * Return false and the click will dispatched to the next listener
- */
- fun onClusterClick(cluster: Cluster): Boolean
+ * Called when cluster is clicked.
+ * Return true if click has been handled
+ * Return false and the click will dispatched to the next listener
+ */
+ public fun onClusterClick(cluster: Cluster): Boolean
}
/**
* Called when a Cluster's Info Window is clicked.
*/
- fun interface OnClusterInfoWindowClickListener {
- fun onClusterInfoWindowClick(cluster: Cluster)
+ public fun interface OnClusterInfoWindowClickListener {
+ public fun onClusterInfoWindowClick(cluster: Cluster)
}
/**
* Called when a Cluster's Info Window is long clicked.
*/
- fun interface OnClusterInfoWindowLongClickListener {
- fun onClusterInfoWindowLongClick(cluster: Cluster)
+ public fun interface OnClusterInfoWindowLongClickListener {
+ public fun onClusterInfoWindowLongClick(cluster: Cluster)
}
/**
* Called when an individual ClusterItem is clicked.
*/
- fun interface OnClusterItemClickListener {
+ public fun interface OnClusterItemClickListener {
/**
* Called when `item` is clicked.
*
@@ -416,20 +416,20 @@ open class ClusterManager
* occur), false otherwise (i.e. the default behavior should occur). The default behavior
* is for the camera to move to the marker and an info window to appear.
*/
- fun onClusterItemClick(item: T): Boolean
+ public fun onClusterItemClick(item: T): Boolean
}
/**
* Called when an individual ClusterItem's Info Window is clicked.
*/
- fun interface OnClusterItemInfoWindowClickListener {
- fun onClusterItemInfoWindowClick(item: T)
+ public fun interface OnClusterItemInfoWindowClickListener {
+ public fun onClusterItemInfoWindowClick(item: T)
}
/**
* Called when an individual ClusterItem's Info Window is long clicked.
*/
- fun interface OnClusterItemInfoWindowLongClickListener {
- fun onClusterItemInfoWindowLongClick(item: T)
+ public fun interface OnClusterItemInfoWindowLongClickListener {
+ public fun onClusterItemInfoWindowLongClick(item: T)
}
}
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/ClusterManagerFlows.kt b/clustering/src/main/java/com/google/maps/android/clustering/ClusterManagerFlows.kt
new file mode 100644
index 000000000..51fd21d4e
--- /dev/null
+++ b/clustering/src/main/java/com/google/maps/android/clustering/ClusterManagerFlows.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.google.maps.android.clustering
+
+import com.google.maps.android.clustering.Cluster
+import com.google.maps.android.clustering.ClusterItem
+import com.google.maps.android.clustering.ClusterManager
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+
+/**
+ * Returns a flow that emits when a cluster is clicked. Using this to observe cluster clicks
+ * will override an existing listener (if any) to [ClusterManager.setOnClusterClickListener].
+ *
+ * **Warning**: This is a cold flow wrapping a single-listener SDK callback. Concurrently subscribing
+ * multiple collectors will result in listener hijacking, and cancelling any observer will unregister
+ * the active listener completely. Always share this flow (e.g. using [kotlinx.coroutines.flow.shareIn])
+ * for multi-observer configurations.
+ *
+ * **Note on event consumption**: The underlying SDK listener returns the result of `trySend().isSuccess`.
+ * When an emission is accepted by the flow buffer, the click event is considered consumed (`true`),
+ * suppressing default SDK behavior (such as zooming). Under backpressure if the buffer is full,
+ * `trySend` returns `false`, allowing default SDK click handling to proceed.
+ */
+public fun ClusterManager.clusterClickEvents(): Flow> =
+ callbackFlow {
+ setOnClusterClickListener {
+ trySend(it).isSuccess
+ }
+ awaitClose {
+ setOnClusterClickListener(null)
+ }
+ }
+
+/**
+ * Returns a flow that emits when a cluster item is clicked. Using this to observe cluster item clicks
+ * will override an existing listener (if any) to [ClusterManager.setOnClusterItemClickListener].
+ *
+ * **Warning**: This is a cold flow wrapping a single-listener SDK callback. Concurrently subscribing
+ * multiple collectors will result in listener hijacking, and cancelling any observer will unregister
+ * the active listener completely. Always share this flow (e.g. using [kotlinx.coroutines.flow.shareIn])
+ * for multi-observer configurations.
+ *
+ * **Note on event consumption**: The underlying SDK listener returns the result of `trySend().isSuccess`.
+ * When an emission is accepted by the flow buffer, the click event is considered consumed (`true`),
+ * suppressing default SDK behavior. Under backpressure if the buffer is full, `trySend` returns `false`,
+ * allowing default SDK click handling to proceed.
+ */
+public fun ClusterManager.clusterItemClickEvents(): Flow =
+ callbackFlow {
+ setOnClusterItemClickListener {
+ trySend(it).isSuccess
+ }
+ awaitClose {
+ setOnClusterItemClickListener(null)
+ }
+ }
+
+/**
+ * Returns a flow that emits when a cluster's info window is clicked. Using this to observe cluster info window clicks
+ * will override an existing listener (if any) to [ClusterManager.setOnClusterInfoWindowClickListener].
+ *
+ * **Warning**: This is a cold flow wrapping a single-listener SDK callback. Concurrently subscribing
+ * multiple collectors will result in listener hijacking, and cancelling any observer will unregister
+ * the active listener completely. Always share this flow (e.g. using [kotlinx.coroutines.flow.shareIn])
+ * for multi-observer configurations.
+ */
+public fun ClusterManager.clusterInfoWindowClickEvents(): Flow> =
+ callbackFlow {
+ setOnClusterInfoWindowClickListener {
+ trySend(it).isSuccess
+ }
+ awaitClose {
+ setOnClusterInfoWindowClickListener(null)
+ }
+ }
+
+/**
+ * Returns a flow that emits when a cluster's info window is long clicked. Using this to observe cluster info window long clicks
+ * will override an existing listener (if any) to [ClusterManager.setOnClusterInfoWindowLongClickListener].
+ *
+ * **Warning**: This is a cold flow wrapping a single-listener SDK callback. Concurrently subscribing
+ * multiple collectors will result in listener hijacking, and cancelling any observer will unregister
+ * the active listener completely. Always share this flow (e.g. using [kotlinx.coroutines.flow.shareIn])
+ * for multi-observer configurations.
+ */
+public fun ClusterManager.clusterInfoWindowLongClickEvents(): Flow> =
+ callbackFlow {
+ setOnClusterInfoWindowLongClickListener {
+ trySend(it).isSuccess
+ }
+ awaitClose {
+ setOnClusterInfoWindowLongClickListener(null)
+ }
+ }
+
+/**
+ * Returns a flow that emits when a cluster item's info window is clicked. Using this to observe cluster item info window clicks
+ * will override an existing listener (if any) to [ClusterManager.setOnClusterItemInfoWindowClickListener].
+ *
+ * **Warning**: This is a cold flow wrapping a single-listener SDK callback. Concurrently subscribing
+ * multiple collectors will result in listener hijacking, and cancelling any observer will unregister
+ * the active listener completely. Always share this flow (e.g. using [kotlinx.coroutines.flow.shareIn])
+ * for multi-observer configurations.
+ */
+public fun ClusterManager.clusterItemInfoWindowClickEvents(): Flow =
+ callbackFlow {
+ setOnClusterItemInfoWindowClickListener {
+ trySend(it).isSuccess
+ }
+ awaitClose {
+ setOnClusterItemInfoWindowClickListener(null)
+ }
+ }
+
+/**
+ * Returns a flow that emits when a cluster item's info window is long clicked. Using this to observe cluster item info window long clicks
+ * will override an existing listener (if any) to [ClusterManager.setOnClusterItemInfoWindowLongClickListener].
+ *
+ * **Warning**: This is a cold flow wrapping a single-listener SDK callback. Concurrently subscribing
+ * multiple collectors will result in listener hijacking, and cancelling any observer will unregister
+ * the active listener completely. Always share this flow (e.g. using [kotlinx.coroutines.flow.shareIn])
+ * for multi-observer configurations.
+ */
+public fun ClusterManager.clusterItemInfoWindowLongClickEvents(): Flow =
+ callbackFlow {
+ setOnClusterItemInfoWindowLongClickListener {
+ trySend(it).isSuccess
+ }
+ awaitClose {
+ setOnClusterItemInfoWindowLongClickListener(null)
+ }
+ }
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/AbstractAlgorithm.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/AbstractAlgorithm.kt
index 8ba76a038..639a1ed80 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/AbstractAlgorithm.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/AbstractAlgorithm.kt
@@ -22,7 +22,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock
/**
* Base Algorithm class that implements lock/unlock functionality.
*/
-abstract class AbstractAlgorithm : Algorithm {
+public abstract class AbstractAlgorithm : Algorithm {
private val mLock: ReadWriteLock = ReentrantReadWriteLock()
override fun lock() {
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/Algorithm.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/Algorithm.kt
index ab6b67e58..c5904d58d 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/Algorithm.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/Algorithm.kt
@@ -21,22 +21,22 @@ import com.google.maps.android.clustering.ClusterItem
/**
* Logic for computing clusters
*/
-interface Algorithm {
+public interface Algorithm {
/**
* Adds an item to the algorithm
* @param item the item to be added
* @return true if the algorithm contents changed as a result of the call
*/
- fun addItem(item: T): Boolean
+ public fun addItem(item: T): Boolean
/**
* Adds a collection of items to the algorithm
* @param items the items to be added
* @return true if the algorithm contents changed as a result of the call
*/
- fun addItems(items: Collection): Boolean
+ public fun addItems(items: Collection): Boolean
- fun clearItems()
+ public fun clearItems()
/**
* Removes an item from the algorithm
@@ -44,7 +44,7 @@ interface Algorithm {
* @return true if this algorithm contained the specified element (or equivalently, if this
* algorithm changed as a result of the call).
*/
- fun removeItem(item: T): Boolean
+ public fun removeItem(item: T): Boolean
/**
* Updates the provided item in the algorithm
@@ -52,22 +52,22 @@ interface Algorithm {
* @return true if the item existed in the algorithm and was updated, or false if the item did
* not exist in the algorithm and the algorithm contents remain unchanged.
*/
- fun updateItem(item: T): Boolean
+ public fun updateItem(item: T): Boolean
/**
* Removes a collection of items from the algorithm
* @param items the items to be removed
* @return true if this algorithm contents changed as a result of the call
*/
- fun removeItems(items: Collection): Boolean
+ public fun removeItems(items: Collection): Boolean
- fun getClusters(zoom: Float): Set>
+ public fun getClusters(zoom: Float): Set>
- val items: Collection
+ public val items: Collection
- var maxDistanceBetweenClusteredItems: Int
+ public var maxDistanceBetweenClusteredItems: Int
- fun lock()
+ public fun lock()
- fun unlock()
+ public fun unlock()
}
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/CentroidNonHierarchicalDistanceBasedAlgorithm.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/CentroidNonHierarchicalDistanceBasedAlgorithm.kt
index 521e7971f..ca66c4fc7 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/CentroidNonHierarchicalDistanceBasedAlgorithm.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/CentroidNonHierarchicalDistanceBasedAlgorithm.kt
@@ -31,7 +31,7 @@ import java.util.HashSet
*
* @param the type of cluster item
*/
-open class CentroidNonHierarchicalDistanceBasedAlgorithm : NonHierarchicalDistanceBasedAlgorithm() {
+public open class CentroidNonHierarchicalDistanceBasedAlgorithm : NonHierarchicalDistanceBasedAlgorithm() {
/**
* Computes the centroid (average latitude and longitude) of a collection of cluster items.
*
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/ContinuousZoomEuclideanCentroidAlgorithm.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/ContinuousZoomEuclideanCentroidAlgorithm.kt
index b9c048aca..b3c40c551 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/ContinuousZoomEuclideanCentroidAlgorithm.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/ContinuousZoomEuclideanCentroidAlgorithm.kt
@@ -31,7 +31,7 @@ import kotlin.math.pow
*
* @param the type of cluster item
*/
-class ContinuousZoomEuclideanCentroidAlgorithm : CentroidNonHierarchicalDistanceBasedAlgorithm() {
+public open class ContinuousZoomEuclideanCentroidAlgorithm : CentroidNonHierarchicalDistanceBasedAlgorithm() {
override fun getClusters(zoom: Float): Set> {
// Continuous zoom — no casting to int
val zoomSpecificSpan = maxDistanceBetweenClusteredItems.toDouble() / 2.0.pow(zoom.toDouble()) / 256.0
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/GridBasedAlgorithm.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/GridBasedAlgorithm.kt
index 4a77032b8..ad0c7f370 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/GridBasedAlgorithm.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/GridBasedAlgorithm.kt
@@ -35,7 +35,7 @@ import kotlin.math.pow
*
* @param The type of {@link ClusterItem} to be clustered.
*/
-class GridBasedAlgorithm : AbstractAlgorithm() {
+public open class GridBasedAlgorithm : AbstractAlgorithm() {
private var mGridSize = DEFAULT_GRID_SIZE
private val mItems: MutableSet = Collections.synchronizedSet(HashSet())
@@ -103,7 +103,7 @@ class GridBasedAlgorithm : AbstractAlgorithm() {
override val items: Collection
get() = mItems
- companion object {
+ public companion object {
private const val DEFAULT_GRID_SIZE = 100
private fun getCoord(
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.kt
index 5fcac43e9..948100062 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/NonHierarchicalDistanceBasedAlgorithm.kt
@@ -40,13 +40,13 @@ import java.util.LinkedHashSet
*
* Clusters have the center of the first element (not the centroid of the items within it).
*/
-open class NonHierarchicalDistanceBasedAlgorithm : AbstractAlgorithm() {
+public open class NonHierarchicalDistanceBasedAlgorithm : AbstractAlgorithm() {
/**
* Any modifications should be synchronized on mQuadTree.
*/
@JvmField
protected val mItems: MutableCollection> = LinkedHashSet()
- protected val mItemMap = HashMap>()
+ protected val mItemMap: MutableMap> = HashMap()
/**
* Any modifications should be synchronized on mQuadTree.
@@ -230,7 +230,7 @@ open class NonHierarchicalDistanceBasedAlgorithm : AbstractAlgo
}
protected class QuadItem(
- @JvmField val mClusterItem: T,
+ @JvmField public val mClusterItem: T,
) : PointQuadTree.Item,
Cluster {
private val mPoint: Point = PROJECTION.toPoint(mClusterItem.position)
@@ -260,7 +260,7 @@ open class NonHierarchicalDistanceBasedAlgorithm : AbstractAlgo
}
}
- companion object {
+ public companion object {
private const val DEFAULT_MAX_DISTANCE_AT_ZOOM = 100 // essentially 100 dp.
private val PROJECTION = SphericalMercatorProjection(1.0)
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/NonHierarchicalViewBasedAlgorithm.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/NonHierarchicalViewBasedAlgorithm.kt
index bdd28d678..2ed7f1a66 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/NonHierarchicalViewBasedAlgorithm.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/NonHierarchicalViewBasedAlgorithm.kt
@@ -31,12 +31,12 @@ import kotlin.math.pow
*
* @param The [ClusterItem] type
*/
-class NonHierarchicalViewBasedAlgorithm
+public open class NonHierarchicalViewBasedAlgorithm
/**
* @param screenWidth map width in dp
* @param screenHeight map height in dp
*/
- (private var mViewWidth: Int, private var mViewHeight: Int) : NonHierarchicalDistanceBasedAlgorithm(), ScreenBasedAlgorithm {
+ public constructor(private var mViewWidth: Int, private var mViewHeight: Int) : NonHierarchicalDistanceBasedAlgorithm(), ScreenBasedAlgorithm {
private var mMapCenter: LatLng? = null
@@ -75,7 +75,7 @@ class NonHierarchicalViewBasedAlgorithm
* @param width map width in dp
* @param height map height in dp
*/
- fun updateViewSize(width: Int, height: Int) {
+ public fun updateViewSize(width: Int, height: Int) {
mViewWidth = width
mViewHeight = height
}
@@ -96,7 +96,7 @@ class NonHierarchicalViewBasedAlgorithm
)
}
- companion object {
+ public companion object {
private val PROJECTION = SphericalMercatorProjection(1.0)
}
}
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/PreCachingAlgorithmDecorator.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/PreCachingAlgorithmDecorator.kt
index 9ae93c972..8ac578260 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/PreCachingAlgorithmDecorator.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/PreCachingAlgorithmDecorator.kt
@@ -27,7 +27,7 @@ import kotlin.concurrent.withLock
/**
* Optimistically fetch clusters for adjacent zoom levels, caching them as necessary.
*/
-class PreCachingAlgorithmDecorator(
+public open class PreCachingAlgorithmDecorator public constructor(
private val algorithm: Algorithm,
) : AbstractAlgorithm() {
// TODO: evaluate maxSize parameter for LruCache.
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/ScreenBasedAlgorithm.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/ScreenBasedAlgorithm.kt
index f6aab988f..193d55fbe 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/ScreenBasedAlgorithm.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/ScreenBasedAlgorithm.kt
@@ -25,8 +25,8 @@ import com.google.maps.android.clustering.ClusterItem
*
* @param The {@link ClusterItem} type
*/
-interface ScreenBasedAlgorithm : Algorithm {
- fun shouldReclusterOnMapMovement(): Boolean
+public interface ScreenBasedAlgorithm : Algorithm {
+ public fun shouldReclusterOnMapMovement(): Boolean
- fun onCameraChange(position: CameraPosition)
+ public fun onCameraChange(position: CameraPosition)
}
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/ScreenBasedAlgorithmAdapter.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/ScreenBasedAlgorithmAdapter.kt
index 52f08c02d..dd04abc70 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/ScreenBasedAlgorithmAdapter.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/ScreenBasedAlgorithmAdapter.kt
@@ -19,7 +19,7 @@ import com.google.android.gms.maps.model.CameraPosition
import com.google.maps.android.clustering.Cluster
import com.google.maps.android.clustering.ClusterItem
-class ScreenBasedAlgorithmAdapter(
+public open class ScreenBasedAlgorithmAdapter public constructor(
private val algorithm: Algorithm,
) : AbstractAlgorithm(),
ScreenBasedAlgorithm {
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/algo/StaticCluster.kt b/clustering/src/main/java/com/google/maps/android/clustering/algo/StaticCluster.kt
index e292b6e33..a10d87160 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/algo/StaticCluster.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/algo/StaticCluster.kt
@@ -22,17 +22,17 @@ import com.google.maps.android.clustering.ClusterItem
/**
* A cluster whose center is determined upon creation.
*/
-class StaticCluster(
+public open class StaticCluster public constructor(
private val mCenter: LatLng,
) : Cluster {
private val mItems: MutableCollection = LinkedHashSet()
- fun add(t: T): Boolean = mItems.add(t)
+ public fun add(t: T): Boolean = mItems.add(t)
override val position: LatLng
get() = mCenter
- fun remove(t: T): Boolean = mItems.remove(t)
+ public fun remove(t: T): Boolean = mItems.remove(t)
override val items: Collection
get() = mItems
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/view/ClusterRenderer.kt b/clustering/src/main/java/com/google/maps/android/clustering/view/ClusterRenderer.kt
index 02a200b4a..0f882bd47 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/view/ClusterRenderer.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/view/ClusterRenderer.kt
@@ -28,54 +28,54 @@ import com.google.maps.android.clustering.ClusterManager.OnClusterItemInfoWindow
/**
* Renders clusters.
*/
-interface ClusterRenderer {
+public interface ClusterRenderer {
/**
* Called when the view needs to be updated because new clusters need to be displayed.
*
* @param clusters the clusters to be displayed.
*/
- fun onClustersChanged(clusters: Set>)
+ public fun onClustersChanged(clusters: Set>)
- fun setOnClusterClickListener(listener: OnClusterClickListener?)
+ public fun setOnClusterClickListener(listener: OnClusterClickListener?)
- fun setOnClusterInfoWindowClickListener(listener: OnClusterInfoWindowClickListener?)
+ public fun setOnClusterInfoWindowClickListener(listener: OnClusterInfoWindowClickListener?)
- fun setOnClusterInfoWindowLongClickListener(listener: OnClusterInfoWindowLongClickListener?)
+ public fun setOnClusterInfoWindowLongClickListener(listener: OnClusterInfoWindowLongClickListener?)
- fun setOnClusterItemClickListener(listener: OnClusterItemClickListener?)
+ public fun setOnClusterItemClickListener(listener: OnClusterItemClickListener?)
- fun setOnClusterItemInfoWindowClickListener(listener: OnClusterItemInfoWindowClickListener?)
+ public fun setOnClusterItemInfoWindowClickListener(listener: OnClusterItemInfoWindowClickListener?)
- fun setOnClusterItemInfoWindowLongClickListener(listener: OnClusterItemInfoWindowLongClickListener?)
+ public fun setOnClusterItemInfoWindowLongClickListener(listener: OnClusterItemInfoWindowLongClickListener?)
/**
* Called to set animation on or off
*/
- fun setAnimation(animate: Boolean)
+ public fun setAnimation(animate: Boolean)
/**
* Sets the length of the animation in milliseconds.
*/
- fun setAnimationDuration(animationDurationMs: Long)
+ public fun setAnimationDuration(animationDurationMs: Long)
/**
* Called when the view is added.
*/
- fun onAdd()
+ public fun onAdd()
/**
* Called when the view is removed.
*/
- fun onRemove()
+ public fun onRemove()
/**
* Called to determine the color of a Cluster.
*/
- fun getColor(clusterSize: Int): Int
+ public fun getColor(clusterSize: Int): Int
/**
* Called to determine the text appearance of a cluster.
*/
@StyleRes
- fun getClusterTextAppearance(clusterSize: Int): Int
+ public fun getClusterTextAppearance(clusterSize: Int): Int
}
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/view/ClusterRendererMultipleItems.kt b/clustering/src/main/java/com/google/maps/android/clustering/view/ClusterRendererMultipleItems.kt
index 15356bfb7..d3435ce88 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/view/ClusterRendererMultipleItems.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/view/ClusterRendererMultipleItems.kt
@@ -73,7 +73,7 @@ import kotlin.math.sign
/**
* The default view for a ClusterManager. Markers are animated in and out of clusters.
*/
-open class ClusterRendererMultipleItems @JvmOverloads constructor(
+public open class ClusterRendererMultipleItems @JvmOverloads public constructor(
context: Context,
private val mMap: GoogleMap,
private val mClusterManager: ClusterManager,
@@ -90,7 +90,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
// Default interpolator
private var animationInterp: TimeInterpolator = DecelerateInterpolator()
- enum class AnimationType {
+ public enum class AnimationType {
LINEAR,
EASE_IN,
EASE_OUT,
@@ -101,7 +101,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
DECELERATE,
}
- fun setAnimationType(type: AnimationType) {
+ public fun setAnimationType(type: AnimationType) {
animationInterp =
when (type) {
AnimationType.LINEAR -> LinearInterpolator()
@@ -118,7 +118,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
*
* @param interpolator the interpolator to use for the animation.
*/
- fun setAnimationInterpolator(interpolator: TimeInterpolator) {
+ public fun setAnimationInterpolator(interpolator: TimeInterpolator) {
animationInterp = interpolator
}
@@ -140,7 +140,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
/**
* If cluster size is less than this size, display individual markers.
*/
- var minClusterSize: Int = 2
+ public open var minClusterSize: Int = 2
/**
* The currently displayed set of clusters.
@@ -263,7 +263,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
*
* @param enabled `true` to enable logging; `false` to disable it.
*/
- fun setLoggingEnabled(enabled: Boolean) {
+ public fun setLoggingEnabled(enabled: Boolean) {
RendererLogger.setEnabled(enabled)
}
@@ -577,7 +577,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
mAnimationDurationMs = animationDurationMs
}
- fun stopAnimation() {
+ public fun stopAnimation() {
for (animation in ongoingAnimations) {
animation.cancel()
}
@@ -904,7 +904,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
marker: Marker,
) {
var changed = false
- // Update marker text if the item text changed - same logic as adding marker in CreateMarkerTask.perform()
+ // Update marker text if the item text changed - same logic as adding marker in onBeforeClusterItemRendered()
if (item.title != null && item.snippet != null) {
if (item.title != marker.title) {
marker.title = item.title
@@ -914,19 +914,33 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
marker.snippet = item.snippet
changed = true
}
- } else if (item.snippet != null && item.snippet != marker.title) {
- marker.title = item.snippet
- changed = true
- } else if (item.title != null && item.title != marker.title) {
- marker.title = item.title
- changed = true
+ } else if (item.snippet != null) {
+ if (item.snippet != marker.title) {
+ marker.title = item.snippet
+ changed = true
+ }
+ if (marker.snippet != null) {
+ marker.snippet = null
+ changed = true
+ }
+ } else if (item.title != null) {
+ if (item.title != marker.title) {
+ marker.title = item.title
+ changed = true
+ }
+ if (marker.snippet != null) {
+ marker.snippet = null
+ changed = true
+ }
}
// Update marker position if the item changed position
if (marker.position != item.position) {
marker.position = item.position
- if (item.zIndex != null) {
- marker.zIndex = item.zIndex!!
- }
+ changed = true
+ }
+ val itemZIndex = item.zIndex
+ if (itemZIndex != null && marker.zIndex != itemZIndex) {
+ marker.zIndex = itemZIndex
changed = true
}
if (changed && marker.isInfoWindowShown) {
@@ -1034,7 +1048,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
* @param clusterItem ClusterItem which you will obtain its marker
* @return a marker from a ClusterItem or null if it does not exists
*/
- fun getMarker(clusterItem: T): Marker? = mMarkerCache[clusterItem]
+ public open fun getMarker(clusterItem: T): Marker? = mMarkerCache[clusterItem]
/**
* Get the ClusterItem from a marker
@@ -1042,7 +1056,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
* @param marker which you will obtain its ClusterItem
* @return a ClusterItem from a marker or null if it does not exists
*/
- fun getClusterItem(marker: Marker): T? = mMarkerCache[marker]
+ public open fun getClusterItem(marker: Marker): T? = mMarkerCache[marker]
/**
* Get the marker from a Cluster
@@ -1050,7 +1064,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
* @param cluster which you will obtain its marker
* @return a marker from a cluster or null if it does not exists
*/
- fun getMarker(cluster: Cluster): Marker? = mClusterMarkerCache[cluster]
+ public open fun getMarker(cluster: Cluster): Marker? = mClusterMarkerCache[cluster]
/**
* Get the Cluster from a marker
@@ -1058,7 +1072,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
* @param marker which you will obtain its Cluster
* @return a Cluster from a marker or null if it does not exists
*/
- fun getCluster(marker: Marker): Cluster? = mClusterMarkerCache[marker]
+ public open fun getCluster(marker: Marker): Cluster? = mClusterMarkerCache[marker]
/**
* Creates markerWithPosition(s) for a particular cluster, animating it if necessary.
@@ -1259,7 +1273,7 @@ open class ClusterRendererMultipleItems @JvmOverloads construct
}
}
- companion object {
+ public companion object {
private val BUCKETS = intArrayOf(10, 20, 50, 100, 200, 500, 1000)
private const val RUN_TASK = 0
private const val TASK_FINISHED = 1
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/view/DefaultAdvancedMarkersClusterRenderer.kt b/clustering/src/main/java/com/google/maps/android/clustering/view/DefaultAdvancedMarkersClusterRenderer.kt
index c36d6fa5c..c22107b76 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/view/DefaultAdvancedMarkersClusterRenderer.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/view/DefaultAdvancedMarkersClusterRenderer.kt
@@ -69,7 +69,7 @@ import kotlin.math.sign
/**
* The default view for a ClusterManager. Markers are animated in and out of clusters.
*/
-open class DefaultAdvancedMarkersClusterRenderer @JvmOverloads constructor(
+public open class DefaultAdvancedMarkersClusterRenderer @JvmOverloads public constructor(
context: Context,
private val mMap: GoogleMap,
private val mClusterManager: ClusterManager,
@@ -102,7 +102,7 @@ open class DefaultAdvancedMarkersClusterRenderer @JvmOverloads
/**
* If cluster size is less than this size, display individual markers.
*/
- var minClusterSize: Int = 4
+ public open var minClusterSize: Int = 4
/**
* The currently displayed set of clusters.
@@ -833,7 +833,7 @@ open class DefaultAdvancedMarkersClusterRenderer @JvmOverloads
marker: Marker,
) {
var changed = false
- // Update marker text if the item text changed - same logic as adding marker in CreateMarkerTask.perform()
+ // Update marker text if the item text changed - same logic as adding marker in onBeforeClusterItemRendered()
if (item.title != null && item.snippet != null) {
if (item.title != marker.title) {
marker.title = item.title
@@ -843,19 +843,33 @@ open class DefaultAdvancedMarkersClusterRenderer @JvmOverloads
marker.snippet = item.snippet
changed = true
}
- } else if (item.snippet != null && item.snippet != marker.title) {
- marker.title = item.snippet
- changed = true
- } else if (item.title != null && item.title != marker.title) {
- marker.title = item.title
- changed = true
+ } else if (item.snippet != null) {
+ if (item.snippet != marker.title) {
+ marker.title = item.snippet
+ changed = true
+ }
+ if (marker.snippet != null) {
+ marker.snippet = null
+ changed = true
+ }
+ } else if (item.title != null) {
+ if (item.title != marker.title) {
+ marker.title = item.title
+ changed = true
+ }
+ if (marker.snippet != null) {
+ marker.snippet = null
+ changed = true
+ }
}
// Update marker position if the item changed position
if (marker.position != item.position) {
marker.position = item.position
- if (item.zIndex != null) {
- marker.zIndex = item.zIndex!!
- }
+ changed = true
+ }
+ val itemZIndex = item.zIndex
+ if (itemZIndex != null && marker.zIndex != itemZIndex) {
+ marker.zIndex = itemZIndex
changed = true
}
if (changed && marker.isInfoWindowShown) {
@@ -963,7 +977,7 @@ open class DefaultAdvancedMarkersClusterRenderer @JvmOverloads
* @param clusterItem ClusterItem which you will obtain its marker
* @return a marker from a ClusterItem or null if it does not exists
*/
- fun getMarker(clusterItem: T): Marker? = mMarkerCache[clusterItem]
+ public open fun getMarker(clusterItem: T): Marker? = mMarkerCache[clusterItem]
/**
* Get the ClusterItem from a marker
@@ -971,7 +985,7 @@ open class DefaultAdvancedMarkersClusterRenderer @JvmOverloads
* @param marker which you will obtain its ClusterItem
* @return a ClusterItem from a marker or null if it does not exists
*/
- fun getClusterItem(marker: Marker): T? = mMarkerCache[marker]
+ public open fun getClusterItem(marker: Marker): T? = mMarkerCache[marker]
/**
* Get the marker from a Cluster
@@ -979,7 +993,7 @@ open class DefaultAdvancedMarkersClusterRenderer @JvmOverloads
* @param cluster which you will obtain its marker
* @return a marker from a cluster or null if it does not exists
*/
- fun getMarker(cluster: Cluster): Marker? = mClusterMarkerCache[cluster]
+ public open fun getMarker(cluster: Cluster): Marker? = mClusterMarkerCache[cluster]
/**
* Get the Cluster from a marker
@@ -987,7 +1001,7 @@ open class DefaultAdvancedMarkersClusterRenderer @JvmOverloads
* @param marker which you will obtain its Cluster
* @return a Cluster from a marker or null if it does not exists
*/
- fun getCluster(marker: Marker): Cluster? = mClusterMarkerCache[marker]
+ public open fun getCluster(marker: Marker): Cluster? = mClusterMarkerCache[marker]
/**
* Creates markerWithPosition(s) for a particular cluster, animating it if necessary.
@@ -1123,7 +1137,7 @@ open class DefaultAdvancedMarkersClusterRenderer @JvmOverloads
}
}
- companion object {
+ public companion object {
private val BUCKETS = intArrayOf(10, 20, 50, 100, 200, 500, 1000)
private val ANIMATION_INTERP: TimeInterpolator = DecelerateInterpolator()
private const val RUN_TASK = 0
diff --git a/clustering/src/main/java/com/google/maps/android/clustering/view/DefaultClusterRenderer.kt b/clustering/src/main/java/com/google/maps/android/clustering/view/DefaultClusterRenderer.kt
index ed2633829..d59d406a0 100644
--- a/clustering/src/main/java/com/google/maps/android/clustering/view/DefaultClusterRenderer.kt
+++ b/clustering/src/main/java/com/google/maps/android/clustering/view/DefaultClusterRenderer.kt
@@ -68,7 +68,7 @@ import kotlin.math.sign
/**
* The default view for a ClusterManager. Markers are animated in and out of clusters.
*/
-open class DefaultClusterRenderer @JvmOverloads constructor(
+public open class DefaultClusterRenderer @JvmOverloads public constructor(
context: Context,
private val mMap: GoogleMap,
private val mClusterManager: ClusterManager,
@@ -101,7 +101,7 @@ open class DefaultClusterRenderer @JvmOverloads constructor(
/**
* If cluster size is less than this size, display individual markers.
*/
- var minClusterSize: Int = 4
+ public open var minClusterSize: Int = 4
/**
* The currently displayed set of clusters.
@@ -835,7 +835,7 @@ open class DefaultClusterRenderer @JvmOverloads constructor(
marker: Marker,
) {
var changed = false
- // Update marker text if the item text changed - same logic as adding marker in CreateMarkerTask.perform()
+ // Update marker text if the item text changed - same logic as adding marker in onBeforeClusterItemRendered()
if (item.title != null && item.snippet != null) {
if (item.title != marker.title) {
marker.title = item.title
@@ -845,19 +845,33 @@ open class DefaultClusterRenderer @JvmOverloads constructor(
marker.snippet = item.snippet
changed = true
}
- } else if (item.snippet != null && item.snippet != marker.title) {
- marker.title = item.snippet
- changed = true
- } else if (item.title != null && item.title != marker.title) {
- marker.title = item.title
- changed = true
+ } else if (item.snippet != null) {
+ if (item.snippet != marker.title) {
+ marker.title = item.snippet
+ changed = true
+ }
+ if (marker.snippet != null) {
+ marker.snippet = null
+ changed = true
+ }
+ } else if (item.title != null) {
+ if (item.title != marker.title) {
+ marker.title = item.title
+ changed = true
+ }
+ if (marker.snippet != null) {
+ marker.snippet = null
+ changed = true
+ }
}
// Update marker position if the item changed position
if (marker.position != item.position) {
marker.position = item.position
- if (item.zIndex != null) {
- marker.zIndex = item.zIndex!!
- }
+ changed = true
+ }
+ val itemZIndex = item.zIndex
+ if (itemZIndex != null && marker.zIndex != itemZIndex) {
+ marker.zIndex = itemZIndex
changed = true
}
if (changed && marker.isInfoWindowShown) {
@@ -972,7 +986,7 @@ open class DefaultClusterRenderer @JvmOverloads constructor(
* @param clusterItem ClusterItem which you will obtain its marker
* @return a marker from a ClusterItem or null if it does not exists
*/
- fun getMarker(clusterItem: T): Marker? = mMarkerCache[clusterItem]
+ public open fun getMarker(clusterItem: T): Marker? = mMarkerCache[clusterItem]
/**
* Get the ClusterItem from a marker
@@ -980,7 +994,7 @@ open class DefaultClusterRenderer @JvmOverloads constructor(
* @param marker which you will obtain its ClusterItem
* @return a ClusterItem from a marker or null if it does not exists
*/
- fun getClusterItem(marker: Marker): T? = mMarkerCache[marker]
+ public open fun getClusterItem(marker: Marker): T? = mMarkerCache[marker]
/**
* Get the marker from a Cluster
@@ -988,7 +1002,7 @@ open class DefaultClusterRenderer @JvmOverloads constructor(
* @param cluster which you will obtain its marker
* @return a marker from a cluster or null if it does not exists
*/
- fun getMarker(cluster: Cluster