web-dev-qa-db-fra.com

Gestion des contacts à l'intérieur de UIWebview

J'ai créé une sous-classe de UIWebView et mis en œuvre les méthodes touchesBegan, touchesMoved et touchesEnded.

mais la sous-classe webview ne gère pas les événements touch.

Existe-t-il une méthode pour gérer les événements tactiles dans la sous-classe UIWebView ???

35
Biranchi

Aucun sous-classement nécessaire, ajoutez simplement une UITapGestureRecognizer:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapMethod)];
[tap setNumberOfTapsRequired:1]; // Set your own number here
[tap setDelegate:self]; // Add the <UIGestureRecognizerDelegate> protocol

[self.myWebView addGestureRecognizer:tap];

Ajoutez le protocole <UIGestureRecognizerDelegate> dans le fichier d'en-tête et ajoutez cette méthode:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}
45
John

Si tout ce dont vous avez besoin est de gérer les gestes tout en laissant intacte le reste de la fonctionnalité UIWebView, vous pouvez sous-classer UIWebView et utiliser cette stratégie:

dans la méthode init de votre sous-classe UIWebView, ajoutez un identificateur de mouvements, par exemple:

UISwipeGestureRecognizer  * swipeRight = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeGestureRightMethod)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self addGestureRecognizer:swipeRight];
swipeRight.delegate = self;

ajoutez ensuite cette méthode à votre classe:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

Ajoutez et gérez votre sélecteur désigné à la classe, dans ce cas "handleSwipeGestureRightMethod" et vous êtes prêt à partir ...

8
ecume des jours

Vous pouvez mettre un UIView sur votre UIWebView et remplacer le touchesDidBegin etc., puis les envoyer à votre vue Web. Ex:

L'utilisateur touche votre UIView, ce qui provoque un 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{  
    // Execute your code then send a touchesBegan to your webview like so:
[webView touchesBegan:touches withEvent:event];
return;
}

votre UIView doit être sur la vue Web.

7
Alexandre Cassagne

Je ne sais pas si c'est ce que vous voulez (ce n'est pas ce que vous avez demandé, mais cela peut fonctionner en fonction de la fin du jeu), mais vous pouvez interpréter les touches en JavaScript depuis l'intérieur de UIWebView, et obtenir le javascript nécessaire. faire

document.location='http://null/'+xCoord+'/'+yCoord; // Null is arbitrary.

Ensuite, vous pouvez attraper cela en utilisant la méthode déléguée de UIWebView

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

Et si la requête.URL.Host (ou quoi que ce soit) estEqualToString: @ "null", prenez l'action appropriée (et retournez NO au lieu de YES). Vous pouvez même ajouter le JS à chaque page en procédant comme suit:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
  [webView stringByEvaluatingJavaScriptFromString:@"window.ontouchstart=function(/* ... */);"];
}

J'espère que cela t'aides?

5
Benjie

La gestion des gestes sur UIWebView est décrite dans le fil de discussion de ce forum pour développeurs Apple

En utilisant les informations données ici, il ne sera pas nécessaire d’afficher une vue supplémentaire dans la plupart ou dans tous les cas, et comme mentionné précédemment, il n’est pas utile de remplacer UIWebView.

Copypaste du message le plus important dans le fil de discussion:

C'est un problème connu. UIWebView a ses propres UITapGestureRecognizers et se trouve dans une sous-vue privée de UIWebView lui-même. La priorité UIGestureRecognizer définit que les gestes attachés aux vues situées plus en profondeur dans la hiérarchie des vues excluent ceux des vues superposées. Ainsi, les gestes de la vue Web l'emporteront toujours sur les vôtres.

Si vous souhaitez que votre effleurement se produise en même temps que le tapotement normal de la vue Web, votre meilleure solution serait d'implémenter la méthode UIGestureRecognizerDelegate gestureRecognizer: shouldRecognizeSimultaneousWithGestureRecognizer et de renvoyer YES pour les autres gestes de tapotement. De cette façon, votre gestionnaire de taps sera appelé et la vue Web le sera toujours.

