拦截/劫持iPhone触摸事件进行的MKMapView拦截/劫持iPhone触摸事件进行的MKMap

2019-06-14 05:53发布

有没有在3.0 SDK禁用实时缩放和拦截针对的MKMapView缩放手势的错误吗? 我有一些真正简单的代码,所以我可以检测到点击事件,但有两个问题:

  1. 放大手势总是被解释为一个缩小
  2. 无缩放手势更新地图的实时视图。

在则hitTest,如果我返回“图”视图中,功能性的MKMapView的伟大工程,但我没有得到机会拦截事件。

有任何想法吗?

MyMapView.h:

@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];
}

Answer 1:

我已经找到了实现这一目标的最好方法是使用手势识别。 如果你想自己承认缩放事件或当用户缩放/平移只是检测目前还不清楚。

我不需要侦测到地图上平移或缩放 - 我只关心用户是否在的MKMapView把手指在任何地方。 如果您需要检测缩放或100%的召回率和准确平移,这可能是比这更复杂。 我们真正需要的是的MKMapView的一个开源实现,所以我们可以将它添加到委托,许多其他特征。

下面是我做的:实现不能阻止一个手势识别,并不能阻止其他手势识别。 将它添加到地图视图和相关触摸事件处理,你的愿望。

如何检测的MKMapView内的任何水龙头(SANS技巧)

WildcardGestureRecognizer * tapInterceptor = [[WildcardGestureRecognizer alloc] init];
 tapInterceptor.touchesBeganCallback = ^(NSSet * touches, UIEvent * event) {
  self.lockedOnUserLocation = NO;
 };
 [mapView addGestureRecognizer:tapInterceptor];

WildcardGestureRecognizer.h

//
//  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

//
//  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


Answer 2:

我有同样的问题 - 我想画上的地图视图顶部的比例尺。 为了做到这一点,我不得不拦截触摸事件,然后送他们回地图视图。 不幸的是,当的MKMapView不是事件的原始接收器,一些顺利平移和缩放动画不工作了。

不过,我已经找到了解决这个问题 - 有点哈克但工作原理:1.我已经把我的MapScales的UIView上的MKMapView的顶部,并关闭接收它的事件,让底层的MKMapView默认收到的事件。 2.我已经子类的UIWindow与MyMainWindow类,并在它我已经重写的方法:

- (void) sendEvent:(UIEvent*)event {
  [super sendEvent:event];
  [self send_the_event_also_to_my_MapScales_component_with_use_of_listener_design_pattern];
}
  1. 我已经作出了应用程序的主窗口MyMainWindow的instasnce。

这样我MapScales组件接收并能应对所有的触摸事件,并在同一时间它不是破坏底层的MKMapView :)



Answer 3:

#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

此代码将检测触摸以及缩放。



Answer 4:

尝试

[super touchesEnded:touches withEvent:event];

代替

[map touchesEnded:touches withEvent:event];

并运用这种思想的所有的触摸事件的方法。 这样一来,倒是应该向下行进响应链,和平将得到恢复。



Answer 5:

为了延长了对@ chomasek的答案,为了只处理那些触摸的地图视图,我做到以下几点:

  1. 给地图查看标签,像99
  2. 当我触摸,穿越了接收视图的视图层次,寻找与上述标签的视图。

下面是代码:

// 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


Answer 6:

的MKMapView不响应上面列出的触摸方法...



文章来源: Intercepting/Hijacking iPhone Touch Events for MKMapView