35

I have a small android problem (google maps v2 api)

This is my code:

GoogleMaps mMap;
Marker marker =  mMap.addMarker(new MarkerOptions().position(new LatLng(20, 20)));

I am trying to find a way to get the current screen coordinates (x,y) for this marker object.

Perhaps someone has an idea? I tried getProjection but it does not see to work. Thanks! :)

Kara
  • 6,115
  • 16
  • 50
  • 57
mangotasche
  • 731
  • 2
  • 7
  • 14

2 Answers2

89

Yes, use Projection class. More specifically:

  1. Get Projection of the map:

    Projection projection = map.getProjection();
    
  2. Get location of your marker:

    LatLng markerLocation = marker.getPosition();
    
  3. Pass location to the Projection.toScreenLocation() method:

    Point screenPosition = projection.toScreenLocation(markerLocation);
    

That's all. Now screenPosition will contain the position of the marker relative to the top-left corner of the whole Map container :)

Edit

Remember, that the Projection object will only return valid values after the map has passed the layout process (i.e. it has valid width and height set). You're probably getting (0, 0) because you're trying to access position of the markers too soon, like in this scenario:

  1. Create the map from layout XML file by inflating it
  2. Initialize the map.
  3. Add markers to the map.
  4. Query Projection of the map for marker positions on the screen.

This is not a good idea since the the map doesn't have valid width and height set. You should wait until these values are valid. One of the solutions is attaching a OnGlobalLayoutListener to the map view and waiting for layout process to settle. Do it after inflating the layout and initializing the map - for example in onCreate():

// map is the GoogleMap object
// marker is Marker object
// ! here, map.getProjection().toScreenLocation(marker.getPosition()) will return (0, 0)
// R.id.map is the ID of the MapFragment in the layout XML file
View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView();
if (mapView.getViewTreeObserver().isAlive()) {
    mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // remove the listener
            // ! before Jelly Bean:
            mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            // ! for Jelly Bean and later:
            //mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            // set map viewport
            // CENTER is LatLng object with the center of the map
            map.moveCamera(CameraUpdateFactory.newLatLngZoom(CENTER, 15));
            // ! you can query Projection object here
            Point markerScreenPosition = map.getProjection().toScreenLocation(marker.getPosition());
            // ! example output in my test code: (356, 483)
            System.out.println(markerScreenPosition);
        }
    });
}

Please read through the comments for additional informations.

andr
  • 15,970
  • 10
  • 45
  • 59
  • Thats my problem too, it always says 0,0. The current location of my map is the default on 0,0 latlng. Marker is on 20,20, so it should give me on 800x400 px something about 300x 100y. – mangotasche Jan 21 '13 at 10:50
  • @andr Thank you so much, it works like a charm. You were right about the layout process, it was the problem. – mangotasche Jan 22 '13 at 00:39
  • Sometimes `getViewTreeObserver` is not alive at listener even if is alive at before `addOnGlobalLayoutListener`. – Idemax Oct 25 '13 at 14:02
  • 1
    @IdemaxGreen assuming you are doing it all in UI thread, if the observer is not alive it means that the view has been incorporated or moved in the view hierarchy. this might be caused by you (by reparenting the map view) or by some logic in UI framework - for example `Fragment` related stuff like transactions or things with content that might be swapped (more or less a `ViewPager`). A simple resolution might be to query the map view in a `Runnable` which you schedule for execution by the map view using: `mapView.post(new Runnable{ public void run() {/* your listener code here */}});` – andr Oct 25 '13 at 17:39
  • `onGlobalLayout` is never called for me ! – alizeyn Oct 18 '17 at 08:29
0

toScreenLocation appears to have been replaced by fromLatLngToPoint gmaps api doc for projection: https://developers.google.com/maps/documentation/javascript/reference/image-overlay#Projection