Android Google Maps v2 Camera Animation
Asked Answered
L

4

8

So im not sure if this is a bug or not yet... might be or I may have missed something.

Anyway so here is the link to Google Maps V2 Camera Controls. https://developers.google.com/maps/documentation/android/views#moving_the_camera

The issue :

Animate to a location already animated to does not call onFinish();

How to replicate:

mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(mLocation.getLatLng(), zoomLevel), 200, new GoogleMap.CancelableCallback() {

                    @Override
                    public void onFinish() {
                        //DO some stuff here!
                    Log.d("animation", "onFinishCalled");

                    }

                    @Override
                    public void onCancel() {
                    Log.d("animation", "onCancel");


                    }
                }); 

This issue may well come about when a user double taps something which called the same animation even if there is a long time between, onFinish will only be called for a successful animation. When the camera is already positioned the onFinish method will not be called!

I could go around doing checks before I do any camera animation but I don't like that as its wasteful.

Any help would be appreciated. Thanks.

Liggitt answered 11/2, 2013 at 16:32 Comment(1)
so far the only viable alternate is to use moveCamera rather than animateCamera but BOOOO to that.Liggitt
L
17

I have the same problem when i want to move camera to the same position, it seems like a bug. Even if old and new position are not the same and the difference is so small , ex: old position.latitude = 94.54284009112, new position.latitude = 94.54284003451, it dosen't work. my solution is to truncate values to get only old_position.latitude = new_position.latitude = 94.54, then i do a test.

There is another problem with moving camera and scroll the map in the same time, for that i disable scroll gesture before moving and enable it on the onFinish() and the onCancel().

public void animateCameraTo(final double lat, final double lng)
{
    _googleMap = getMap();
    CameraPosition camPosition = _googleMap.getCameraPosition();
    if (!((Math.floor(camPosition.target.latitude * 100) / 100) == (Math.floor(lat * 100) / 100) && (Math.floor(camPosition.target.longitude * 100) / 100) == (Math.floor(lng * 100) / 100)))
    {
        _googleMap.getUiSettings().setScrollGesturesEnabled(false);
        _googleMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(lat, lng)), new CancelableCallback()
        {

            @Override
            public void onFinish()
            {
                _googleMap.getUiSettings().setScrollGesturesEnabled(true);

            }

            @Override
            public void onCancel()
            {
                _googleMap.getUiSettings().setAllGesturesEnabled(true);

            }
        });
    }

}

Hope this helps you ;)

Lollipop answered 4/4, 2013 at 15:22 Comment(2)
fair point, good work around, i would go down to at least 4 decimal points though! 2 decimals on lat long is quite a large area stillLiggitt
The rounding of lat/long values to the nearest 100th is seemingly arbitrary and results in different behavior depending on the zoom level. A better solution would incorporate the zoom level for determining the amount to round by.Leaves
T
2

Your should check the pixel distance, not the geo distance:

LatLngBounds myBounds = YOUR_BOUNDS;
LatLngBounds visibleBounds = map.getProjection().getVisibleRegion().latLngBounds;
Point myCenter = map.getProjection().toScreenLocation(myBounds.getCenter());
Point visibleCenter = map.getProjection().toScreenLocation(visibleBounds.getCenter());
int dist = (int) Math.sqrt(Math.pow(myCenter.x - visibleCenter.x, 2) + Math.pow(myCenter.y - visibleCenter.y, 2));
if (dist > YOUR_THRESHOLD) {
    map.animateCamera(CameraUpdateFactory.newLatLngBounds(myBounds, YOUR_PADDING), new GoogleMap.CancelableCallback() {
        @Override
        public void onFinish() {
            // do something
        }

        @Override
        public void onCancel() {
            // do something
        }
    });
} else {
    // do something
}
Tempered answered 7/6, 2014 at 11:28 Comment(0)
S
0

The only solution I have found is doing the wasteful pixel value checks, setting up a bogus (but close) CameraUpdate object and making a nested animateCamera() call using the bogus CameraUpdate first and then calling another cameraUpdate() inside the first onFinish() with the correct CameraUpdate. I installed the Google MAP v2 update today but it didn't help. This is a problem on device rotation for me. I am displaying bounding rectangles and the centroid doesn't change on rotation so the animateCamera() doesn't work and when the device is rotated the selected rectangle may be partially off the screen.

Did you find another solution yet? Thanks

Sisto answered 7/3, 2013 at 7:45 Comment(2)
Nope, iv moved to moveCamera rather than animateCamera which kinda sucks :(Liggitt
The only alternative i can think off (similar to yours) is to check if the LatLng you are animating to is the same as Camera target position before starting the animation. if it is do your onFinished methods. Your rects are likely being null'd when you rotate. Look at this developer.android.com/guide/topics/resources/… might helpLiggitt
D
-1

Here's another workaround:

You do know the animation duration of your map animations. So you can post a delayed runnable with a delay of the animation duration + some offset and there you can check if the finished/canceld listener was called... if not you can fetch it there and call the apropriate listener

Dior answered 26/7, 2013 at 9:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.