2012-08-08 14 views
6

Ich habe eine Reihe von Fragen zu diesem Thema gelesen, aber keiner von ihnen scheint zu erreichen, was ich suche ... Also sagen wir, ich habe eine beliebige UIWebView innerhalb einer UIViewController. Die UIViewController hat eine SwipeGestureRecognizer, die gut funktioniert. Es funktioniert sogar innerhalb der UIWebView - wenn es keine Bildlaufleiste gibt. (Bevor ich eine Seite lade oder auch wenn ich eine Seite lade, die passgenau in die Größe meiner UIWebView passt). Allerdings, wenn ich eine Webseite laden, die das horizontale Scrollen nach links oder rechts erfordert, dann innerhalb des UIWebView Teil meiner Sicht kann ich keine Swipe Gesten erkannt werden. Jedes Klicken/Ziehen/Wischen löst nur die Scroll-Aktion aus. Gibt es eine Möglichkeit, zwischen einem "Wischen" und dem bloßen Scrollen mit dem Finger zu unterscheiden (nicht heben, sondern ziehen, um zu blättern).Swipe Gesture Erkennung Inside UIWebView

Antwort

2

Sie müssen UIWebView ableiten und die Gestenerkenneraufrufe überschreiben.

EDIT - in diesem Beitrag Schauen Handling touches inside UIWebview und diesen Link http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way/

+2

Können Sie beschreiben, wie Sie vorgehen? In der Dokumentation heißt es "Die UIWebView-Klasse sollte nicht unterklassifiziert sein". Schauen Sie http://developer.apple.com/library/ios/#documentation/uikit/reference/UIWebView_Class/Reference/Reference.html – MrHappyAsthma

+0

bei der Bearbeitung –

24

Ja, können Sie die UIScrollView der UIWebView sagen, dass seine UIPanGestureRecognizer sollte nur Feuer, wenn Sie Ihre eigenen UISwipeGestureRecognizer ausgefallen ist.

Dies ist, wie Sie es tun:

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

, die für Sie den Trick tun sollten.

+1

funktioniert genau richtig. –

+1

Genius, gerettet viel Zeit! –

+1

Ich habe das nicht getestet, aber ich denke, es wird das Standard-Scrollen von UIWebview überschreiben. Ist das nicht richtig? –

1

Johannes Fahrenkrug's answer ist es gelungen, die integrierten Schwenkbewegungen des webViews bedingt zu blockieren. Ich fand jedoch, dass dies funktioniert nur, wenn die Pfanne Gesten des webView waren sehr langsam ... wenn ich die webView mit einer vernünftigen Geschwindigkeit verrissen wurde die Streichgeste ausgelöst. Ich wollte nur einen schnellen Swipe, um die Swipe-Geste auszulösen, und einen mittleren oder langsamen Schwenk, um die Standard-Scrollfunktion von webView zu verwenden.

Die UISwipeGestureRecognizer hat keine Eigenschaften für die Geschwindigkeit eines Swipe-Customizing und die UIPanGestureRecognizer hat eine Geschwindigkeit Eigenschaft, aber keine Möglichkeit, eine erforderliche Geschwindigkeit zu setzen, so dass ich einen benutzerdefinierten Gestenerkenner basierend auf this tutorial up:

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 

Richten Sie Ihre Gesten

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

dann die Richtung der empfangenen Geste erkennen

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

Beachten Sie, dass dies erfordert nur eine Geste alle vier Wischrichtungen zu handhaben, statt ein UISwipeGestureRecognizer pro Richtung.