iOS GoogleMaps SDK - animateToCameraPosition animation finished handler?
Asked Answered
B

5

13

Currently I am using the GoogleMaps SDK for iOS for various operations. When calling

[self.googleMapsView animateToCameraPosition:[GMSCameraPosition 
                            cameraWithLatitude:LATITUDE
                                     longitude:LONGITUDE
                                          zoom:ZOOM]];

is there a completion handler to determine wether the animation finished or not?

Of course I get with the GMSMapViewDelegate updates about the cameraPosition but how should I check if the animation finished?

- (void)mapView:(GMSMapView *)mapView 
didChangeCameraPosition:(GMSCameraPosition *)position;
Bruns answered 4/3, 2013 at 14:36 Comment(2)
On related: didChangeCameraPosition also is called multiple (10+) times on simple swipe or pinch gestures instead of just being called once the map has been changed.Swacked
Im suffering with this because I'm updating a textfield whenever I call this delegate method with the new address retrieved from google maps API, and it's been called so many times that I get OVER_QUERY_LIMITSalty
S
19

For the reference of future readers of this post, Google Maps SDK for iOS Version 1.4.0 released in July 2013 has added a new delegate method mapView:idleAtCameraPosition: which will be fired at the end of any camera movement - be it programatic animation like in this question or user triggered movements.

Simpkins answered 27/7, 2013 at 12:4 Comment(0)
C
9

This might work (I haven't tried it):

[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat: 1.0f] forKey:kCATransactionAnimationDuration];
[self.googleMapsView animateToCameraPosition:[GMSCameraPosition 
                        cameraWithLatitude:LATITUDE
                                 longitude:LONGITUDE
                                      zoom:ZOOM]];
[CATransaction setCompletionBlock:^{
    // ... whatever you want to do when the animation is complete
}];
[CATransaction commit];

Basically, this creates an animation transaction that animates your camera movement (change the value for numberWithFloat: to change the speed) and you set your own completion block stating what you want to do when the animation is over. [CATransaction commit] is what fires the animation off.

Note: this answer partially based off this answer.

Couvade answered 19/5, 2013 at 8:59 Comment(3)
sorry but how we can use this code?I don't understand where I need to put it!Preset
This did not work for me. The completion block is called before the animation endsBursiform
For this to work, the completion block needs to be defined before the animation code.Riebling
K
3

I came across the issue of google's animation methods lacking completion handlers recently.
The best solution I've found so far is to attach my own completion handler via CATransation API.

private func attachCompletionHandlerToGoogleAnimations(@noescape animations: () -> Void, #completion: (() -> Void)!) {
    CATransaction.begin()
    CATransaction.setCompletionBlock(completion)
    animations()
    CATransaction.commit()
}

Example usage:

attachCompletionHandlerToGoogleAnimations({
    googleMapView.animateToLocation(coordinate)
}) {
    println("camera moved to location \(coordinate)")
}
Kurtzman answered 2/6, 2015 at 14:40 Comment(0)
D
2

I don't believe there is, however...

A method that has worked well for me so far is to set a timer to fire (very) shortly after the location stops updating:

- (void)mapView:(GMSMapView*)mapView didChangeCameraPosition:(GMSCameraPosition*)position {
  // _panTimer is an instance variable of the delegate.
  [_panTimer invalidate];
  _panTimer = [NSTimer timerWithTimeInterval:0.2
                                      target:self
                                    selector:@selector(_mapHasStoppedMoving)
                                    userInfo:nil
                                     repeats:NO];
  [[NSRunLoop currentRunLoop] addTimer:_panTimer forMode:NSDefaultRunLoopMode];
}
Dorsad answered 11/3, 2013 at 0:42 Comment(3)
but if the user is just making a small change? the timer wouldn't be invalidated and the mapHasStoppedMoving wouldn't be calledSalty
Any change would cause the method to eventually be fired. The _panTimer is an ivar of the class that manages the GMSMapView, otherwise known as the mapView's delegate.Dorsad
that's how I do it in 1.1.2. there is an enhancement request on the GMS issue tracker for a delegate method AFTER the changeDepredation
P
1

SWIFT version example:

let vancouver = CLLocationCoordinate2D(latitude: 49.26, longitude: -123.11)
let calgary = CLLocationCoordinate2D(latitude: 51.05,longitude: -114.05)
let bounds = GMSCoordinateBounds(coordinate: vancouver, coordinate: calgary)
let cameraPosition = GMSCameraUpdate.fit(bounds)

CATransaction.begin()
CATransaction.setValue(1.0/*duration in seconds*/, forKey: kCATransactionAnimationDuration)
CATransaction.setCompletionBlock({
    print("animation complete, do whatever you want here")
})
mMapView.animate(with: cameraPosition)
CATransaction.commit()
Posy answered 12/12, 2018 at 22:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.