Question

Je cherche à mettre en œuvre une pincée dans / sur le dessus d'un UITableView, je l'ai regardé plusieurs méthodes dont celui-ci:

question similaires

Mais alors que je peux créer un objet UIViewTouch et superposer sur mon UITableView, faites défiler les événements ne sont pas relayés à mon UITableView, je peux toujours sélectionner les cellules, et ils répondent correctement en déclenchant une transition vers un nouvel objet ViewController. Mais je ne peux pas faire défiler le UITableView malgré le passage du touchesBegan, touchesMoved et événements touchesEnded.

Était-ce utile?

La solution

Cela semble être un problème classique. Dans mon cas, je voulais intercepter certains événements sur une UIWebView qui ne peut pas être sous-etc, etc.

J'ai trouvé que la meilleure façon de le faire est d'intercepter les événements à l'aide du 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

Créer cette classe, changer la classe de votre UIWindow dans votre MainWindow.xib à EventInterceptWindow, puis définissez quelque part eventInterceptDelegate à un contrôleur de vue que vous souhaitez intercepter les événements. Exemple qui intercepte un double-clic:

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

Infos connexes ici: http://iphoneincubator.com/blog/windows-views/360idev Les développeurs de -iphone-conférence-présentation

Autres conseils

Nimrod a écrit:

  

quelque part défini eventInterceptDelegate à un contrôleur de vue que vous souhaitez intercepter les événements

Je ne comprends pas immédiatement cette déclaration. Pour le bénéfice de quelqu'un d'autre qui avait le même problème que moi, comme je l'ai fait était en ajoutant le code suivant à ma sous-classe UIView qui doit détecter des touches.

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


Cette version de interceptEvent: est une implémentation simple de détection de pincement à zoom. NB. Une partie du code a été prise depuis le début de l'iPhone 3 de développement 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;
}


Edit: Bien que ce code a fonctionné à 100% fin dans le simulateur iPhone, quand je l'ai couru sur un appareil iPhone que j'ai rencontré des bugs étranges liés au défilement de la table. Si cela se produit aussi à vous, la force alors la méthode interceptEvent: pour revenir NO dans tous les cas. Cela signifie que la superclasse traitera aussi l'événement tactile, mais heureusement cela n'a pas briser mon code.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top