我想在UITableView上实现一个捏合/外出,我已经看了几个方法,包括这个:
类似的问题
但是虽然我可以创建一个UIViewTouch
对象并将其覆盖到我的UITableView上,滚动事件不会被转发到我的UITableView,我仍然可以选择单元格,并且它们通过触发转换到新的ViewController对象来正确响应.但是,尽管传递了touchesBegan,touchesMoved和touchesEnded事件,但我无法滚动UITableView.
这似乎是一个经典问题.在我的情况下,我想拦截UIWebView上的一些事件,这些事件不能被子类化,等等.
我发现最好的方法是使用UIWindow拦截事件:
EventInterceptWindow.h
@protocol EventInterceptWindowDelegate - (BOOL)interceptEvent:(UIEvent *)event; // return YES if event handled @end @interface EventInterceptWindow : UIWindow { // It would appear that using the variable name 'delegate' in any UI Kit // subclass is a really bad idea because it can occlude the same name in a // superclass and silently break things like autorotation. ideventInterceptDelegate; } @property(nonatomic, assign) id eventInterceptDelegate; @end
EventInterceptWindow.m:
#import "EventInterceptWindow.h" @implementation EventInterceptWindow @synthesize eventInterceptDelegate; - (void)sendEvent:(UIEvent *)event { if ([eventInterceptDelegate interceptEvent:event] == NO) [super sendEvent:event]; } @end
创建该类,将MainWindow.xib中的UIWindow类更改为EventInterceptWindow,然后将eventInterceptDelegate设置为要拦截事件的视图控制器.拦截双击的示例:
- (BOOL)interceptEvent:(UIEvent *)event { NSSet *touches = [event allTouches]; UITouch *oneTouch = [touches anyObject]; UIView *touchView = [oneTouch view]; // NSLog(@"tap count = %d", [oneTouch tapCount]); // check for taps on the web view which really end up being dispatched to // a scroll view if (touchView && [touchView isDescendantOfView:webView] && touches && oneTouch.phase == UITouchPhaseBegan) { if ([oneTouch tapCount] == 2) { [self toggleScreenDecorations]; return YES; } } return NO; }
相关信息:http: //iphoneincubator.com/blog/windows-views/360idev-iphone-developers-conference-presentation
尼姆罗德写道:
某处将eventInterceptDelegate设置为您要拦截事件的视图控制器
我没有立即理解这句话.为了让与我有同样问题的其他人的利益,我这样做的方法是将以下代码添加到我必须检测触摸的UIView子类中.
- (void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // Register to receive touch events MyApplicationAppDelegate *appDelegate = (MyApplicationAppDelegate *) [[UIApplication sharedApplication] delegate]; EventInterceptWindow *window = (EventInterceptWindow *) appDelegate.window; window.eventInterceptDelegate = self; } - (void) viewWillDisappear:(BOOL) animated { // Deregister from receiving touch events MyApplicationAppDelegate *appDelegate = (MyApplicationAppDelegate *) [[UIApplication sharedApplication] delegate]; EventInterceptWindow *window = (EventInterceptWindow *) appDelegate.window; window.eventInterceptDelegate = nil; [super viewWillDisappear:animated]; } - (BOOL) interceptEvent:(UIEvent *) event { NSLog(@"interceptEvent is being called..."); return NO; }
这个版本interceptEvent:
是一个简单的缩放检测实现.NB.一些代码来自Apress的Beginning iPhone 3 Development.
CGFloat initialDistance; - (BOOL) interceptEvent:(UIEvent *) event { NSSet *touches = [event allTouches]; // Give up if user wasn't using two fingers if([touches count] != 2) return NO; UITouchPhase phase = ((UITouch *) [touches anyObject]).phase; CGPoint firstPoint = [[[touches allObjects] objectAtIndex:0] locationInView:self.view]; CGPoint secondPoint = [[[touches allObjects] objectAtIndex:1] locationInView:self.view]; CGFloat deltaX = secondPoint.x - firstPoint.x; CGFloat deltaY = secondPoint.y - firstPoint.y; CGFloat distance = sqrt(deltaX*deltaX + deltaY*deltaY); if(phase == UITouchPhaseBegan) { initialDistance = distance; } else if(phase == UITouchPhaseMoved) { CGFloat currentDistance = distance; if(initialDistance == 0) initialDistance = currentDistance; else if(currentDistance - initialDistance > kMinimumPinchDelta) NSLog(@"Zoom in"); else if(initialDistance - currentDistance > kMinimumPinchDelta) NSLog(@"Zoom out"); } else if(phase == UITouchPhaseEnded) { initialDistance = 0; } return YES; }
编辑:虽然这个代码在iPhone模拟器中工作得很好,但当我在iPhone设备上运行时,我遇到了与表滚动相关的奇怪错误.如果您也遇到这种情况,则强制该interceptEvent:
方法在所有情况下都返回NO.这意味着超类也将处理触摸事件,但幸运的是,这并没有破坏我的代码.