我希望在 UITableView 上实现捏入/捏出,我已经研究了几种方法,包括这个:
但是虽然我可以创建一个UIViewTouch
对象并将其覆盖到我的 UITableView 上,但滚动事件不会被中继到我的 UITableView,我仍然可以选择单元格,并且它们通过触发到新 ViewController 对象的转换来正确响应。但是,尽管传递了 touchesBegan、touchesMoved 和 touchesEnded 事件,但我无法滚动 UITableView。
我希望在 UITableView 上实现捏入/捏出,我已经研究了几种方法,包括这个:
但是虽然我可以创建一个UIViewTouch
对象并将其覆盖到我的 UITableView 上,但滚动事件不会被中继到我的 UITableView,我仍然可以选择单元格,并且它们通过触发到新 ViewController 对象的转换来正确响应。但是,尽管传递了 touchesBegan、touchesMoved 和 touchesEnded 事件,但我无法滚动 UITableView。
这似乎是一个经典的问题。在我的情况下,我想通过 UIWebView 拦截一些事件,这些事件不能被子类化,等等。
我发现最好的方法是使用 UIWindow 拦截事件:
事件拦截窗口.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.
id <EventInterceptWindowDelegate> eventInterceptDelegate;
}
@property(nonatomic, assign)
id <EventInterceptWindowDelegate> eventInterceptDelegate;
@end
事件拦截窗口.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:
是捏到缩放检测的简单实现。注意。一些代码取自 Apress 的《开始 iPhone 3 开发》。
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。这意味着超类也将处理触摸事件,但幸运的是这并没有破坏我的代码。