1
+ /*
2
+ * Copyright 2025 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ package com.google.maps.android.utils.demo
18
+
19
+ import android.view.View
20
+ import android.widget.AdapterView
21
+ import android.widget.ArrayAdapter
22
+ import android.widget.Spinner
23
+ import com.google.android.gms.maps.CameraUpdateFactory
24
+ import com.google.android.gms.maps.MapView
25
+ import com.google.android.gms.maps.model.LatLng
26
+ import com.google.maps.android.clustering.ClusterManager
27
+ import com.google.maps.android.clustering.algo.AbstractAlgorithm
28
+ import com.google.maps.android.clustering.algo.CentroidNonHierarchicalDistanceBasedAlgorithm
29
+ import com.google.maps.android.clustering.algo.ContinuousZoomEuclideanCentroidAlgorithm
30
+ import com.google.maps.android.clustering.algo.GridBasedAlgorithm
31
+ import com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm
32
+ import com.google.maps.android.clustering.algo.NonHierarchicalViewBasedAlgorithm
33
+ import com.google.maps.android.utils.demo.model.MyItem
34
+ import kotlin.random.Random
35
+
36
+ /* *
37
+ * A demo activity that showcases the various clustering algorithms
38
+ * available in the library.
39
+ */
40
+ class ClusterAlgorithmsDemoActivity : BaseDemoActivity () {
41
+
42
+ private var clusterManager: ClusterManager <MyItem >? = null
43
+ private lateinit var mapView: MapView
44
+
45
+ override fun getLayoutId (): Int {
46
+ return R .layout.activity_cluster_algorithms_demo
47
+ }
48
+
49
+ override fun startDemo (isRestore : Boolean ) {
50
+
51
+ if (! isRestore) {
52
+ map.moveCamera(
53
+ CameraUpdateFactory .newLatLngZoom(
54
+ LatLng (51.503186 , - 0.126446 ), 10f
55
+ )
56
+ )
57
+ }
58
+
59
+ setupSpinner()
60
+
61
+ setupClusterer(0 )
62
+ }
63
+
64
+ private fun setupSpinner () {
65
+ val spinner: Spinner = findViewById(R .id.algorithm_spinner)
66
+ val adapter = ArrayAdapter .createFromResource(
67
+ this , R .array.clustering_algorithms, android.R .layout.simple_spinner_item
68
+ )
69
+ adapter.setDropDownViewResource(android.R .layout.simple_spinner_dropdown_item)
70
+ spinner.adapter = adapter
71
+ spinner.onItemSelectedListener = object : AdapterView .OnItemSelectedListener {
72
+ override fun onItemSelected (
73
+ parent : AdapterView <* >? , view : View ? , position : Int , id : Long
74
+ ) {
75
+ setupClusterer(position)
76
+ }
77
+
78
+ override fun onNothingSelected (parent : AdapterView <* >? ) {
79
+ // Do nothing
80
+ }
81
+ }
82
+ }
83
+
84
+ /* *
85
+ * Sets up the ClusterManager with the chosen algorithm and populates it with items.
86
+ */
87
+ private fun setupClusterer (algorithmPosition : Int ) {
88
+ // 1. Clear the map and previous cluster manager
89
+ map.clear()
90
+
91
+ // 2. Initialize a new ClusterManager, using getMap() from BaseDemoActivity
92
+ clusterManager = ClusterManager (this , map)
93
+
94
+ // 3. Set the desired algorithm based on the spinner position
95
+ clusterManager?.algorithm = when (algorithmPosition) {
96
+ 1 -> GridBasedAlgorithm ()
97
+ 2 -> NonHierarchicalDistanceBasedAlgorithm ()
98
+ 3 -> CentroidNonHierarchicalDistanceBasedAlgorithm ()
99
+ 4 -> NonHierarchicalViewBasedAlgorithm (mapView.width, mapView.height)
100
+ 5 -> ContinuousZoomEuclideanCentroidAlgorithm ()
101
+ else -> error(" Unsupported algorithm position: $algorithmPosition " )
102
+ }
103
+
104
+ // 4. Point the map's listeners to the ClusterManager
105
+ map.setOnCameraIdleListener(clusterManager)
106
+ map.setOnMarkerClickListener(clusterManager)
107
+
108
+ // 5. Generate and add cluster items to the manager
109
+ val items = generateItems()
110
+ clusterManager?.addItems(items)
111
+
112
+ // 6. Trigger the initial clustering
113
+ clusterManager?.cluster()
114
+ }
115
+
116
+ private fun generateItems (): List <MyItem > {
117
+ val items = mutableListOf<MyItem >()
118
+ // Add 100 random items in the map region
119
+ for (i in 0 until 100 ) {
120
+ val lat = 51.5145 + (Random .nextDouble() - 0.5 ) / 2.0
121
+ val lng = - 0.1245 + (Random .nextDouble() - 0.5 ) / 2.0
122
+ items.add(MyItem (lat, lng, " Marker #$i " , " Snippet for marker #$i " ))
123
+ }
124
+ return items
125
+ }
126
+ }
0 commit comments