Наблюдение за жестами с несколькими касаниями в UITableView

StackOverflow https://stackoverflow.com/questions/2003201

Вопрос

Я хочу реализовать щепотку ввода / вывода поверх UITableView, я рассмотрел несколько методов, включая этот:

Похожий вопрос

Но пока я могу создать UIViewTouch объект и наложите его на мой UITableView, события прокрутки не передаются на мой UITableView, я все еще могу выбирать ячейки, и они реагируют должным образом, вызывая переход к новому объекту ViewController.Но я не могу прокрутить UITableView, несмотря на передачу событий touchesBegan, touchesMoved и touchesEnded.

Это было полезно?

Решение

Это, по-видимому, классическая проблема.В моем случае я хотел перехватить некоторые события через 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

Создайте этот класс, измените класс вашего UIWindow в вашем MainWindow.xib на 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: представляет собой простую реализацию определения пинч-к-зуму.ПРИМЕЧАНИЕ.Некоторый код был взят из Начала разработки iPhone 3 компанией Apress.

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


Редактировать:Хотя этот код работал на 100% нормально в симуляторе iPhone, когда я запустил его на устройстве iPhone, я столкнулся со странными ошибками, связанными с прокруткой таблицы.Если это также произойдет с вами, то принудительно interceptEvent: метод, возвращающий NO во всех случаях.Это означает, что суперкласс также обработает событие касания, но, к счастью, это не нарушило мой код.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top