捏合 MKMapView 时保持中心坐标

发布于 2024-11-07 03:40:24 字数 1629 浏览 1 评论 0原文

如果您在跟踪设备位置时在 Apple 地图应用程序中进行捏合放大/缩小,则捏合手势的“平移”部分将被忽略,蓝色位置指示器将保持固定在屏幕中央。使用普通的 MKMapView 时情况并非如此。

假设我已经有了用户的位置,我怎样才能达到这个效果呢?我尝试在委托的 regionDid/WillChangeAnimated: 方法中重置中心坐标,但它们仅在手势开始和结束时调用。我还尝试添加一个 UIPinchGestureRecognizer 子类,该子类在触摸移动时重置中心坐标,但这会导致渲染故障。


编辑:对于那些感兴趣的人,以下内容对我有用。

// CenterGestureRecognizer.h
@interface CenterGestureRecognizer : UIPinchGestureRecognizer

- (id)initWithMapView:(MKMapView *)mapView;

@end

// CenterGestureRecognizer.m
@interface CenterGestureRecognizer ()

- (void)handlePinchGesture;

@property (nonatomic, assign) MKMapView *mapView;

@end

@implementation CenterGestureRecognizer

- (id)initWithMapView:(MKMapView *)mapView {
  if (mapView == nil) {
    [NSException raise:NSInvalidArgumentException format:@"mapView cannot be nil."];
  }

  if ((self = [super initWithTarget:self action:@selector(handlePinchGesture)])) {
    self.mapView = mapView;
  }

  return self;
}

- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
  return NO;
}

- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
  return NO;
}

- (void)handlePinchGesture {
  CLLocation *location = self.mapView.userLocation.location;
  if (location != nil) {
    [self.mapView setCenterCoordinate:location.coordinate];
  }
}

@synthesize mapView;

@end

然后只需将其添加到您的 MKMapView 中即可:

[self.mapView addGestureRecognizer:[[[CenterGestureRecognizer alloc] initWithMapView:self.mapView] autorelease]];

If you pinch to zoom in/out in Apple's Maps application while tracking the device's location, the "pan" component of the pinch gesture is ignored and the blue location indicator remains fixed in the centre of the screen. This is not the case when using a plain MKMapView.

Assuming I already have the user's location, how could I achieve this effect? I've tried resetting the centre coordinate in the delegate's regionDid/WillChangeAnimated: methods but they're only called at the start and end of the gesture. I also tried adding a UIPinchGestureRecognizer subclass that resets the centre coordinate when the touches move, but this resulted in rendering glitches.


Edit: For those who are interested, the following works for me.

// CenterGestureRecognizer.h
@interface CenterGestureRecognizer : UIPinchGestureRecognizer

- (id)initWithMapView:(MKMapView *)mapView;

@end

// CenterGestureRecognizer.m
@interface CenterGestureRecognizer ()

- (void)handlePinchGesture;

@property (nonatomic, assign) MKMapView *mapView;

@end

@implementation CenterGestureRecognizer

- (id)initWithMapView:(MKMapView *)mapView {
  if (mapView == nil) {
    [NSException raise:NSInvalidArgumentException format:@"mapView cannot be nil."];
  }

  if ((self = [super initWithTarget:self action:@selector(handlePinchGesture)])) {
    self.mapView = mapView;
  }

  return self;
}

- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
  return NO;
}

- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer {
  return NO;
}

- (void)handlePinchGesture {
  CLLocation *location = self.mapView.userLocation.location;
  if (location != nil) {
    [self.mapView setCenterCoordinate:location.coordinate];
  }
}

@synthesize mapView;

@end

Then simply add it to your MKMapView:

[self.mapView addGestureRecognizer:[[[CenterGestureRecognizer alloc] initWithMapView:self.mapView] autorelease]];

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

西瑶 2024-11-14 03:40:24

当用户在实际设备上(而不是模拟器)上捏合屏幕时,它会导致平移和捏合手势 - 捏合包含运动的“缩放”元素,并且平移包含动作的“缩放”元素。包含垂直和水平变化。您需要拦截并阻止平移,这意味着使用 UIPanGestureRecognizer

scrollEnabled 设置为 NO,然后添加 UIPanGestureRecognizer 以重置中心坐标。该组合将阻止单指平移和捏合的平移部分。


编辑以添加更多详细信息,并在查看代码后: touchesMoved:withEvent 在平移已经开始后调用,因此如果您在那里更改 MKMapView 的中心,您将得到你所描述的不稳定的渲染问题。您真正需要的是创建一个带有目标操作的 UIPanGestureRecognizer ,如下所示:

    UIPanGestureRecognizer *pan = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didRecognizePan)] autorelease];
    pan.delegate = self;
    [self.mapView addGestureRecognizer:pan];

...然后向您的控制器添加一个 didRecognizePan 方法,然后执行您的 center-在那里重置。

When the user pinches the screen on the actual device (as opposed to the simulator), it causes both a pan and a pinch gesture – the pinch contains the "zoom" element of the motion, and the pan contains the vertical and horizontal change. You need to be intercepting and blocking the pan, and that means using a UIPanGestureRecognizer.

Set scrollEnabled to NO, then add a UIPanGestureRecognizer to reset the center coordinate. The combination will block both single-finger panning and the pan component of a pinch.


Edit to add more details, and after seeing your code: touchesMoved:withEvent is called after the pan has already begun, so if you change the MKMapView's center there, you'll get the herky-jerky rendering problems you've described. What you really need is to create a UIPanGestureRecognizer with a target-action, like so:

    UIPanGestureRecognizer *pan = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didRecognizePan)] autorelease];
    pan.delegate = self;
    [self.mapView addGestureRecognizer:pan];

...and then add a didRecognizePan method to your controller, and do your center-resetting there.

吻风 2024-11-14 03:40:24

只是猜测,但您是否尝试过在 regionWillChangeAnimated: 开始时将 scrollEnabled 设置为 NO

Just a guess, but have you tried setting scrollEnabled to NO at the start of regionWillChangeAnimated:?

风和你 2024-11-14 03:40:24

也只是一个猜测。在 RegionWillChangeAnimated 开始时:保存当前地图区域,然后使用 self.myMapView.region=theSavedRegion 或类似方法通过 NSTimer 不断更新该区域。然后在调用regionDidChangeAnimated:时使计时器无效。

但是,您可能会遇到一个问题,即 NSTimer 的区域更新会导致再次调用 RegionWillChangeAnimated。

尝试一下,看看会发生什么。

Just a guess as well. At the start of regionWillChangeAnimated: save the current map region, then continuously update the region via an NSTimer using self.myMapView.region=theSavedRegion or similar. Then invalidate the timer when regionDidChangeAnimated: is called.

However, you might have an issue where the region update by the NSTimer causes regionWillChangeAnimated to be called again.

Give it a try and see what happens.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文