[ios] Fixed KVO for annotation view center

Always reposition the annotation view using the standard -setCenter: setter, fixing KVO compliance for the center key path and making the view behave more like a normal view. -setCenter: updates the transform by side effect, and it always starts from the identity transform to avoid surprises. To apply a custom transform on an annotation view, make sure to apply it in -mapView:didFinishLoadingFrame:fullyRendered: based on the existing transform.
This commit is contained in:
Minh Nguyễn
2016-06-05 13:23:58 -07:00
committed by Minh Nguyễn
parent 649b068270
commit bb4606b53d
3 changed files with 33 additions and 27 deletions

View File

@@ -54,31 +54,46 @@
[self didChangeValueForKey:@"selected"];
}
- (void)setCenter:(CGPoint)center
- (CGPoint)center
{
[self setCenter:center pitch:self.mapView.camera.pitch];
CGPoint center = super.center;
center.x -= _centerOffset.dx;
center.y -= _centerOffset.dy;
return center;
}
- (void)setCenter:(CGPoint)center pitch:(CGFloat)pitch
- (void)setCenter:(CGPoint)center
{
center.x += _centerOffset.dx;
center.y += _centerOffset.dy;
[super setCenter:center];
// Omit applying a new transformation while the view is being dragged.
if (self.dragState == MGLAnnotationViewDragStateDragging) {
return;
}
if (self.scalesWithViewingDistance)
super.center = center;
[self updateTransform];
}
- (void)setScalesWithViewingDistance:(BOOL)scalesWithViewingDistance
{
if (_scalesWithViewingDistance != scalesWithViewingDistance)
{
[self updateScaleForPitch:pitch];
_scalesWithViewingDistance = scalesWithViewingDistance;
[self updateTransform];
}
}
- (void)updateScaleForPitch:(CGFloat)pitch
- (void)updateTransform
{
// Omit applying a new transformation while the view is being dragged.
if (self.dragState == MGLAnnotationViewDragStateDragging)
{
return;
}
self.layer.transform = CATransform3DIdentity;
if ( ! self.scalesWithViewingDistance)
{
return;
}
CGFloat superviewHeight = CGRectGetHeight(self.superview.frame);
if (superviewHeight > 0.0) {
// Find the maximum amount of scale reduction to apply as the view's center moves from the top
@@ -93,7 +108,7 @@
// as the map view will allow). The map view's maximum pitch is defined in `mbgl::util::PITCH_MAX`.
// Since it is possible for the map view to report a pitch less than 0 due to the nature of
// how the gesture information is captured, the value is guarded with MAX.
CGFloat pitchIntensity = MAX(pitch, 0) / MGLDegreesFromRadians(mbgl::util::PITCH_MAX);
CGFloat pitchIntensity = MAX(self.mapView.camera.pitch, 0) / MGLDegreesFromRadians(mbgl::util::PITCH_MAX);
// The pitch adjusted scale is the inverse proportion of the maximum possible scale reduction
// multiplied by the pitch intensity. For example, if the maximum scale reduction is 75% and the
@@ -174,8 +189,7 @@
- (void)handlePan:(UIPanGestureRecognizer *)sender
{
CGPoint center = [sender locationInView:sender.view.superview];
[self setCenter:center pitch:self.mapView.camera.pitch];
self.center = [sender locationInView:sender.view.superview];
if (sender.state == UIGestureRecognizerStateEnded) {
self.dragState = MGLAnnotationViewDragStateNone;
@@ -203,11 +217,7 @@
{
if ([self.mapView.delegate respondsToSelector:@selector(mapView:didDragAnnotationView:toCoordinate:)])
{
CGPoint offsetAdjustedCenter = self.center;
offsetAdjustedCenter.x -= self.centerOffset.dx;
offsetAdjustedCenter.y -= self.centerOffset.dy;
CLLocationCoordinate2D coordinate = [self.mapView convertPoint:offsetAdjustedCenter toCoordinateFromView:self.mapView];
CLLocationCoordinate2D coordinate = [self.mapView convertPoint:self.center toCoordinateFromView:self.mapView];
[self.mapView.delegate mapView:self.mapView didDragAnnotationView:self toCoordinate:coordinate];
}
}

View File

@@ -11,8 +11,6 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readwrite, nullable) id <MGLAnnotation> annotation;
@property (nonatomic, weak) MGLMapView *mapView;
- (void)setCenter:(CGPoint)center pitch:(CGFloat)pitch;
@end
NS_ASSUME_NONNULL_END

View File

@@ -4576,8 +4576,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
[self.glView addSubview:annotationView];
}
CGPoint center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
[annotationView setCenter:center pitch:self.camera.pitch];
annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
annotationView.mapView = self;
annotationContext.annotationView = annotationView;
}
@@ -4590,8 +4589,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
}
else
{
CGPoint center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
[annotationView setCenter:center pitch:self.camera.pitch];
annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
}
}
}