我在MKMapView上有一个MKCircle。它是用户可拖动的,但如果用户拖动圆圈外的区域,则应该移动地图。
- (IBAction)createPanGestureRecognizer:(id)sender
{
_mapView.scrollEnabled=NO;
_panRecognizer = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:@selector(respondToPanGesture:)];
[_mapView addGestureRecognizer:_panRecognizer];
}
-(void)respondToPanGesture:(UIPanGestureRecognizer*)sender {
static CGPoint originalPoint;
if (sender.state == UIGestureRecognizerStateBegan) {
CGPoint point = [sender locationInView:_mapView];
CLLocationCoordinate2D tapCoordinate = [_mapView convertPoint:point toCoordinateFromView:_mapView];
CLLocation *tapLocation = [[CLLocation alloc] initWithLatitude:tapCoordinate.latitude longitude:tapCoordinate.longitude];
CLLocationCoordinate2D originalCoordinate = [_circle coordinate];
CLLocation *originalLocation = [[CLLocation alloc] initWithLatitude:originalCoordinate.latitude longitude:originalCoordinate.longitude];
if ([tapLocation distanceFromLocation:originalLocation] > [_circle radius]) {
_mapView.scrollEnabled=YES;
_isAllowedToMove=NO;
}
else if ([tapLocation distanceFromLocation:originalLocation] < [_circle radius]) {
originalPoint = [_mapView convertCoordinate:originalCoordinate toPointToView:sender.view];
_isAllowedToMove=YES;
}
}
if (sender.state == UIGestureRecognizerStateChanged) {
if (_isAllowedToMove)
{
CGPoint translation = [sender translationInView:sender.view];
CGPoint newPoint = CGPointMake(originalPoint.x + translation.x, originalPoint.y + translation.y);
CLLocationCoordinate2D newCoordinate = [_mapView convertPoint:newPoint toCoordinateFromView:sender.view];
MKCircle *circle2 = [MKCircle circleWithCenterCoordinate:newCoordinate radius:[_circle radius]];
[_mapView addOverlay:circle2];
[_mapView removeOverlay:_circle];
_circle = circle2;
}
}
if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
_mapView.scrollEnabled=NO;
_isAllowedToMove=NO;
}
}
拖动圆圈可以正常工作,但在尝试拖动地图时,它会保持静止状态。 我的假设是
_mapView.scrollEnabled=YES;
使地图可拖动,但需要启动另一个拖动手势。 如何在不失去移动圆圈的能力的情况下实现这一目标?
答案 0 :(得分:2)
使其成为可以在用户开始在圆圈外拖动时拖动地图(如果用户开始在内拖动,则不拖动地图 ),不要从头开始禁用scrollEnabled
- 保持开启状态(直到拖动启动,我们可以决定是否禁用)。
为了最初离开scrollEnabled
(即让地图自行平移)和添加我们自己的手势识别器,我们需要实现{{1}并返回shouldRecognizeSimultaneouslyWithGestureRecognizer
。
更新的YES
将如下所示:
createPanGestureRecognizer:
然后在我们的手势处理程序中,当手势开始时,根据平移开始的位置(圆圈外部或内部)启用或禁用- (IBAction)createPanGestureRecognizer:(id)sender
{
//_mapView.scrollEnabled=NO; // <-- do NOT disable scrolling here
_panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(respondToPanGesture:)];
_panRecognizer.delegate = self; // <-- to implement shouldRecognize
[_mapView addGestureRecognizer:_panRecognizer];
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
:
scrollEnabled
最后,当手势结束时(以防万一),始终重新启用if ([tapLocation distanceFromLocation:originalLocation] > [_circle radius]) {
_mapView.scrollEnabled=YES;
_isAllowedToMove=NO;
}
else //if ([tapLocation distanceFromLocation:originalLocation] < [_circle radius]) {
//NOTE: It's not really necessary to check if distance is less than radius
// in the ELSE part since in the IF we checked if it's greater-than.
// If we get to the ELSE, we know distance is <= radius.
// Unless for some reason you want to handle the case where
// distance exactly equals radius differently but this is unlikely.
{
originalPoint = [_mapView convertCoordinate:originalCoordinate toPointToView:sender.view];
_mapView.scrollEnabled=NO; // <-- disable scrolling HERE
_isAllowedToMove=YES;
}
当下一个手势开始时,如有必要,它将被重新禁用:
scrollEnabled
请注意,如果允许用户多次调用if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) {
_mapView.scrollEnabled=YES; // <-- enable instead of disable
_isAllowedToMove=NO;
}
,您可能应该在其他地方移动识别器的创建和添加(可能createPanGestureRecognizer:
),否则会将多个实例添加到地图中。
或者,将按钮更改为切换,以便在“移动”模式为ON时,它会从地图中删除手势识别器,而不是创建和添加手势识别器。
答案 1 :(得分:0)
使用 swift 4
更新了答案包括一些更改:
panGesture.maximumNumberOfTouches = 1
以避免检测到像平移手势一样缩放
可用于开始平移手势的活动区域的屏幕点。
private func addPanGestureRecognizer(to map: MKMapView) {
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(respondToPanGesture(_:)))
panGesture.maximumNumberOfTouches = 1
panGesture.delegate = self
map.addGestureRecognizer(panGesture)
}
@objc private func respondToPanGesture(_ sender: UIPanGestureRecognizer) {
guard let map = self.map else {
return
}
let circlePoint = map.convert(startPoint, toPointTo: map) // circle center in View coordinate system
switch sender.state {
case .began:
let point = sender.location(in: map)
// Set touch radius in points (20), not meters to support different map zoom levels
if point.radiusContainsPoint(radius: 20, point: circlePoint) {
// set class property to store initial circle position before start dragging
initialDragPoint = circlePoint
map.isScrollEnabled = false
isDragEnabled = true
}
else {
map.isScrollEnabled = true
isDragEnabled = false
}
case .changed:
if isDragEnabled {
let translation = sender.translation(in: map)
let newPoint = CGPoint(x: initialDragPoint.x + translation.x, y: initialDragPoint.y + translation.y)
let updatedCoordinate = map.convert(newPoint, toCoordinateFrom: map)
let newOverlay = makeCircleOverlay(at: updatedCoordinate)
map.remove(circleOverlay)
map.add(newOverlay)
circleOverlay = newOverlay
}
case .ended, .failed, .cancelled:
map.isScrollEnabled = true
isDragEnabled = false
case .possible:
break
}
}
// MARK: - UIGestureRecognizerDelegate
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}