拦截/劫持MKMapView的iPhone Touch事件
3.0 SDK中是否存在禁用实时缩放和拦截MKMapView放大手势的错误?我有一些真正简单的代码,因此我可以检测tap事件,但有两个问题:拦截/劫持MKMapView的iPhone Touch事件,iphone,events,gesture-recognition,Iphone,Events,Gesture Recognition,3.0 SDK中是否存在禁用实时缩放和拦截MKMapView放大手势的错误?我有一些真正简单的代码,因此我可以检测tap事件,但有两个问题: 放大手势始终被解释为缩小 所有缩放手势都不会实时更新地图的视图 在hitTest中,如果我返回“map”视图,MKMapView功能工作得很好,但我没有机会截获事件 有什么想法吗 MyMapView.h: @interface MyMapView : MKMapView { UIView *map; } MyMapView.m: - (
@interface MyMapView : MKMapView
{
UIView *map;
}
MyMapView.m:
- (id)initWithFrame:(CGRect)frame
{
if (![super initWithFrame:frame])
return nil;
self.multipleTouchEnabled = true;
return self;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
NSLog(@"Hit Test");
map = [super hitTest:point withEvent:event];
return self;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"%s", __FUNCTION__);
[map touchesCancelled:touches withEvent:event];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent*)event
{
NSLog(@"%s", __FUNCTION__);
[map touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
NSLog(@"%s, %x", __FUNCTION__, mViewTouched);
[map touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
NSLog(@"%s, %x", __FUNCTION__, mViewTouched);
[map touchesEnded:touches withEvent:event];
}
MKMapView不响应上面列出的触摸方法…请尝试
[super-touchesend:toucheevent:event]代码>
而不是
[map touchesEnded:TouchwithEvent:event]代码>
并将此思想应用到所有触摸事件方法中。这样,触碰应该沿着响应链向下移动,和平就会恢复。我也遇到了同样的问题-我想在地图视图的顶部绘制地图比例。为了做到这一点,我必须截取触摸事件,然后将它们发送回地图视图。不幸的是,当MKMapView不是事件的原始接收器时,一些平滑的平移和缩放动画不再工作
然而,我已经找到了这个问题的解决方案——有点老套,但很有效:
1.我已将我的MapScales UIView放在MKMapView的顶部,并关闭了在其中接收事件的功能,因此默认情况下,底层MKMapView会接收事件。
2.我用MyMainWindow类将UIWindow子类化,并在其中重写了方法:
- (void) sendEvent:(UIEvent*)event {
[super sendEvent:event];
[self send_the_event_also_to_my_MapScales_component_with_use_of_listener_design_pattern];
}
我已经将我的应用程序的主窗口设置为我的主窗口
通过这种方式,我的MapScales组件可以接收所有触摸事件并对其作出反应,同时不会破坏底层的MKMapView:)要扩展@chomasek的答案,为了只处理地图视图的这些触摸,我执行以下操作:
给地图视图一个标签,比如99
当我接触时,向上遍历接收视图的视图层次结构,寻找具有上述标记的视图
代码如下:
// this is in the view controller containing the map view
// kICTagForMapView is just a constant
_mapView.tag = kICTagForMapView;
然后在sendEvent:
// this does into the UIWindow subclass
BOOL isMapView = NO;
UIView* superView = touch.view.superview;
while(superView)
{
//Debug(@"superView = %@", superView);
if (superView.tag == kICTagForMapView)
{
isMapView = YES;
break;
}
superView = superView.superview;
}
if (isMapView == NO) return;
// do stuff here
#导入
#导入“UIViewTouch.h”
#进口
@接口MapTouchAppDelegate:NSObject
{
UIViewTouch*viewTouch;
MKMapView*mapView;
UIWindow*窗口;
}
@属性(非原子,保留)IBUIWindow*window;
@属性(非原子,保留)UIViewTouch*viewTouch;
@属性(非原子,保留)MKMapView*mapView;
@结束
#导入“MapTouchAppDelegate.h”
@实现MapTouchAppDelegate
@合成窗口;
@综合视觉触觉;
@综合地图视图;
-(无效)应用程序IDFinishLaunching:(UIApplication*)应用程序
{
//我们创建一个视图,它将捕获事件发生时的情况并将其记录在控制台中
viewTouch=[[UIViewTouch alloc]initWithFrame:CGRectMake(0,0320480)];
//接下来,我们创建MKMapView对象,它将作为viewTouch的子视图添加
mapView=[[MKMapView alloc]initWithFrame:CGRectMake(0,0320480)];
[viewTouch addSubview:mapView];
//我们展示一切!
[窗口添加子视图:视图触摸];
//应用程序启动后自定义的覆盖点
[WindowMakeKeyandVisible];
}
-(无效)解除锁定{
[窗口释放];
[super dealoc];
}
#进口
@界面UIViewTouch:UIView
{
UIView*viewTouched;
}
@属性(非原子,保留)UIView*viewTouched;
-(UIView*)hitTest:(CGPoint)point with event:(UIEvent*)event;
-(无效)触摸开始:(NSSet*)触摸事件:(UIEvent*)事件;
-(无效)触摸移动:(NSSet*)触摸事件:(UIEvent*)事件;
-(void)touchesend:(NSSet*)toucheevent:(UIEvent*)event;
-(void)touchscancelled:(NSSet*)touchsevent:(UIEvent*)event;
@结束
#导入“UIViewTouch.h”
@UIViewTouch的实现
@综合观察;
//这里的基本思想是截取作为hitTest中的第一响应者发送回来的视图。
//我们将其精确地保存在属性视图中,并作为第一响应者返回视图。
-(UIView*)hitTest:(CGPoint)point with event:(UIEvent*)event
{
NSLog(“命中测试”);
self.multipleTouchEnabled=true;
viewTouched=[super hitTest:PointWithEvent:event];
回归自我;
}
//然后,当一个事件被触发时,我们记录这个事件,然后将它发送回我们保存的viewTouch,瞧!!!:)
-(无效)触摸开始:(NSSet*)触摸事件:(UIEvent*)事件
{
NSLog(@“触摸开始”);
[查看触摸开始:触摸事件:事件];
}
-(无效)触摸移动:(NSSet*)触摸事件:(UIEvent*)事件
{
NSLog(“触摸移动”);
[查看触摸移动:触摸事件:事件];
}
-(void)touchesend:(NSSet*)toucheevent:(UIEvent*)event
{
NSLog(@“触摸结束”);
[查看触摸已解除:触摸事件:事件];
}
-(无效)触控取消:(NSSet*)触控事件:(UIEvent*)事件
{
NSLog(“触摸取消”);
}
@结束
此代码将检测触摸和缩放。我发现实现这一点的最佳方法是使用手势识别器。不清楚您是想自己识别缩放事件,还是只想检测用户何时进行缩放/平移
我不需要检测地图平移或缩放——我只关心用户是否将手指放在MKMapView中的任何位置。如果您需要以100%的召回率和准确率检测缩放或平移,则可能比这更复杂。我们真正需要的是MKMapView的开源实现,这样我们就可以将它添加到委托中,以及许多其他功能中
我要做的是:实现一个无法阻止的手势识别器,也无法阻止其他手势识别器。将其添加到地图视图,并根据需要处理相关触摸事件
如何检测MKMapView中的任何点击(SAN技巧)
wildcardGestureRecognitor.h
我不相信。通过将事件传递到地图视图,地图可以平移和缩小。“何时”地图
#import <UIKit/UIKit.h>
#import "UIViewTouch.h"
#import <MapKit/MapKit.h>
@interface MapTouchAppDelegate : NSObject <UIApplicationDelegate>
{
UIViewTouch *viewTouch;
MKMapView *mapView;
UIWindow *window;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) UIViewTouch *viewTouch;
@property (nonatomic, retain) MKMapView *mapView;
@end
#import "MapTouchAppDelegate.h"
@implementation MapTouchAppDelegate
@synthesize window;
@synthesize viewTouch;
@synthesize mapView;
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
//We create a view wich will catch Events as they occured and Log them in the Console
viewTouch = [[UIViewTouch alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
//Next we create the MKMapView object, which will be added as a subview of viewTouch
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[viewTouch addSubview:mapView];
//And we display everything!
[window addSubview:viewTouch];
// Override point for customization after application launch
[window makeKeyAndVisible];
}
- (void)dealloc {
[window release];
[super dealloc];
}
#import <UIKit/UIKit.h>
@interface UIViewTouch : UIView
{
UIView *viewTouched;
}
@property (nonatomic, retain) UIView * viewTouched;
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
@end
#import "UIViewTouch.h"
@implementation UIViewTouch
@synthesize viewTouched;
//The basic idea here is to intercept the view which is sent back as the firstresponder in hitTest.
//We keep it preciously in the property viewTouched and we return our view as the firstresponder.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSLog(@"Hit Test");
self.multipleTouchEnabled = true;
viewTouched = [super hitTest:point withEvent:event];
return self;
}
//Then, when an event is fired, we log this one and then send it back to the viewTouched we kept, and voilà!!! :)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Touch Began");
[viewTouched touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Touch Moved");
[viewTouched touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Touch Ended");
[viewTouched touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"Touch Cancelled");
}
@end
WildcardGestureRecognizer * tapInterceptor = [[WildcardGestureRecognizer alloc] init];
tapInterceptor.touchesBeganCallback = ^(NSSet * touches, UIEvent * event) {
self.lockedOnUserLocation = NO;
};
[mapView addGestureRecognizer:tapInterceptor];
//
// WildcardGestureRecognizer.h
// Copyright 2010 Floatopian LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^TouchesEventBlock)(NSSet * touches, UIEvent * event);
@interface WildcardGestureRecognizer : UIGestureRecognizer {
TouchesEventBlock touchesBeganCallback;
}
@property(copy) TouchesEventBlock touchesBeganCallback;
@end
//
// WildcardGestureRecognizer.m
// Created by Raymond Daly on 10/31/10.
// Copyright 2010 Floatopian LLC. All rights reserved.
//
#import "WildcardGestureRecognizer.h"
@implementation WildcardGestureRecognizer
@synthesize touchesBeganCallback;
-(id) init{
if (self = [super init])
{
self.cancelsTouchesInView = NO;
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (touchesBeganCallback)
touchesBeganCallback(touches, event);
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)reset
{
}
- (void)ignoreTouch:(UITouch *)touch forEvent:(UIEvent *)event
{
}
- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer
{
return NO;
}
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
{
return NO;
}
@end