Skip to content
This repository was archived by the owner on Aug 8, 2023. It is now read-only.

Completion handlers for animated MGLMapView methods #3090

Merged
merged 1 commit into from
Nov 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Known issues:

## iOS master

- `MGLMapView` methods that alter the viewport now accept optional completion handlers. ([#3090](https://github.com/mapbox/mapbox-gl-native/pull/3090))
- Fixed an issue preventing the compass from responding to taps after the compass is moved programmatically. ([#3117](https://github.com/mapbox/mapbox-gl-native/pull/3117))

## iOS 3.0.0
Expand Down
25 changes: 25 additions & 0 deletions include/mbgl/ios/MGLMapView.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,14 @@ IB_DESIGNABLE
* @param animated Specify `YES` if you want the map view to animate scrolling, zooming, and rotating to the new location or `NO` if you want the map to display the new location immediately. */
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated;

/** Changes the center coordinate, zoom level, and direction of the map, calling a completion handler at the end of an optional animation.
* @param centerCoordinate The new center coordinate for the map.
* @param zoomLevel The new zoom level for the map.
* @param direction The new direction for the map, measured in degrees relative to true north.
* @param animated Specify `YES` if you want the map view to animate scrolling, zooming, and rotating to the new location or `NO` if you want the map to display the new location immediately.
* @param completion The block executed after the animation finishes. */
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated completionHandler:(nullable void (^)(void))completion;

/** The coordinate bounds visible in the receiver’s viewport.
*
* Changing the value of this property updates the receiver immediately. If you want to animate the change, call `setVisibleCoordinateBounds:animated:` instead. */
Expand All @@ -157,6 +165,16 @@ IB_DESIGNABLE
* @param animated Specify `YES` to animate the change by smoothly scrolling and zooming or `NO` to immediately display the given bounds. */
- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets animated:(BOOL)animated;

/** Changes the receiver’s viewport to fit all of the given coordinates and optionally some additional padding on each side.
* @param coordinates The coordinates that the viewport will show.
* @param count The number of coordinates. This number must not be greater than the number of elements in `coordinates`.
* @param insets The minimum padding (in screen points) that will be visible around the given coordinate bounds.
* @param direction The direction to rotate the map to, measured in degrees relative to true north.
* @param duration The duration to animate the change in seconds.
* @param function The timing function to animate the change.
* @param completion The block executed after the animation finishes. */
- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion;

/** Sets the visible region so that the map displays the specified annotations.
*
* Calling this method updates the value in the visibleCoordinateBounds property and potentially other properties to reflect the new map region.
Expand Down Expand Up @@ -193,6 +211,13 @@ IB_DESIGNABLE
* @param function A timing function used for the animation. Set this parameter to `nil` for a transition that matches most system animations. If the duration is `0`, this parameter is ignored. */
- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function;

/** Moves the viewpoint to a different location with respect to the map with an optional transition duration and timing function.
* @param camera The new viewpoint.
* @param duration The amount of time, measured in seconds, that the transition animation should take. Specify `0` to jump to the new viewpoint instantaneously.
* @param function A timing function used for the animation. Set this parameter to `nil` for a transition that matches most system animations. If the duration is `0`, this parameter is ignored.
* @param completion The block to execute after the animation finishes. */
- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion;

#pragma mark - Converting Map Coordinates

/** @name Converting Map Coordinates */
Expand Down
4 changes: 4 additions & 0 deletions include/mbgl/map/camera.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/unitbezier.hpp>

#include <functional>

namespace mbgl {

struct CameraOptions {
Expand All @@ -16,6 +18,8 @@ struct CameraOptions {
mapbox::util::optional<double> pitch;
mapbox::util::optional<Duration> duration;
mapbox::util::optional<mbgl::util::UnitBezier> easing;
std::function<void(double)> transitionFrameFn;
std::function<void()> transitionFinishFn;
};

}
Expand Down
52 changes: 46 additions & 6 deletions platform/ios/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1565,14 +1565,18 @@ - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(
[self setCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:self.direction animated:animated];
}

- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated {
[self setCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:direction animated:animated completionHandler:NULL];
}

- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated completionHandler:(nullable void (^)(void))completion
{
self.userTrackingMode = MGLUserTrackingModeNone;

[self _setCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:direction animated:animated];
[self _setCenterCoordinate:centerCoordinate zoomLevel:zoomLevel direction:direction animated:animated completionHandler:completion];
}

- (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated
- (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel direction:(CLLocationDirection)direction animated:(BOOL)animated completionHandler:(nullable void (^)(void))completion
{
_mbglMap->cancelTransitions();

Expand All @@ -1589,6 +1593,17 @@ - (void)_setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:
options.duration = durationInSeconds(duration);
options.easing = MGLUnitBezierForMediaTimingFunction(nil);
}
if (completion)
{
options.transitionFinishFn = [completion]() {
// Must run asynchronously after the transition is completely over.
// Otherwise, a call to -setCenterCoordinate: within the completion
// handler would reenter the completion handler’s caller.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
completion();
});
};
}
_mbglMap->easeTo(options);

[self unrotateIfNeededAnimated:animated];
Expand Down Expand Up @@ -1679,7 +1694,11 @@ - (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUIn
[self setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil];
}

- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(CAMediaTimingFunction *)function
- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function {
[self setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:duration animationTimingFunction:function completionHandler:NULL];
}

- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
{
_mbglMap->cancelTransitions();

Expand All @@ -1702,6 +1721,14 @@ - (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUIn
options.duration = durationInSeconds(duration);
options.easing = MGLUnitBezierForMediaTimingFunction(function);
}
if (completion)
{
options.transitionFinishFn = [completion]() {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
completion();
});
};
}
_mbglMap->easeTo(options);
[self didChangeValueForKey:@"visibleCoordinateBounds"];

Expand Down Expand Up @@ -1815,7 +1842,12 @@ - (void)setCamera:(MGLMapCamera *)camera animated:(BOOL)animated
[self setCamera:camera withDuration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil];
}

- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(CAMediaTimingFunction *)function
- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function
{
[self setCamera:camera withDuration:duration animationTimingFunction:function completionHandler:NULL];
}

- (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
{
_mbglMap->cancelTransitions();

Expand Down Expand Up @@ -1880,6 +1912,14 @@ - (void)setCamera:(MGLMapCamera *)camera withDuration:(NSTimeInterval)duration a
options.duration = durationInSeconds(duration);
options.easing = MGLUnitBezierForMediaTimingFunction(function);
}
if (completion)
{
options.transitionFinishFn = [completion]() {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
completion();
});
};
}
_mbglMap->easeTo(options);
}

Expand Down Expand Up @@ -2675,7 +2715,7 @@ - (void)locationManager:(__unused CLLocationManager *)manager didUpdateLocations
{
// at sufficient detail, just re-center the map; don't zoom
//
[self _setCenterCoordinate:self.userLocation.location.coordinate zoomLevel:self.zoomLevel direction:course animated:YES];
[self _setCenterCoordinate:self.userLocation.location.coordinate zoomLevel:self.zoomLevel direction:course animated:YES completionHandler:NULL];
}
else
{
Expand Down
9 changes: 9 additions & 0 deletions src/mbgl/map/transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ void Transform::_easeTo(const CameraOptions& options, double new_scale, double n
state.angle = angle;
state.pitch = pitch;

if (options.transitionFinishFn) {
options.transitionFinishFn();
}
view.notifyMapChange(MapChangeRegionDidChange);
} else {
view.notifyMapChange(MapChangeRegionWillChangeAnimated);
Expand Down Expand Up @@ -291,6 +294,9 @@ void Transform::_easeTo(const CameraOptions& options, double new_scale, double n
state.pitch = util::interpolate(startP, pitch, t);
// At t = 1.0, a DidChangeAnimated notification should be sent from finish().
if (t < 1.0) {
if (options.transitionFrameFn) {
options.transitionFrameFn(t);
}
view.notifyMapChange(MapChangeRegionIsChanging);
}
return update;
Expand All @@ -299,6 +305,9 @@ void Transform::_easeTo(const CameraOptions& options, double new_scale, double n
state.panning = false;
state.scaling = false;
state.rotating = false;
if (options.transitionFinishFn) {
options.transitionFinishFn();
}
view.notifyMapChange(MapChangeRegionDidChangeAnimated);
}, *easeOptions.duration);
}
Expand Down