捏合 MKMapView 时保持中心坐标
如果您在跟踪设备位置时在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当用户在实际设备上(而不是模拟器)上捏合屏幕时,它会导致平移和捏合手势 - 捏合包含运动的“缩放”元素,并且平移包含动作的“缩放”元素。包含垂直和水平变化。您需要拦截并阻止平移,这意味着使用
UIPanGestureRecognizer
。将
scrollEnabled
设置为NO
,然后添加UIPanGestureRecognizer
以重置中心坐标。该组合将阻止单指平移和捏合的平移部分。编辑以添加更多详细信息,并在查看代码后:
touchesMoved:withEvent
在平移已经开始后调用,因此如果您在那里更改 MKMapView 的中心,您将得到你所描述的不稳定的渲染问题。您真正需要的是创建一个带有目标操作的UIPanGestureRecognizer
,如下所示:...然后向您的控制器添加一个
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
toNO
, then add aUIPanGestureRecognizer
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 aUIPanGestureRecognizer
with a target-action, like so:...and then add a
didRecognizePan
method to your controller, and do your center-resetting there.只是猜测,但您是否尝试过在
regionWillChangeAnimated:
开始时将scrollEnabled
设置为NO
?Just a guess, but have you tried setting
scrollEnabled
toNO
at the start ofregionWillChangeAnimated:
?也只是一个猜测。在 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.