5

How can I create two listeners? One is used for the clustering and the other will load new cluster items to the map if no cluster items exists on the map.

       //needed for clustering
       map.setOnCameraChangeListener(mClusterManager);

       // need for loading clusteritems
       map.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
       @Override
       public void onCameraChange(CameraPosition position) {

       // ifMarkesNotInsideMapReload...

I think it's not possible but someone maybe solved this...

One idea is to set a starting position and poll for changes manually.. not cool :-)

I'm using googles cluster library: google cluster

MaciejGórski
  • 22,187
  • 7
  • 70
  • 94

5 Answers5

15

Use the Composite Pattern to create a class that both is a CameraChangeListener and contains CameraChangeListeners, such that it can be set as the sole listener on the map while delegating to multiple children that do the real work.

In this case, you would create a CompositeCameraChangeListener class which implements the CameraChangeListener interface and maintains a list of child listeners it delegates to.

Some pseudocode:

public class CompositeCameraChangeListener implements CameraChangeListener {
    private final List<CameraChangeListener> mListeners = new ArrayList<CameraChangeListener>();

    @Override
    public void onCameraChange(CameraPosition position) {
        for (CameraChangeListener listener in mListeners) {
            listener.onCameraChange(position);
        }
    }

    // Other methods to add, remove listeners
}

Then in your main class:

CompositeCameraChangeListener composite = new CompositeCameraChangeListener();
composite.add(mClusterManager);
composite.add(new CameraChangeListner() { ... });
map.setOnCameraChangeListener(composite);

Now when the CompositeCameraChangeListener's method is invoked, it forwards the call to the other listeners and as far as your app is concerned, you now have two (or more) listeners registered on an object that is designed to only accepted one.

dominicoder
  • 9,338
  • 1
  • 26
  • 32
  • Looks good to have a separate class for handling camera event. Can be handy. – bestKoderEverR Feb 04 '14 at 07:57
  • This is the best solution. Also one that I implemented is to add the listener to this and redirect the event to all the listeners, is kind of similar to this one without the middle class. – Franklin Sep 24 '15 at 16:54
  • I was using your solution but today the setOnCameraChangedListener is deprecated by setOnCameraIdleListener which doesn't accept MultiListener as an argument. Do you know a way around? – KasparTr Aug 31 '16 at 04:41
  • @KasparTr The MultiListener is just an example of a design pattern (Composite) to wrap an existing class into one that can act as a group. Just apply the same pattern to `OnCameraIdleListener` – dominicoder Jan 05 '17 at 06:08
7

I have looked into ClusterManager implementation of AMUtils library and it looks like it calls onCameraChange on your implementation of ClusterRenderer if it also implements OnCameraChangeListener. Simply make it implement that interface.

Relevant parts of the code:

@Override
public void onCameraChange(CameraPosition cameraPosition) {
    if (mRenderer instanceof GoogleMap.OnCameraChangeListener) {
        ((GoogleMap.OnCameraChangeListener) mRenderer).onCameraChange(cameraPosition);
    }

If you are using DefaultClusterRendeder, create a class like:

public class MyClusterRenderer extends DefaultClusterRenderer implements OnCameraChangeListener {
MaciejGórski
  • 22,187
  • 7
  • 70
  • 94
  • Worked fine! Although I have not understood if I need/should create that mRenderer variable..? Because now the clusters wont show up(the first time) unless i zoom in/out a little bit. Can I call on some refresh/re-render function on the map? – bestKoderEverR Feb 04 '14 at 07:55
  • The reason why my cluster dident display was because the mycluster.cluster() re-clustering method was not called on the main thread.. so heads up :-) – bestKoderEverR Feb 06 '14 at 09:24
7

For those struggling on the above pseudo code by TreKing, you can use the code snippet below

public class MultiListener implements GoogleMap.OnCameraChangeListener {
    private List<GoogleMap.OnCameraChangeListener> mListeners = new ArrayList<GoogleMap.OnCameraChangeListener>();

    public void registerListener (GoogleMap.OnCameraChangeListener listener) {
       mListeners.add(listener);
    }

    @Override
    public void onCameraChange(CameraPosition cameraPosition)
    {
        for (GoogleMap.OnCameraChangeListener ccl: mListeners)
        {
            ccl.onCameraChange(cameraPosition);
        }
    }

}

and to add to MultiListener

MultiListener ml = new MultiListener();
ml.registerListener(mClusterManager);
ml.registerListener(new GoogleMap.OnCameraChangeListener() {
               @Override
               public void onCameraChange(CameraPosition cameraPosition) {

                 // code here
               }
           }
    );
map.setOnCameraChangeListener(ml);
Bih Cheng
  • 655
  • 1
  • 13
  • 28
1

include cluster manager onCameraChange in your custom camera change listener

mMap.setOnCameraChangeListener(new OnCameraChangeListener() {
    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
        mClusterManager.onCameraChange(cameraPosition);
        .....
    }
});
rajeswari ratala
  • 650
  • 7
  • 14
0

Since setOnCameraChangeListener is deprecated, it's better to use setOnCameraIdleListener

map.setOnCameraIdleListener {
    //...
    clusterManager.onCameraIdle()
}
Psijic
  • 743
  • 7
  • 20