Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to focus on location on Google maps, considering a view is on top of it?

Background

Suppose I have a Google maps view, and another view on top of it, that covers a part of it, hiding some content of the map.

The problem

I need to make the "camera" of the map, to focus and have a marker on a coordinate , yet let it all be in the middle of the visible part of the map.

Something like this:

enter image description here

The original code was focusing on (about) the center of the entire screen, making the marker almost invisible (as the bottom view covers it).

Thing is, I can't find the proper way to set the correct value to the Y coordinate of the map itself (meaning latitude).

What I've tried

I tried, given the height of the bottom view, and the coordinate that I've put the marker on, to calculate the delta (yet of course not change the marker itself) :

    final float neededZoom = 6.5f;
    int bottomViewHeight = bottomView.getHeight();
    LatLng posToFocusOn = ...;
    final Point point = mMap.getProjection().toScreenLocation(posToFocusOn);
    final float curZoom = mMap.getCameraPosition().zoom;
    point.y += bottomViewHeight * curZoom / neededZoom;
    posToFocusOn = mMap.getProjection().fromScreenLocation(point);
    final CameraUpdate cameraPosition = CameraUpdateFactory.newCameraPosition(new Builder().target(posToFocusOn).zoom(neededZoom).build());

Sadly, this focuses way above the marker.

The question

What's wrong with what I wrote? What can I do to fix it?

like image 971
android developer Avatar asked Jun 23 '16 09:06

android developer


People also ask

Can you change the view on Google Maps?

Face North: At the bottom, tap the compass. Tilt the map: With 2 fingers, touch and hold the map, then move your fingers up and down the screen. Rotate the map: With 2 fingers, touch and hold the map, then move your fingers around each other on the screen.

How do you focus on Google Maps?

On your computer, open Google Maps. On your keyboard, press Tab until the map is in focus.

How do I keep Google Maps always on top?

For me (Android 6 on a Sony phone), "screen pinning" does this, with no need for third party apps. The option for me is in "Settings", "Security", "Screen pinning", which you set to "on". You pin an app by swiping up on it from the overview list, then clicking the "pin" icon which will appear.


2 Answers

ok, I've found a workaround, which I think works on all devices (tested on 3, each with a different screen resolution and size) :

I've measured how many pixels (and then converted to DP) a change of one degree has on the marker itself.

From this, I measured the height of each view, and calculated the delta needed to move the camera.

In my case, it's this way (supposing the zoom is 6.5f) :

    //measured as 223 pixels on Nexus 5, which has xxhdpi, so divide by 3
    final float oneDegreeInPixels = convertDpToPixels( 223.0f / 3.0f);
    final float mapViewCenter = mapViewHeight / 2.0f;
    final float bottomViewHeight = ...;
    final float posToFocusInPixelsFromTop = (mapViewHeight - bottomViewHeight) / 2.0f ;// can optionally add the height of the view on the top area
    final float deltaLatDegreesToMove = (mapViewCenter - posToFocusInPixelsFromTop) / oneDegreeInPixels;
    LatLng posToFocusOn = new LatLng(latitude - deltaLatDegreesToMove, longitude);
    final CameraUpdate cameraPosition = CameraUpdateFactory.newCameraPosition(new Builder().target(posToFocusOn).zoom(neededZoom).build());

And it worked.

I wonder if it can be adjusted to support any value of zoom.

like image 118
android developer Avatar answered Oct 01 '22 16:10

android developer


Your code is almost right, but it goes above the marker because you are taking into account bottomViewHeight when computing point.y instead of bottomViewHeight/2 (When your view's size is 200px, you only need to displace the map 100px to recenter it):

point.y += (bottomViewHeight / 2) * curZoom / neededZoom;

Update:

This is a more general approach taht takes into account the map bounds and calculates a new map bounds according to the height of your bottomView. This is zoom independent.

public void recenter() {
    LatLngBounds mapBounds = mMap.getProjection().getVisibleRegion().latLngBounds;
    Point nothEastPoint = mMap.getProjection().toScreenLocation(mapBounds.northeast);
    Point souhWestPoint = mMap.getProjection().toScreenLocation(mapBounds.southwest);

    Point newNorthEast = new Point(nothEastPoint.x, nothEastPoint.y + bottomView.getHeight() / 2);
    Point newSouhWestPoint = new Point(souhWestPoint.x, souhWestPoint.y + bottomView.getHeight() / 2);

    LatLngBounds newBounds = LatLngBounds.builder()
            .include(mMap.getProjection().fromScreenLocation(newNorthEast))
            .include(mMap.getProjection().fromScreenLocation(newSouhWestPoint))
            .build();

    mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(newBounds, 0));
}

Note that each time you call recenter() the map will move.

like image 38
antonio Avatar answered Oct 01 '22 16:10

antonio