41 votes

UIGestureRecognizer fonctionne sur un UIWebView ?

Je suis d'essayer d'obtenir un UIGestureRecognizer de travail avec une UIWebview qui est une sous-vue d'un UIScrollView. Cela semble étrange, mais quand j'ai l' numberOfTouchesRequired 2 le sélecteur de feux, mais lorsqu' numberOfTouchesRequired est un le sélecteur de ne pas le feu.

Voici mon code:

UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(select1:)];
    tap1.numberOfTouchesRequired = 2;
    tap1.numberOfTapsRequired = 1;
    tap1.delegate = self;
    [self.ans1WebView addGestureRecognizer:tap1];
    [tap1 release];

- (void) select1:(UILongPressGestureRecognizer *)sender {
    //Do Stuff
}

J'ai confirmé cela en utilisant la Pomme de l'échantillon pour UIGestureRecognizer et l'insertion d'une webview dans leur plume. Leur robinet code fonctionne partout, mais à l'intérieur de la zone de la webview.

68voto

drawnonward Points 35444

De ce que j'ai vu, UIWebView ne joue pas bien avec les autres. Pour les modules de reconnaissance de geste, vous pouvez essayer de retourner OUI partir de:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

J'ai eu d'être compatible avec la version 3.0 j'ai donc fini par faire tout le geste de manipulation avec le Javascript à l'intérieur de la UIWebView. Pas une bonne solution, mais cela a fonctionné pour mes besoins. J'ai été en mesure de capturer un appui long sur un élément, ainsi que les touchez, faites glisser, pincer et de rotation. Bien sûr, j'ai été en utilisant uniquement le contenu local.

Edit:

Vous pouvez regarder dans PhoneGap pour un exemple de l'envoi de messages à la déléguée de la UIWebView. En un mot, vous utilisez document.location = "myscheme:mycommand?myarguments" alors d'analyser la commande et les arguments de ce délégué de rappel:

-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
  if ( [[[inRequest URL] absoluteString] hasPrefix:@"myscheme:"] ) {
    //.. parse arguments
    return NO;
  }
}

Vous pouvez le voir dans la PhoneGap code qu'ils ont mis en place une file d'attente et la minuterie pour envoyer les messages. En fonction de votre utilisation, vous devrez peut-être faire la même chose. Il y a d'autres questions sur DONC sur ce sujet.

Ici est la gestion des Événements de la documentation. Dans mon cas, j'ai ajouté des écouteurs d'événements à document de <body onload="myloader();">

function myloader() {
    document.addEventListener( 'touchcancel' , touch_cancel , false );
    document.addEventListener( 'touchstart' , touch_start , false );
    document.addEventListener( 'touchmove' , touch_move , false );
    document.addEventListener( 'touchend' , touch_end , false );
};

L'événement réel de la manipulation varie beaucoup en fonction de vos besoins. Chaque gestionnaire d'événement recevra un TouchEvent avec une touche de la propriété où chaque élément est une Touch. Vous pouvez enregistrer l'heure de début et l'emplacement dans votre gestionnaire d'évènements touchstart. Si la touche déplacer pour la mesure ou la mauvaise quantité de temps qui passe, il n'est pas un long touch.

WebKit peut essayer de gérer une longue touche pour démarrer une sélection et copie. Dans votre gestionnaire d'événements, vous pouvez utiliser event.preventDefault(); pour arrêter le comportement par défaut. J'ai aussi trouvé l' -webkit-user-select:none css bien pratique pour certaines choses.

var touch = {};
function touch_start( event /*TouchEvent*/ {
  event.preventDefault();
  touch = {};
  touch.startX = event.touches.item(0).pageX;
  touch.startY = event.touches.item(0).pageY;
  touch.startT = ( new Date() ).getTime();
}

Ce n'est que le deuxième projet, j'ai utilisé du javascript avec. Vous pouvez trouver de meilleurs exemples ailleurs.

Comme vous pouvez le voir ce n'est pas une réponse rapide à votre problème. Je suis assez heureux avec les résultats que j'ai obtenu. Le html je travaillais avait pas d'éléments interactifs au-delà d'un lien ou deux.

45voto

Don Wilson Points 867

UIWebView a sa propre salle de points de vue, qui a aussi des modules de reconnaissance de geste attaché. Par conséquent, les règles de priorité de garder tout geste modules de reconnaissance ajouté à une UIWebView de fonctionner correctement.

Une option est de mettre en œuvre les UIGestureRecognizerDelegate protocole et de mettre en œuvre la méthode gestureRecognizer:shouldRecognizeSimultaneouslyWithgesturerecognizer. Retourner OUI partir de cette méthode pour d'autres touchez gestes. De cette façon, vous obtiendrez votre robinet fonction appelée, et la vue web obtiendrez toujours de son nom.

Voir cela sur le dev Apple forums.

13voto

Johannes Fahrenkrug Points 12795

C'est un peu le hack-ish solution, mais il fonctionne. UIWebView a beaucoup de mouvement interne des modules de reconnaissance que vous ne pouvez normalement pas accès sans utilisation privée de l'API. Vous obtenez tous gratuitement, cependant, lorsque vous implémentez gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:. À ce stade, vous pouvez dire à tous les internes UITapGestureRecognizers à déclenche uniquement lorsque votre propre UITapGestureRecognizer a échoué. Vous ne faites qu'une fois et ensuite supprimer le délégué de votre propre geste de reconnaissance. Le résultat est que vous pouvez toujours casserole et faites webView, mais il n'y aura pas de (unique) appuyez sur les gestes plus.

- (void)viewDidLoad 
{      
    [super viewDidLoad];

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];

    // view is your UIViewController's view that contains your UIWebView as a subview
    [self.view addGestureRecognizer:tap];

    tap.delegate = self;
}

- (void)handleTapGesture:(UITapGestureRecognizer *)gestureRecognizer
{
    NSLog(@"tap!");

    // this is called after gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: so we can safely remove the delegate here
    if (gestureRecognizer.delegate) {
        NSLog(@"Removing delegate...");
        gestureRecognizer.delegate = nil;
    }
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if ([otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        [otherGestureRecognizer requireGestureRecognizerToFail:gestureRecognizer];

        NSLog(@"added failure requirement to: %@", otherGestureRecognizer);
    }

    return YES;
}

Profitez-en!

4voto

chrisallick Points 271

J’ai eu le même problème. Cette solution a fonctionné pour moi :

1) Assurez-vous d’ajouter le protocole à votre interface : UIGestureRecognizerDelegate par exemple :

2) Ajoutez cette ligne de code

3)

3voto

BHUPI Points 806
<pre><code></code></pre>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X