Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 onBeforeClusterItemRendered and onBeforeClusterRendered 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)

like image 757
Denny Weinberg Avatar asked Mar 12 '23 13:03

Denny Weinberg


1 Answers

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
    if(!isAdded())
        return;

    // 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);
}

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

@Override
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() {
    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
        mClusterManager.onCameraChange(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());
        }

        // Cluster item only
        Collection<Marker> markers = mClusterManager.getMarkerCollection().getMarkers();
        for(Marker marker : markers) {
            if(isInBounds(marker.getPosition(), latLngBounds))
                onBeforeClusterItemRendered(getClusterItem(marker), new MarkerOptions());
        }
    }
});
like image 74
Denny Weinberg Avatar answered May 05 '23 00:05

Denny Weinberg