2012-08-08 15 views
6

Ho letto un sacco di domande su questo argomento ma nessuno di essi sembra ottenere ciò che sto cercando ... Quindi diciamo che ho un arbitrario UIWebView all'interno di un UIViewController. Il UIViewController ha un SwipeGestureRecognizer che funziona bene. Funziona anche all'interno dello UIWebView - ogni volta che non c'è alcuna barra di scorrimento. (Prima di caricare una pagina o anche se carico una pagina che può adattarsi in modo appropriato all'interno della dimensione del mio UIWebView). Tuttavia, se carico una pagina web che richiede lo scorrimento orizzontale a sinistra o a destra, quindi all'interno della parte UIWebView della mia visualizzazione, non riesco a riconoscere alcun movimento di scorrimento. Ogni clic/trascinamento/scorrimento fa scattare l'azione di scorrimento. C'è un modo per distinguere tra uno "scorrimento" e semplicemente lo scorrimento con il dito (non sollevandolo ma piuttosto trascinando per scorrere).Riconoscimento di gesti swipe all'interno di UIWebView

risposta

2

Sarà necessario suddividere in sottoclasse UIWebView e ignorare le chiamate al riconoscimento dei gesti.

EDIT - un'occhiata a questo post Handling touches inside UIWebview e questo legame http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way/

+2

Puoi descrivere come procedere? Nella documentazione dice "La classe UIWebView non dovrebbe essere sottoclasse". http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebView_Class/Reference/Reference.html – MrHappyAsthma

+0

Guarda la modifica –

24

Sì, si può dire UIScrollView del UIWebView che la sua UIPanGestureRecognizer dovrebbe fuoco solo quando il proprio UISwipeGestureRecognizer è riuscito.

Ecco come si fa:

UISwipeGestureRecognizer *rightSwipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)]; 
UISwipeGestureRecognizer *leftSwipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)]; 
rightSwipeGesture.direction = UISwipeGestureRecognizerDirectionRight; 
leftSwipeGesture.direction = UISwipeGestureRecognizerDirectionLeft; 
[self.view addGestureRecognizer:rightSwipeGesture]; 
[self.view addGestureRecognizer:leftSwipeGesture]; 

[_webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:rightSwipeGesture]; 
[_webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:leftSwipeGesture]; 

Questo dovrebbe fare il trucco per voi.

+1

Funziona perfettamente. –

+1

Genius, ho risparmiato molto tempo! –

+1

Non ho provato questo, ma penso che sostituirà lo scorrimento di default di UIWebview. Non è giusto? –

1

Johannes Fahrenkrug's answer riuscito a bloccare in modo condizionale i gesti di panoramica incorporati di webView. Tuttavia, ho scoperto che questo funzionava solo se i movimenti di panoramica della webView erano molto lenti ... se ho fatto una panoramica della webView con una velocità ragionevole, il gesto di scorrimento è stato attivato. Volevo solo un passaggio rapido per attivare il gesto di scorrimento e le pentole medie o lente per utilizzare la funzionalità di scorrimento WebView predefinita.

L'UISwipeGestureRecognizer non ha proprietà per personalizzare la velocità di un colpo, e l'UIPanGestureRecognizer ha una proprietà di velocità, ma non c'è modo di impostare una velocità desiderata, in modo da impostare un sistema di riconoscimento gesto personalizzata basata su this tutorial:

FastSwipeGestureRecognizer.h

#import <UIKit/UIKit.h> 
#import <UIKit/UIGestureRecognizerSubclass.h> 

#define REQUIRED_TOUCHES 5 
#define REQUIRED_STRAIGHTNESS 3 
#define REQUIRED_TIME .1 

typedef enum { 
    DirectionUp = 0, 
    DirectionRight, 
    DirectionDown, 
    DirectionLeft 
} Direction; 

