Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Offseting the center of the MapFragment for an animation moving both the target lat/lng and the zoom level

I've got a UI that has a MapFragment with a transparent View overlaid on top of it. The map takes up the entire screen, whereas the View is just the left third of the screen. As a result, the default "center" of the map is off. When someone clicks on a marker, I want to center that marker in the wholly visible area of the MapFragment (not the center of the MapFragment itself).

Since this is hard to describe with words, let me use a few pictures. Suppose this is how my UI looks:

Default Map

When the user clicks a marker, I want to both center it and zoom in to see it closer. Without any adjustments, this is what you'll get:

Map with incorrectly centered marker

What I want is for the marker to be centered, but in the space to the right, like this:

Map with correctly centered marker

It's very easy to achieve this feat if you're not changing the zoom level using the map's projection:

// Offset the target latitude/longitude by preset x/y ints LatLng target = new LatLng(latitude, longitude); Projection projection = getMap().getProjection(); Point screenLocation = projection.toScreenLocation(target); screenLocation.x += offsetX; screenLocation.y += offsetY; LatLng offsetTarget = projection.fromScreenLocation(screenLocation);  // Animate to the calculated lat/lng getMap().animateCamera(CameraUpdateFactory.newLatLng(offsetTarget)); 

However, if you're changing the zoom level at the same time, the above calculations don't work (since the lat/lng offsets change at different zoom levels).

Let me run down a list of attempted fixes:

  • Changing the zoom level quickly, doing the calculations, zooming back to the original camera position, then animating. Unfortunately the sudden camera change (even if it's only for a split second) is unfortunately very obvious and I'd like to avoid the flicker.

  • Overlaying two MapFragments on top of each other, having one do the calculations while the other displays. I've found that MapFragments are not really built to be layered on top of each other (there are unavoidable bugs down this route).

  • Modifying the screen location's x/y by the difference in zoom level squared. Theoretically this should work but it's always off by quite a bit (~.1 latitude/longitude, which is enough to be way off).

Is there a way to calculate the offsetTarget even with the zoom level changing?

like image 470
Dan Lew Avatar asked Mar 25 '13 22:03

Dan Lew


1 Answers

The most recent version of the play services library adds a setPadding() function to GoogleMap. This padding will project all camera movements to the offset map center. This doc further explains how map padding behaves.

The question originally asked here can now simply be solved by adding left padding equivalent to the width of the left-side layout.

mMap.setPadding(leftPx, topPx, rightPx, bottomPx); 
like image 171
Kyle Ivey Avatar answered Oct 15 '22 04:10

Kyle Ivey