Denny Weinberg Denny Weinberg - 1 year ago 624
Android Question

Best way to render only the visible cluster items on a google map

I have a map fragment that is handled by google's cluster manager that I configured with my custom cluster renderer

extends DefaultClusterRenderer

I have overritten the functions
to be able to diplay my pictures:

enter image description here

Now If the user zooms in it makes no sense to render the items that are not in the visible area.
It's very easy to find out if the item is in the visible area:

private Boolean isInBounds(LatLng position) {
return map.getProjection().getVisibleRegion().latLngBounds.contains(position);

But if I skip the rendering if the item is not currently visible, it will be empty when the user scrolls on the map.

So who knows how to get an event if the user scrolls and how to re render the items that are not in the visible bounds? (switchen from visible to non visible and vice versa)?

(Sorry for my bad English)

Answer Source

Here is my solution. It works very well and renders only the visible items. I use the camera changed listener to re render the items that became visible now:

private void onBeforeClusterOrClusterItemRendered(final Cluster<MediaItem> cluster, final MediaItem mediaItem, final MarkerOptions markerOption

    // Placeholder. If we do not do this, there will be a default red pin while the picture is loading (async Glide)

    // In visible area?
    Marker marker = cluster == null ? getMarker(mediaItem) : getMarker(cluster);
    Boolean isInBounds = isInBounds(marker != null ? marker.getPosition() : mediaItem.getPosition(), null);

    if(isInBounds) {
        // ...

private Boolean isInBounds(LatLng position, LatLngBounds latLngBounds) {
    return (latLngBounds == null ? mMap.getProjection().getVisibleRegion().latLngBounds : latLngBounds).contains(position);

protected void onBeforeClusterItemRendered(final MediaItem mediaItem, final MarkerOptions markerOptions) {
    onBeforeClusterOrClusterItemRendered(null, mediaItem, markerOptions);

protected void onBeforeClusterRendered(final Cluster<MediaItem> cluster, final MarkerOptions markerOptions) {
    final MediaItem mediaItem = MediaPicker.getBestRated(new ArrayList<>(cluster.getItems()));
    onBeforeClusterOrClusterItemRendered(cluster, mediaItem, markerOptions);


// Re render
mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
    public void onCameraChange(CameraPosition cameraPosition) {
        final LatLngBounds latLngBounds = mMap.getProjection().getVisibleRegion().latLngBounds;

        // Cluster only
        Collection<Marker> clusters = mClusterManager.getClusterMarkerCollection().getMarkers();
        for(Marker marker : clusters) {
            if(isInBounds(marker.getPosition(), latLngBounds))
                onBeforeClusterRendered(getCluster(marker), new MarkerOptions());

        // Marker only
        Collection<Marker> markers = mClusterManager.getMarkerCollection().getMarkers();
        for(Marker marker : markers) {
            if(isInBounds(marker.getPosition(), latLngBounds))
                onBeforeClusterItemRendered(getClusterItem(marker), new MarkerOptions());
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download