Skip to content

Commit ac53c33

Browse files
committed
docs: adding sample with Clustering Algorithms
1 parent 0bb1d34 commit ac53c33

File tree

5 files changed

+204
-1
lines changed

5 files changed

+204
-1
lines changed

demo/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@
124124
<activity
125125
android:name=".StreetViewDemoActivity"
126126
android:exported="true" />
127+
<activity
128+
android:name=".ClusterAlgorithmsDemoActivity"
129+
android:exported="true" />
127130

128131
</application>
129132

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
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.CentroidNonHierarchicalDistanceBasedAlgorithm
28+
import com.google.maps.android.clustering.algo.ContinuousZoomEuclideanCentroidAlgorithm
29+
import com.google.maps.android.clustering.algo.GridBasedAlgorithm
30+
import com.google.maps.android.clustering.algo.NonHierarchicalDistanceBasedAlgorithm
31+
import com.google.maps.android.clustering.algo.NonHierarchicalViewBasedAlgorithm
32+
import com.google.maps.android.utils.demo.model.MyItem
33+
import kotlin.random.Random
34+
35+
/**
36+
* A demo activity that showcases the various clustering algorithms
37+
* available in the library.
38+
*/
39+
class ClusterAlgorithmsDemoActivity : BaseDemoActivity() {
40+
41+
private var clusterManager: ClusterManager<MyItem>? = null
42+
private lateinit var mapView: MapView
43+
44+
override fun getLayoutId(): Int {
45+
return R.layout.activity_cluster_algorithms_demo
46+
}
47+
48+
override fun startDemo(isRestore: Boolean) {
49+
// The MapView is needed for the NonHierarchicalViewBasedAlgorithm.
50+
mapView = findViewById(R.id.map)
51+
52+
if (!isRestore) {
53+
map.moveCamera(
54+
CameraUpdateFactory.newLatLngZoom(
55+
LatLng(51.503186, -0.126446),
56+
10f
57+
)
58+
)
59+
}
60+
61+
setupSpinner()
62+
63+
setupClusterer(0)
64+
}
65+
66+
private fun setupSpinner() {
67+
val spinner: Spinner = findViewById(R.id.algorithm_spinner)
68+
val adapter = ArrayAdapter.createFromResource(
69+
this,
70+
R.array.clustering_algorithms,
71+
android.R.layout.simple_spinner_item
72+
)
73+
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
74+
spinner.adapter = adapter
75+
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
76+
override fun onItemSelected(
77+
parent: AdapterView<*>?,
78+
view: View?,
79+
position: Int,
80+
id: Long
81+
) {
82+
setupClusterer(position)
83+
}
84+
85+
override fun onNothingSelected(parent: AdapterView<*>?) {
86+
// Do nothing
87+
}
88+
}
89+
}
90+
91+
/**
92+
* Sets up the ClusterManager with the chosen algorithm and populates it with items.
93+
*/
94+
private fun setupClusterer(algorithmPosition: Int) {
95+
// 1. Clear the map and previous cluster manager
96+
map.clear()
97+
clusterManager = null
98+
99+
// 2. Initialize a new ClusterManager, using getMap() from BaseDemoActivity
100+
clusterManager = ClusterManager(this, map)
101+
102+
// 3. Set the desired algorithm based on the spinner position
103+
when (algorithmPosition) {
104+
1 -> {
105+
clusterManager?.algorithm = GridBasedAlgorithm()
106+
}
107+
108+
2 -> {
109+
clusterManager?.algorithm = NonHierarchicalDistanceBasedAlgorithm()
110+
}
111+
112+
3 -> {
113+
clusterManager?.algorithm = CentroidNonHierarchicalDistanceBasedAlgorithm()
114+
}
115+
116+
4 -> {
117+
clusterManager?.algorithm = NonHierarchicalViewBasedAlgorithm(
118+
mapView.width, mapView.height
119+
)
120+
}
121+
122+
5 -> {
123+
clusterManager?.algorithm = ContinuousZoomEuclideanCentroidAlgorithm()
124+
}
125+
126+
else -> { // Default
127+
128+
}
129+
}
130+
131+
// 4. Point the map's listeners to the ClusterManager
132+
map.setOnCameraIdleListener(clusterManager)
133+
map.setOnMarkerClickListener(clusterManager)
134+
135+
// 5. Add cluster items to the manager
136+
addItems()
137+
138+
// 6. Trigger the initial clustering
139+
clusterManager?.cluster()
140+
}
141+
142+
private fun addItems() {
143+
val items = mutableListOf<MyItem>()
144+
// Add 100 random items in the map region
145+
for (i in 0..99) {
146+
val lat = 51.5145 + (Random.nextDouble() - 0.5) / 2.0
147+
val lng = -0.1245 + (Random.nextDouble() - 0.5) / 2.0
148+
items.add(MyItem(lat, lng, "Marker #$i", "Snippet for marker #$i"))
149+
}
150+
clusterManager?.addItems(items)
151+
}
152+
}

demo/src/main/java/com/google/maps/android/utils/demo/MainActivity.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ protected void onCreate(Bundle savedInstanceState) {
3636

3737
mListView = findViewById(R.id.list);
3838

39-
addDemo("Clustering", ClusteringDemoActivity.class);
4039
addDemo("Advanced Markers Clustering Example", CustomAdvancedMarkerClusteringDemoActivity.class);
40+
addDemo("Cluster Algorithms", ClusterAlgorithmsDemoActivity.class);
41+
addDemo("Clustering", ClusteringDemoActivity.class);
4142
addDemo("Clustering: Custom Look", CustomMarkerClusteringDemoActivity.class);
4243
addDemo("Clustering: Diff", ClusteringDiffDemoActivity.class);
4344
addDemo("Clustering: 2K markers", BigClusteringDemoActivity.class);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:layout_width="match_parent"
4+
android:layout_height="match_parent">
5+
6+
<com.google.android.gms.maps.MapView
7+
android:id="@+id/map"
8+
android:layout_width="match_parent"
9+
android:layout_height="match_parent" />
10+
11+
<Spinner
12+
android:id="@+id/algorithm_spinner"
13+
android:layout_width="wrap_content"
14+
android:layout_height="wrap_content"
15+
android:layout_gravity="top|center_horizontal"
16+
android:layout_marginTop="16dp"
17+
android:background="@android:drawable/btn_dropdown"
18+
android:padding="8dp" />
19+
20+
</FrameLayout>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
Copyright 2025 Google LLC
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
18+
<resources>
19+
<string-array name="clustering_algorithms">
20+
<item>Default</item>
21+
<item>Grid-based</item>
22+
<item>Distance-based</item>
23+
<item>Distance-based (Centroid)</item>
24+
<item>View-based</item>
25+
<item>Continuous Zoom (Centroid)</item>
26+
</string-array>
27+
</resources>

0 commit comments

Comments
 (0)