@interface FastSwipeGestureRecognizer : UIGestureRecognizer { 
    CGPoint firstTouchLocation; 
    NSTimeInterval firstTouchTime; 
    int touchesCount; 

    Direction direction; 
} 

@property (nonatomic) CGPoint firstTouchLocation; 
@property (nonatomic) NSTimeInterval firstTouchTime; 
@property (nonatomic) int touchesCount; 

@property (nonatomic) Direction direction; 

@end 

FastSwipeGestureRecognizer.m

#import "FastSwipeGestureRecognizer.h" 

@implementation FastSwipeGestureRecognizer 

@synthesize firstTouchLocation; 
@synthesize firstTouchTime; 
@synthesize touchesCount; 

-(void)reset { 
    [super reset]; 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesBegan:touches withEvent:event]; 
    self.firstTouchLocation = [[touches anyObject] locationInView:self.view]; 
    self.firstTouchTime = [NSDate timeIntervalSinceReferenceDate]; 
    self.touchesCount = 1; 
    self.state = UIGestureRecognizerStatePossible; 
} 

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesMoved:touches withEvent:event]; 
    self.touchesCount++; 
    if (self.touchesCount > REQUIRED_TOUCHES) { // wait until we have a few touches before we evaluate the gesture 
     CGPoint thisTouchLocation = [[touches anyObject] locationInView:self.view]; 
     float horizontalRatio = (ABS(thisTouchLocation.x - self.firstTouchLocation.x)/ABS(thisTouchLocation.y - self.firstTouchLocation.y)); 
     float verticalRatio = 1/horizontalRatio; 
     NSTimeInterval elapsedTime = [NSDate timeIntervalSinceReferenceDate] - self.firstTouchTime; 
     NSLog(@"swipe? %f, %f, %f", verticalRatio, horizontalRatio, elapsedTime); 

     // if we're moving straight enough and fast enough, complete the gesture 
     if (((horizontalRatio > REQUIRED_STRAIGHTNESS)||(verticalRatio > REQUIRED_STRAIGHTNESS))&&(elapsedTime < REQUIRED_TIME)) { 
      if (horizontalRatio > REQUIRED_STRAIGHTNESS) { 
       self.direction = (thisTouchLocation.x > self.firstTouchLocation.x) ? DirectionRight : DirectionLeft ; 
      } else if (verticalRatio > REQUIRED_STRAIGHTNESS) { 
       self.direction = (thisTouchLocation.y > self.firstTouchLocation.y) ? DirectionDown : DirectionUp ; 
      } 
      self.state = UIGestureRecognizerStateRecognized; 
     } else { 
      self.state = UIGestureRecognizerStateFailed; 
     } 
    } 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesEnded:touches withEvent:event]; 
    if (self.touchesCount < REQUIRED_TOUCHES) { 
     self.state = UIGestureRecognizerStateFailed; 
    } 
} 

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { 
    [super touchesCancelled:touches withEvent:event]; 
    self.state = UIGestureRecognizerStateFailed; 
} 

@end 

Impostare le gesti

FastSwipeGestureRecognizer *swipeGesture = [[FastSwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)]; 
[self.view addGestureRecognizer:swipeGesture]; 
[self.webView.scrollView.panGestureRecognizer requireGestureRecognizerToFail:swipeGesture]; 

poi rilevare la direzione del gesto ricevuto

- (void)handleSwipeGesture:(FastSwipeGestureRecognizer *)gesture { 
    if (gesture.state == UIGestureRecognizerStateEnded) { 
     if (gesture.direction == DirectionRight) { 
      // do something 
     } else if (gesture.direction == DirectionLeft) { 
      // do something 
     } else if (gesture.direction == DirectionUp) { 
      // do something 
     } else if (gesture.direction == DirectionDown) { 
      // do something 
     } 
    } 
} 

Si noti che questo richiede un solo gesto per gestire tutte le quattro direzioni magnetiche, invece di un UISwipeGestureRecognizer per direzione.

Problemi correlati