UITableViewでピンチマルチタッチジェスチャーを観察します
-
18-09-2019 - |
質問
私はのUITableViewの上/アウトでピンチを実装するために探しています、私はこの1つを含むいくつかの方法を見てきました
しかし、私は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.
id <EventInterceptWindowDelegate> eventInterceptDelegate;
}
@property(nonatomic, assign)
id <EventInterceptWindowDelegate> eventInterceptDelegate;
@end
EventInterceptWindow.mます:
#import "EventInterceptWindow.h"
@implementation EventInterceptWindow
@synthesize eventInterceptDelegate;
- (void)sendEvent:(UIEvent *)event {
if ([eventInterceptDelegate interceptEvent:event] == NO)
[super sendEvent:event];
}
@end
、そのクラスを作成しますEventInterceptWindowにごMainWindow.xibであなたのUIWindowのクラスを変更し、どこかにあなたがイベントをインターセプトしたいビューコントローラに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;
}
ここで の-iPhone-開発者会議、プレゼンテーション 他のヒント
ニムロッドは書いてます:
は、どこかにあなたがイベントをインターセプトしたいビューコントローラに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。いくつかのコードは、プレスカンファレンスで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シミュレータで100%の罰金を働いている間、私はiPhoneのデバイス上でそれを実行したとき、私はテーブルのスクロールに関連する奇妙なバグに遭遇しました。これはまた、あなたに何が起こる場合は、すべての場合にNOを返すようにinterceptEvent:
方法を強制します。これは、スーパークラスは、タッチイベントを処理しますが、幸いこれは私のコードを壊していなかったことを意味します。