hsujm / android-maps-extensions

Automatically exported from code.google.com/p/android-maps-extensions
0 stars 0 forks source link

Getting Displayed Markers #7

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hi, firstly; thanks for your great extension, your clustering library is really 
useful, I had partly built one myself but it was quite buggy.

I've got a bit stuck while trying to access the displayed markers, I can access 
all of the markers, but ideally I was to get the clustered ones.

I'm currently using an onClickListener in a list of places I've got, what I 
want it to do, is when a place is clicked, find where it is clustered and keep 
zooming into that location until it is no longer clustered and then show the 
infowindow.

I've tried doing map.getMarkers(); but it just shows all the markers from my 
result. Is there any way to get the visible (clustered) markers?

If not it would be great to be able to do it. Thanks!

Original issue reported on code.google.com by redbullg...@gmail.com on 12 Apr 2013 at 11:04

GoogleCodeExporter commented 9 years ago
References to cluster markers are not to be kept (I should probably add this 
info in the non-existent documentation). They are reused when possible and the 
same marker can appear on the other side of the globe.

The way clustering works now (when addMarkerDynamically is used) would not give 
a complete list.

What I think would be useful is to give Marker reference to the API and get 
minimal zoom level at which it is no longer clustered.

I'm renaming this issue.

Your code will probably look like this:

float zoom = map.getMinZoomNotClustered(marker);
map.animateCamera(CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 
zoom));

For now I would use some hardcoded zoom level (18 or 20) which works for all 
markers in your app instead of trying to zoom by some value.

There will probably be a use-case where getting a list of visible markers (both 
normal and cluster) is the thing to do, but I can't think of any.

Original comment by maciek.g...@gmail.com on 12 Apr 2013 at 6:47

GoogleCodeExporter commented 9 years ago
Thanks for your reply, I have just done the zoom as you said. However, I've 
just come across another problem which requires the use of the visible markers 
(clustered and normal).

I need to show off the screen points using this technique: 
http://www.google.co.uk/imgres?um=1&safe=off&client=firefox-a&rls=org.mozilla:en
-US:official&hl=en&biw=2560&bih=1331&tbm=isch&tbnid=GvwWyriWASm0iM:&imgrefurl=ht
tp://stackoverflow.com/questions/9526592/calculating-radius-for-off-screen-map-l
ocations&docid=HemvfVzXcTyefM&imgurl=http://i.stack.imgur.com/qObDP.png&w=1000&h
=1000&ei=SaNpUd-dOqm80QWxoYDQBw&zoom=1&ved=1t:3588,r:0,s:0,i:79&iact=rc&dur=723&
page=1&tbnh=187&tbnw=187&start=0&ndsp=54&tx=139&ty=89

Is there a quick way of getting the visible markers or is it too hard? Would I 
have to use addMarkerDynamically(false) and modify the library? Is it possible 
to do simply?

I need to get this feature complete in the next 24 hours unfortunately.

Original comment by redbullg...@gmail.com on 13 Apr 2013 at 6:30

GoogleCodeExporter commented 9 years ago
For a quick hack you can try to merge
LongSparseArray<ClusterMarker> clusters from GridClusteringStrategy
with what DelegatingGoogleMap.getMarkers return.

Just remember to remove from the second list all markers that are also in any 
ClusterMarker.getMarkers().

I think it would require addMarkersDynamically to be turned off (which I don't 
recommend for more than few few hundred markers) to work properly, but you may 
try without it set to false.

I'll keep in mind to add getDisplayedMarkers function, but for proper working 
it will require some refactoring.

Original comment by maciek.g...@gmail.com on 13 Apr 2013 at 6:48

GoogleCodeExporter commented 9 years ago
Thanks for the help, I have been trying a few things, but obviously I don't 
know the code as well as you :)

I'm working on it at the moment, I've got the full list but struggling to 
remove the markers from within the cluster marker.

    @Override
    public List<Marker> getMarkerCluster() {
        LongSparseArray<ClusterMarker> clusters = clusteringStrategy.getMarkerCluster();
        List<Marker> allMarkers = getMarkers();
        for(long i = 0; i< clusters.size();i++){
            if(clusters.get(i)!=null){
                LazyMarker lazy = createdMarkers.get(clusters.get(i).getVirtual());
                DelegatingMarker delegating = markers.get(lazy);
                allMarkers.add(delegating);

                for(int i2 = 0; i2<allMarkers.size();i2++){
                    Log.e("marker in here",""+allMarkers.get(i2).getTitle());
                    for(Marker m2:clusters.get(i).getMarkers()){
                        Log.e("marker in here",""+m2.getTitle());
                        if(m2.getTitle().equals(allMarkers.get(i2).getTitle())){
                            Log.e("marker should be removed from list","it is clustered");
                            allMarkers.remove(i2);
                        }
                    }
                }

            }
        }

        return allMarkers;
    }

I'm still working on it, atm non of the logs are producing anything so I'm 
working my way up to see what is going on.

Thanks again!

Original comment by redbullg...@gmail.com on 13 Apr 2013 at 8:45

GoogleCodeExporter commented 9 years ago
Ok, I just spotted that clusters.get(i) is null every time.

I guess I am not iterating over the LongSparseArray properly, I'll do some 
googling and figure out the best way :)

Original comment by redbullg...@gmail.com on 13 Apr 2013 at 8:49

GoogleCodeExporter commented 9 years ago
Ok, getting somewhere now, I think I've improved my iteration method.

I removed the removing within the loops, and just created a separate array to 
store the markers which need deleting. However, the cluster.getMarkers() seems 
to be returning null each time.

