Android Maps Point Clustering
Last night i got into PointClustering on Android MapView. Saw that there was nothing out for the community so i would like to share.
Groups the geopoints if the projection of them in the mapView is too close. Also renders only the visible poins.
UPDATE
Code reworked from scrach.
Now available at GitHub
- Code Reworked from scratch
- Used GVM clustering algorithm (pretty fast but doesn't position clustered point as good as mine)
- Soon to add previous clustering algorithm too
Android Google maps markerClickListener for clusterItems
Okay, after some more trail and error, I think I've got it sorted out for the most part. All I had to do was to attach a custom DefaultClusterRenderer
to my clusterManager. In the mapfragment I could use onClusterItemClick
for handling the marker clicks. The one problem I still have is that the circles are not all properly rendered when zooming in and out.
private void markGeofencesOnMap() {
new GeofenceAreasRequest().getAllAreas(new GeofenceAreasCallback() {
@Override
public void onAreasLoaded(List<Point> points) {
for (final Point point : points) {
mClusterManager.addItem(point);
}
}
});
}
private void googleMapSettings() {
mClusterManager = new ClusterManager<Point>(getActivity(), googleMap );
// attach custom renderer behaviour
mClusterManager.setRenderer(new OwnPointRendered(getActivity().getApplicationContext(), googleMap, mClusterManager));
mClusterManager.setOnClusterItemClickListener(this);
googleMap.setOnMarkerClickListener(mClusterManager);
googleMap.setOnCameraIdleListener(mClusterManager);
}
@Override
public boolean onClusterItemClick(ClusterItem clusterItem) {
// cast ClusterItem to my Point class to handle marker clicks
Point retailer = (Point) clusterItem;
String retailerId = retailer.getRetailer();
return true;
}
OwnPointRendered.class
public class OwnPointRendered extends DefaultClusterRenderer<Point> {
private final GoogleMap map;
private List<Circle> circleList = new ArrayList<>();
public OwnPointRendered(Context context, GoogleMap map,
ClusterManager<Point> clusterManager) {
super(context, map, clusterManager);
this.map = map;
}
@Override
protected void onBeforeClusterItemRendered(Point item, MarkerOptions markerOptions) {
markerOptions.flat(true);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(195));
drawRadius(item);
super.onBeforeClusterItemRendered(item, markerOptions);
}
@Override
protected void onClusterRendered(Cluster<Point> cluster, Marker marker) {
super.onClusterRendered(cluster, marker);
for (Circle circle : circleList) {
circle.remove();
}
circleList.clear();
}
private void drawRadius(Point point) {
CircleOptions circleOptions = new CircleOptions()
.center(point.getPosition())
.strokeColor(Color.argb(50, 70, 70, 70))
.fillColor(Color.argb(100, 150, 150, 150))
.radius(point.getRadius());
Circle circle = map.addCircle(circleOptions);
circleList.add(circle);
}
google map marker clustering ad custom Infowindow Adapter how to set tag for clusterItem (marker)
I think this tutorial on cluster manager might help you as it has create a custom popup on a marker click which I think is what you are after.
Work with ClusterManager
How to implement Marker Clustering for Google Maps in Xamarin
You want to use the Xamarin.Android
Binding project that includes the android-maps-utils.aar
file.
Note: I have forked an older Github repo that included a binding project and example and updated it to the latest version of android-maps-utils.aar
(v0.4.3
as of this post).
Just clone that repo and copy the entire GoogleMapsUtility
project into your Xamarin.Android
solution and add that to your solution (via Add Existing Project).
Then you can create a Google Map like you would normally, i.e.:
GoogleMapOptions mapOptions = new GoogleMapOptions()
.InvokeMapType(GoogleMap.MapTypeNormal)
.InvokeZoomControlsEnabled(true)
.InvokeMapToolbarEnabled(true)
.InvokeZoomGesturesEnabled(true)
.InvokeRotateGesturesEnabled(true)
.InvokeCompassEnabled(true);
Then you can add your Map markers to the ClusterManager
and let it manage the clustering:
_clusterManager = new ClusterManager(this, _map);
_clusterManager.SetOnClusterClickListener(this);
_clusterManager.SetOnClusterItemClickListener(this);
_map.SetOnCameraChangeListener(_clusterManager);
_map.SetOnMarkerClickListener(_clusterManager);
I modified the original example to create 20 markers in a log. spiral pattern to test the cluster at various zoom levels:
private void AddClusterItems()
{
double lat = 47.59978;
double lng = -122.3346;
var items = new List<ClusterItem>();
// Create a log. spiral of markers to test clustering
for (int i = 0; i < 20; ++i)
{
var t = i * Math.PI * 0.33f;
var r = 0.005 * Math.Exp(0.1 * t);
var x = r * Math.Cos(t);
var y = r * Math.Sin(t);
var item = new ClusterItem(lat + x, lng + y);
items.Add(item);
}
_clusterManager.AddItems(items);
}
Related Topics
Out of Memory Exception Due to Large Bitmap Size
Embed Activity Feed of a Public Facebook Page Without Forcing User to Login/Allow
How to Display Gif in React-Native Android App
How to Switch Automatically Between Viewpager Pages
How to Stop/Cancel Android Countdowntimer
Custom Font for Android Listview
How to Clear Specific Activity from the Stack History
Firebase Sort by Points Depending on Date
Android: Showing Wrong Screen Resolution
Is Deprecated Word the Only Difference Between Fill_Parent and Match_Parent
Room - Livedata Observer Does Not Trigger When Database Is Updated
How to Distinguish Between Move and Click in Ontouchevent()