2011-12-18 3 views
0

J'ai une vue (parent) avec deux sous-vues, une sur le dessus (topChild) de l'autre (bottomChild).Sous-vue frère ne reçoit pas touche dans iPhone

Si je tape sur l'écran seulement topChild et parent recevoir l'événement tactile.

Que dois-je modifier pour propager l'événement tactile à bottomChild?

Le code:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    MYView* parent = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
    parent.tag = 3; 
    parent.backgroundColor = [UIColor redColor]; 

    MYView* bottomChild = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 90, 90)]; 
    bottomChild.tag = 2; 
    bottomChild.backgroundColor = [UIColor blueColor]; 
    [parent addSubview:bottomChild]; 

    MYView* topChild = [[MYView alloc] initWithFrame:CGRectMake(0, 0, 80, 80)]; 
    topChild.tag = 1; 
    topChild.backgroundColor = [UIColor greenColor]; 
    [parent addSubview:topChild]; 
    [self.view addSubview:parent]; 
} 

MYView est une sous-classe de UIView qui se connecte uniquement touchesBegan.

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    NSLog(@"%d", self.tag); 
    [super touchesBegan:touches withEvent:event]; 
} 

Le résultat:

enter image description here

Toucher la zone verte produit le journal suivant:

TouchTest[25062:f803] 1 
TouchTest[25062:f803] 3 

Ma première idée était de faire parent propager tous les touchesSomething appels à ses enfants mais (A) Je soupçonne qu'il pourrait y avoir une solution plus facile n et (B) Je ne sais pas quel enfant a envoyé l'événement à parent, et envoyer des messages touchesSomething deux fois à la même vue peut provoquer des shenanigans.

Après avoir posé la question j'ai trouvé ce post qui suggère d'outrepasser hitTest pour changer la vue qui reçoit les touches. Je vais essayer cette approche et mettre à jour la question si cela fonctionne.

Répondre

1

C'est un problème intéressant qui est probablement quelque chose de mieux résolu par une refonte de la façon dont vous avez structuré les choses. Mais pour que cela fonctionne comme vous le suggérez, vous devez attraper l'événement tactile dans la vue de dessus actuelle, la passer au parent, puis la propager dans toutes les sous-vues de la vue parente. Pour que cela fonctionne, vous devez utiliser le touchesBegan: (ou toute autre méthode que vous utilisez pour intercepter le toucher) pour ne rien faire dans toutes les vues, en faisant l'action uniquement dans la méthode appelée par la vue parente. Ce qui est vraiment une autre façon de dire ne pas gérer les touches dans les vues, les attraper mais notifier l'affichage de la vue parent, puis appeler les méthodes de sous-vue comme nécessaire pour provoquer l'effet que vous voulez.

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

    // Do nothing, parent view calls my parentNotifiedTouchesBegan method 
    [self.superview touchesBegan:touches withEvent:event]; 
} 

- (void) parentNotifiedTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 

    // Act on the touch here just as my sibling views are doing 
} 

Remarque J'ai changé super à self.superview dans ce code. Vous pouvez ou non vouloir également appeler la méthode super en fonction de ce que vous faites, et de l'endroit à appeler qui peut être en parentNotifiedTouchesBegan.

Vous pouvez savoir quelle sous-vue a envoyé l'événement bien sûr, il suffit d'utiliser une méthode personnalisée pour notifier la super-présentation au lieu d'appeler son touchesBegan:. Utilisez un argument self.

+0

Merci Adam! Cette solution serait-elle compatible avec les reconnaisseurs de gestes?À première vue, il me semble que je devrai réimplémenter la roue si je vais dans cette direction. – hpique

+0

Et j'aimerais beaucoup restructurer les choses, mais je ne vois pas comment dans mon cas. topChild a la transparence, topChild et bottomChild peuvent "se déplacer" (ainsi topChild ne peut pas être une sous-vue de bottomChild), et les deux doivent répondre aux touches. – hpique

+0

Il devrait être possible, vous passeriez juste l'objet gestureRecognizer reçu par le rappel au parent plutôt qu'un simple contact. Au moins dans le projet que j'ai à portée de main cela fonctionnerait pour UIPinchGestureRecognizer. –

0

Si vous ne avez pas besoin des touches sur les enfants alors mis

bottomChild.userInteractionEnabled = NO; 
topChild.userInteractionEnabled = NO;