@Override
    public List<Marker> getMarkerCluster() {
        LongSparseArray<ClusterMarker> clusters = clusteringStrategy.getMarkerCluster();
        List<Marker> allMarkers = getMarkers();
        List<Marker> markersToBeRemoved = new ArrayList<Marker>();
        long key = 0;
        for(int i = 0; i< clusters.size();i++){
            key = clusters.keyAt(i);
            ClusterMarker cluster = clusters.get(key);
            if(cluster!=null){
                Log.e("marker is not null",""+cluster.getTitle());
                LazyMarker lazy = createdMarkers.get(cluster.getVirtual());
                    if(cluster.getMarkers()!=null){
                        for(Marker m2:cluster.getMarkers()){
                            markersToBeRemoved.add(m2);
                        }
                        Log.e("The list of markers exists","");
                    }else{
                        Log.e("the list of markers doesn't exist","");
                    }

                if(lazy!=null){
                    DelegatingMarker delegating = markers.get(lazy);
                    if(delegating !=null){
                        allMarkers.add(delegating);
                    }
                }

            }else{
                Log.e("Cluster is null","NULL");
            }
        }

        for(Marker m:markersToBeRemoved){
            Log.e("Removing Marker","");
            allMarkers.remove(m);
        }

        return allMarkers;
    }

Original comment by redbullg...@gmail.com on 13 Apr 2013 at 9:13

GoogleCodeExporter commented 9 years ago
Doh, sorry to keep spamming here, but I noticed the huge mistake I'm making, 
I'm using the createdMarkers.get to retrieve a LazyMarker to then turn it into 
a DelegateMarker, but I guess that it doesn't exist in the created Markers. I 
guess I can cast it to Delegate? I'll try and find a solution.

Original comment by redbullg...@gmail.com on 13 Apr 2013 at 9:17

GoogleCodeExporter commented 9 years ago
You may skip using createdMarkers, but you have to add all ClusterMarkers to 
allMarkers at the end and this should work.

Original comment by maciek.g...@gmail.com on 13 Apr 2013 at 10:04

GoogleCodeExporter commented 9 years ago
Oh, I didn't realise that would work,lol. I started just retrieving the 
LatLngs, but changed to markers. However, using both methods I'm getting this 
exception:

04-13 23:17:14.006: E/AndroidRuntime(15432): 
java.lang.UnsupportedOperationException
04-13 23:17:14.006: E/AndroidRuntime(15432):    at 
pl.mg6.android.maps.extensions.impl.ClusterMarker.getPosition(ClusterMarker.java
:136)

I haven't changed those lines, so it looks like the marker position is null for 
some reason :(

Original comment by redbullg...@gmail.com on 13 Apr 2013 at 10:21

GoogleCodeExporter commented 9 years ago
You cannot get position from ClusterMarker when it is not yet drawn, so you 
need to get all markers inside cluster and calculate position like in the 
ClusterMarker.refresh():

LatLngBounds.Builder builder = LatLngBounds.builder();
for (DelegatingMarker m : markers) {
    builder.include(m.getPosition());
    m.changeVisible(false);
}
LatLng position = calculateCenter(builder.build());

Original comment by maciek.g...@gmail.com on 13 Apr 2013 at 10:27

GoogleCodeExporter commented 9 years ago
Thanks maciek, got it all working! Really Appreciate your help.

Here's it atm:
https://www.dropbox.com/s/qb6arm9uvhlttvq/device-2013-04-13-234132.png

However, when zooming it creates new circles for markers coming out of the 
cluster, but then the unclustered markers suddenly disappear.

Original comment by redbullg...@gmail.com on 13 Apr 2013 at 10:52

GoogleCodeExporter commented 9 years ago
As this conversation grew a bit, I'm going back to your original feature 
request.

From the images I see there is a need to know where are all the markers 
currently displayed.

I'm still not sure what you want to achieve, but the circles look nice.

Original comment by maciek.g...@gmail.com on 14 Apr 2013 at 11:35

GoogleCodeExporter commented 9 years ago
The feature is to show off screen points by using circles (halos). I've almost 
completed it, I'm using the getProjection to getVisibleRegion, then if they are 
not in the region (ie. off screen), it needs to draw a circle.

I've created a boundary similar to this: 
http://www.google.co.uk/imgres?um=1&safe=off&client=firefox-a&rls=org.mozilla:en
-US:official&hl=en&biw=2560&bih=1331&tbm=isch&tbnid=GvwWyriWASm0iM:&imgrefurl=ht
tp://stackoverflow.com/questions/9526592/calculating-radius-for-off-screen-map-l
ocations&docid=HemvfVzXcTyefM&imgurl=http://i.stack.imgur.com/qObDP.png&w=1000&h
=1000&ei=SaNpUd-dOqm80QWxoYDQBw&zoom=1&ved=1t:3588,r:0,s:0,i:79&iact=rc&dur=723&
page=1&tbnh=187&tbnw=187&start=0&ndsp=54&tx=139&ty=89

By converting the visibleRegion to Points, and using the Point.offset to reduce 
the points by 10dp for now. To create an inner boundary such as the image 
above. I just need to calculate the marker's distance from the nearest point at 
the boundary. This is where it's getting a bit complicated. I managed to get it 
working previous by using pythagorous to get the distance from my center point, 
but need to it to go the closest edge of the boundary :( 

Original comment by redbullg...@gmail.com on 14 Apr 2013 at 11:49

GoogleCodeExporter commented 9 years ago
Added in 1.3

Original comment by maciek.g...@gmail.com on 8 May 2013 at 7:14