@@ -11,7 +11,14 @@ import androidx.compose.runtime.mutableStateOf
1111import androidx.compose.runtime.remember
1212import androidx.compose.runtime.rememberUpdatedState
1313import androidx.compose.runtime.snapshotFlow
14+ import androidx.compose.runtime.CompositionLocalProvider
15+ import androidx.compose.runtime.getValue
16+ import androidx.compose.runtime.mutableStateOf
17+ import androidx.compose.runtime.remember
18+ import androidx.compose.runtime.setValue
19+ import androidx.compose.runtime.staticCompositionLocalOf
1420import androidx.compose.ui.UiComposable
21+ import androidx.compose.ui.geometry.Offset
1522import androidx.compose.ui.platform.LocalContext
1623import com.google.android.gms.maps.GoogleMap
1724import com.google.maps.android.clustering.Cluster
@@ -30,6 +37,43 @@ import com.google.maps.android.compose.rememberReattachClickListenersHandle
3037import kotlinx.coroutines.awaitCancellation
3138import kotlinx.coroutines.launch
3239
40+ /* *
41+ * Properties for a marker in [Clustering].
42+ */
43+ public class ClusteringMarkerProperties {
44+ public var anchor: Offset ? by mutableStateOf(null )
45+ internal set
46+ public var zIndex: Float? by mutableStateOf(null )
47+ internal set
48+ }
49+
50+ /* *
51+ * [CompositionLocal] used to provide [ClusteringMarkerProperties] to the content of a cluster or
52+ * cluster item.
53+ */
54+ public val LocalClusteringMarkerProperties : androidx.compose.runtime.ProvidableCompositionLocal <ClusteringMarkerProperties > =
55+ staticCompositionLocalOf { ClusteringMarkerProperties () }
56+
57+ /* *
58+ * Helper function to specify properties for the marker representing a cluster or cluster item.
59+ *
60+ * @param anchor the anchor for the marker image. If null, the default anchor specified in
61+ * [Clustering] will be used.
62+ * @param zIndex the z-index of the marker. If null, the default z-index specified in [Clustering]
63+ * will be used.
64+ */
65+ @Composable
66+ public fun ClusteringMarkerProperties (
67+ anchor : Offset ? = null,
68+ zIndex : Float? = null,
69+ ) {
70+ val properties = LocalClusteringMarkerProperties .current
71+ SideEffect {
72+ properties.anchor = anchor
73+ properties.zIndex = zIndex
74+ }
75+ }
76+
3377/* *
3478 * Groups many items on a map based on zoom level.
3579 *
@@ -42,6 +86,10 @@ import kotlinx.coroutines.launch
4286 * window of a non-clustered item
4387 * @param clusterContent an optional Composable that is rendered for each [Cluster].
4488 * @param clusterItemContent an optional Composable that is rendered for each non-clustered item.
89+ * @param clusterContentAnchor the anchor for the cluster image
90+ * @param clusterItemContentAnchor the anchor for the non-clustered item image
91+ * @param clusterContentZIndex the z-index of the cluster
92+ * @param clusterItemContentZIndex the z-index of the non-clustered item
4593 * @param clusterRenderer an optional ClusterRenderer that can be used to specify the algorithm used by the rendering.
4694 */
4795@Composable
@@ -85,10 +133,21 @@ public fun <T : ClusterItem> Clustering(
85133 onClusterItemInfoWindowLongClick : (T ) -> Unit = { },
86134 clusterContent : @[UiComposable Composable ] ((Cluster <T >) -> Unit )? = null,
87135 clusterItemContent : @[UiComposable Composable ] ((T ) -> Unit )? = null,
136+ clusterContentAnchor : Offset = Offset (0.5f, 1.0f),
137+ clusterItemContentAnchor : Offset = Offset (0.5f, 1.0f),
138+ clusterContentZIndex : Float = 0.0f,
139+ clusterItemContentZIndex : Float = 0.0f,
88140 clusterRenderer : ClusterRenderer <T >? = null,
89141) {
90- val clusterManager = rememberClusterManager(clusterContent, clusterItemContent, clusterRenderer)
91- ? : return
142+ val clusterManager = rememberClusterManager(
143+ clusterContent,
144+ clusterItemContent,
145+ clusterContentAnchor,
146+ clusterItemContentAnchor,
147+ clusterContentZIndex,
148+ clusterItemContentZIndex,
149+ clusterRenderer
150+ ) ? : return
92151
93152 SideEffect {
94153 clusterManager.setOnClusterClickListener(onClusterClick)
@@ -114,6 +173,10 @@ public fun <T : ClusterItem> Clustering(
114173 * window of a non-clustered item
115174 * @param clusterContent an optional Composable that is rendered for each [Cluster].
116175 * @param clusterItemContent an optional Composable that is rendered for each non-clustered item.
176+ * @param clusterContentAnchor the anchor for the cluster image
177+ * @param clusterItemContentAnchor the anchor for the non-clustered item image
178+ * @param clusterContentZIndex the z-index of the cluster
179+ * @param clusterItemContentZIndex the z-index of the non-clustered item
117180 */
118181@Composable
119182@GoogleMapComposable
@@ -126,6 +189,10 @@ public fun <T : ClusterItem> Clustering(
126189 onClusterItemInfoWindowLongClick : (T ) -> Unit = { },
127190 clusterContent : @[UiComposable Composable ] ((Cluster <T >) -> Unit )? = null,
128191 clusterItemContent : @[UiComposable Composable ] ((T ) -> Unit )? = null,
192+ clusterContentAnchor : Offset = Offset (0.5f, 1.0f),
193+ clusterItemContentAnchor : Offset = Offset (0.5f, 1.0f),
194+ clusterContentZIndex : Float = 0.0f,
195+ clusterItemContentZIndex : Float = 0.0f,
129196) {
130197 Clustering (
131198 items = items,
@@ -135,6 +202,10 @@ public fun <T : ClusterItem> Clustering(
135202 onClusterItemInfoWindowLongClick = onClusterItemInfoWindowLongClick,
136203 clusterContent = clusterContent,
137204 clusterItemContent = clusterItemContent,
205+ clusterContentAnchor = clusterContentAnchor,
206+ clusterItemContentAnchor = clusterItemContentAnchor,
207+ clusterContentZIndex = clusterContentZIndex,
208+ clusterItemContentZIndex = clusterItemContentZIndex,
138209 onClusterManager = null ,
139210 )
140211}
@@ -151,6 +222,10 @@ public fun <T : ClusterItem> Clustering(
151222 * window of a non-clustered item
152223 * @param clusterContent an optional Composable that is rendered for each [Cluster].
153224 * @param clusterItemContent an optional Composable that is rendered for each non-clustered item.
225+ * @param clusterContentAnchor the anchor for the cluster image
226+ * @param clusterItemContentAnchor the anchor for the non-clustered item image
227+ * @param clusterContentZIndex the z-index of the cluster
228+ * @param clusterItemContentZIndex the z-index of the non-clustered item
154229 * @param onClusterManager an optional lambda invoked with the clusterManager as a param when both
155230 * the clusterManager and renderer are set up, allowing callers a customization hook.
156231 */
@@ -165,10 +240,22 @@ public fun <T : ClusterItem> Clustering(
165240 onClusterItemInfoWindowLongClick : (T ) -> Unit = { },
166241 clusterContent : @[UiComposable Composable ] ((Cluster <T >) -> Unit )? = null,
167242 clusterItemContent : @[UiComposable Composable ] ((T ) -> Unit )? = null,
243+ clusterContentAnchor : Offset = Offset (0.5f, 1.0f),
244+ clusterItemContentAnchor : Offset = Offset (0.5f, 1.0f),
245+ clusterContentZIndex : Float = 0.0f,
246+ clusterItemContentZIndex : Float = 0.0f,
168247 onClusterManager : ((ClusterManager <T >) -> Unit )? = null,
169248) {
170249 val clusterManager = rememberClusterManager<T >()
171- val renderer = rememberClusterRenderer(clusterContent, clusterItemContent, clusterManager)
250+ val renderer = rememberClusterRenderer(
251+ clusterContent,
252+ clusterItemContent,
253+ clusterContentAnchor,
254+ clusterItemContentAnchor,
255+ clusterContentZIndex,
256+ clusterItemContentZIndex,
257+ clusterManager
258+ )
172259
173260 SideEffect {
174261 clusterManager ? : return @SideEffect
@@ -266,17 +353,29 @@ public fun <T : ClusterItem> rememberClusterRenderer(
266353 *
267354 * @param clusterContent an optional Composable that is rendered for each [Cluster].
268355 * @param clusterItemContent an optional Composable that is rendered for each non-clustered item.
356+ * @param clusterContentAnchor the anchor for the cluster image
357+ * @param clusterItemContentAnchor the anchor for the non-clustered item image
358+ * @param clusterContentZIndex the z-index of the cluster
359+ * @param clusterItemContentZIndex the z-index of the non-clustered item
269360 */
270361@Composable
271362@GoogleMapComposable
272363@MapsComposeExperimentalApi
273364public fun <T : ClusterItem > rememberClusterRenderer (
274365 clusterContent : @Composable ((Cluster <T >) -> Unit )? ,
275366 clusterItemContent : @Composable ((T ) -> Unit )? ,
367+ clusterContentAnchor : Offset = Offset (0.5f, 1.0f),
368+ clusterItemContentAnchor : Offset = Offset (0.5f, 1.0f),
369+ clusterContentZIndex : Float = 0.0f,
370+ clusterItemContentZIndex : Float = 0.0f,
276371 clusterManager : ClusterManager <T >? ,
277372): ClusterRenderer <T >? {
278373 val clusterContentState = rememberUpdatedState(clusterContent)
279374 val clusterItemContentState = rememberUpdatedState(clusterItemContent)
375+ val clusterContentAnchorState = rememberUpdatedState(clusterContentAnchor)
376+ val clusterItemContentAnchorState = rememberUpdatedState(clusterItemContentAnchor)
377+ val clusterContentZIndexState = rememberUpdatedState(clusterContentZIndex)
378+ val clusterItemContentZIndexState = rememberUpdatedState(clusterItemContentZIndex)
280379 val context = LocalContext .current
281380 val viewRendererState = rememberUpdatedState(rememberComposeUiViewRenderer())
282381 val clusterRendererState: MutableState <ClusterRenderer <T >? > = remember { mutableStateOf(null ) }
@@ -291,6 +390,10 @@ public fun <T : ClusterItem> rememberClusterRenderer(
291390 viewRendererState,
292391 clusterContentState,
293392 clusterItemContentState,
393+ clusterContentAnchorState,
394+ clusterItemContentAnchorState,
395+ clusterContentZIndexState,
396+ clusterItemContentZIndexState,
294397 )
295398 clusterRendererState.value = renderer
296399 awaitCancellation()
@@ -315,10 +418,18 @@ public fun <T : ClusterItem> rememberClusterManager(): ClusterManager<T>? {
315418private fun <T : ClusterItem > rememberClusterManager (
316419 clusterContent : @Composable ((Cluster <T >) -> Unit )? ,
317420 clusterItemContent : @Composable ((T ) -> Unit )? ,
421+ clusterContentAnchor : Offset = Offset (0.5f, 1.0f),
422+ clusterItemContentAnchor : Offset = Offset (0.5f, 1.0f),
423+ clusterContentZIndex : Float = 0.0f,
424+ clusterItemContentZIndex : Float = 0.0f,
318425 clusterRenderer : ClusterRenderer <T >? = null,
319426): ClusterManager <T >? {
320427 val clusterContentState = rememberUpdatedState(clusterContent)
321428 val clusterItemContentState = rememberUpdatedState(clusterItemContent)
429+ val clusterContentAnchorState = rememberUpdatedState(clusterContentAnchor)
430+ val clusterItemContentAnchorState = rememberUpdatedState(clusterItemContentAnchor)
431+ val clusterContentZIndexState = rememberUpdatedState(clusterContentZIndex)
432+ val clusterItemContentZIndexState = rememberUpdatedState(clusterItemContentZIndex)
322433 val context = LocalContext .current
323434 val viewRendererState = rememberUpdatedState(rememberComposeUiViewRenderer())
324435 val clusterManagerState: MutableState <ClusterManager <T >? > = remember { mutableStateOf(null ) }
@@ -332,14 +443,18 @@ private fun <T : ClusterItem> rememberClusterManager(
332443 .collect { hasCustomContent ->
333444 val renderer = clusterRenderer
334445 ? : if (hasCustomContent) {
335- ComposeUiClusterRenderer (
446+ ComposeUiClusterRenderer < T > (
336447 context,
337448 scope = this ,
338449 map,
339450 clusterManager,
340451 viewRendererState,
341452 clusterContentState,
342453 clusterItemContentState,
454+ clusterContentAnchorState,
455+ clusterItemContentAnchorState,
456+ clusterContentZIndexState,
457+ clusterItemContentZIndexState,
343458 )
344459 } else {
345460 DefaultClusterRenderer (context, map, clusterManager)
0 commit comments