Si vous devez être le seul à gérer le tapotement, vous devrez sous-classe UITapGestureRecognizer afin que vous puissiez utiliser les substitutions unidirectionnelles dans UIGestureRecognizerSubclass.h, vous pourrez alors retourner NON à partir de canBePreventedByGestureRecognizer: lorsque vous lui demanderez si la reconnaissance de geste de la vue Web peut prévenir le vôtre.

Dans tous les cas, nous en sommes conscients et espérons pouvoir faciliter les choses à l'avenir.

3
ecotax

Je viens de découvrir que UIWebView vérifie si elle répond au sélecteur - (void)webViewDidNotClick: (id)webBrowserView, une fois que l’on tape sur la zone de visualisation (pas sur hyperref, ni sur toute autre zone devant être traitée spécifiquement). Vous pouvez donc implémenter ce sélecteur avec votre code de traitement :)

2
indexless

Je voudrais essayer de remplacer -sendEvent: sur UIWindow, pour voir si vous pouvez intercepter ces événements tactiles.

0
Unfalkster

Si vous voulez détecter vos propres taps mais désactiver les taps de UIWebView, vous pouvez utiliser ma solution:

-(void)recursivelyDisableTapsOnView:(UIView*)v{
    for(UIView* view in v.subviews){
        for(UIGestureRecognizer* g in view.gestureRecognizers){
            if(g == self.ownTapRecognizer){
                continue;
            }
            if([g isKindOfClass:[UITapGestureRecognizer class]] ||
               [g isKindOfClass:[UILongPressGestureRecognizer class]] ||
               [g isKindOfClass:NSClassFromString(@"UITapAndAHalfRecognizer")]){
                g.enabled = NO;
            }
        }
        [self recursivelyDisableTapsOnView:view];
    }
}


- (void)webViewDidFinishLoad:(UIWebView *)webView{
    [self recursivelyDisableTapsOnView:webView];

    //disable selection
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
    // Disable callout
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
}
0
malhal

Voulez-vous dire que votre implémentation sous-classée n'est pas appelée lorsque touchesBegan, touchesMoved et touchesEnded sont appelées? 

Cela ressemble à un problème avec la façon dont vous avez créé une instance de l'objet. Plus de détails sont nécessaires, je pense.

(pris sous forme de commentaires)

En tête de fichier

#import <UIKit/UIKit.h> 

@interface MyWebView : UIWebView { } @end 

Fichier d'implémentation

#import "MyWebView.h" 

@implementation MyWebView 

- (id)initWithFrame:(CGRect)frame { 
    if (self = [super initWithFrame:frame]) { } return self; 
} 

- (void)drawRect:(CGRect)rect { 
    NSLog(@"MyWebView is loaded"); 
} 

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
   NSLog(@"touches began"); 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 
    NSLog(@"Touches ended");     
} 

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

@end
0
rjstelling

Pour faire suite à ce que Unfalkster a dit, vous pouvez utiliser la méthode hitTest pour réaliser ce que vous voulez, mais vous n’avez pas à sous-classer UIWindow. Il suffit de mettre cela dans votre sous-classe d'affichage Web. Vous aurez un avertissement concernant la compilation mais cela fonctionne:

- (void)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (event.type == UIEventTypeTouches) {

        // get location info
        CGFloat x = point.x;
        CGFloat y = point.y;

        // get touches
        NSSet *touches = [event allTouches];

        // individual touches
        for (UITouch *touch in touches) {

            if (touch.phase == UITouchPhaseBegan) {
                // touches began

            } else if (touch.phase == UITouchPhaseMoved) {

            }

            // etc etc
        }
    }

    // call the super
    [super hitTest:point withEvent:event];
}

J'espère que cela pourra aider!

0
imnk