Question

S'il vous plaît quelqu'un peut aider à trier un noob sur? J'ai posté ce problème sur divers forums et n'a reçu aucune réponse, alors que de nombreuses recherches pour d'autres réponses ont été retrouvés StackOverflow, donc j'espère que c'est l'endroit.

J'ai un BeachView.h (sous-classe de UIScrollView, image d'une plage de sable) recouverte d'un nombre aléatoire de Stone.h (sous-classe de UIImageView, PNG aléatoire d'une pierre, userInteractionEnabled = OUI à accepter des touches) .

Si les touches de l'utilisateur et se déplace sur la plage, il devrait faire défiler. Si l'utilisateur tape une pierre, il doit appeler la méthode « touchedStone ». Si l'utilisateur tape la plage où il n'y a pas de pierre, il doit appeler la méthode « touchedBeach ».

Maintenant, je me rends compte que cela semble simple mort. Tout le monde et tout ce qui me dit que s'il y a quelque chose sur un UIScrollView qui accepte des touches qu'il devrait passer le contrôle sur elle. Alors, quand je touche et faites glisser, il faut faire défiler; mais si je tape, et il est sur une pierre, il faut ignorer les robinets de plage et accepter les robinets en pierre, oui?

Cependant, il semble que les deux vues acceptent le robinet et appeler à la fois touchedStone ET touchedBeach. De plus, le robinet de la plage se produit d'abord, donc je ne peux même mettre dans un « si touchedStone alors ne pas courir touchedBeach » drapeau de type.

Voici un code. Sur BeachView.m


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     if (self.decelerating) { didScroll = YES; }
        else { didScroll = NO; }

     UITouch *touch = [[event allTouches] anyObject];
     CGPoint touchLocation = [touch locationInView:touch.view];
     NSLog(@"touched beach = %@", [touch view]);
     lastTouch = touchLocation;
     [super touchesBegan:touches withEvent:event];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
     didScroll = YES;
     [super touchesMoved:touches withEvent:event];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
     if (didScroll == NO && isPaused == NO) { 
          [self touchedBeach:YES location:lastTouch];
     }
     [super touchesEnded:touches withEvent:event];
}

Stone.m


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     [parent stoneWasTouched]; // parent = ivar pointing from stone to beachview
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
     UITouch *touch = [[event allTouches] anyObject];
     CGPoint touchLocation = [touch locationInView:touch.view];
     NSLog(@"touched stone = %@", [touch view]);
     [parent touchedStone:YES location:touchLocation];
}

Après un robinet de pierre, Mon NSLog ressemble à ceci:


Touched beach = <BeachView: 0x1276a0>
ran touchedBeach
Touched Stone = <Stone: 0x1480c0>
ran touchedStone

Il est en fait en cours d'exécution à la fois. Ce qui est encore plus étrange est que si je prends le touchesBegan et touchesEnded de Stone.m mais laisse userInteractionEnabled = OUI, le Beachview enregistre deux se touche, mais retourne la pierre comme la vue, il a touché (la deuxième fois).


Touched beach = <BeachView: 0x1276a0>
ran touchedBeach
Touched beach = <Stone: 0x1480c0>
ran touchedBeach

Alors S'IL VOUS PLAÎT, j'ai essayé de régler ce problème pendant plusieurs jours. Comment puis-je faire si une pierre taraudée appelle seulement touchedStone et une plage taraudée appelle seulement touchedBeach? Où vais-je tort?

Était-ce utile?

La solution

Avant l'iPhone OS 3.0, hitTest du UIScrollView: withEvent:. Méthode retourne toujours auto pour qu'il reçoive le UIEvent directement, il transmettant uniquement à la sous-vue appropriée si et quand il détermine ce n'est pas lié au défilement ou le zoom

Je ne pouvais pas vraiment commenter l'iPhone OS 3.0 comme il est sous NDA, mais vérifiez votre "iPhone SDK Release Notes pour iPhone OS 3.0 beta 5":)

Si vous devez cibler pré-3.0, vous pouvez passer outre hitTest: withEvent:. En BeachView et définir un indicateur d'ignorer la prochaine touche de plage si le CGPoint est en fait dans une pierre

Mais avez-vous essayé de simplement passer vos appels vers [super touches *: withEvent:] à partir de la fin de vos méthodes redéfinies au début? Cela peut provoquer la prise de pierre pour se produire en premier.

Autres conseils

est vrai, iPhone SDK 3.0 et plus, ne passent pas à des touches -touchesBegan: et -touchesEnded: ** ** UIScrollview sous-classe des méthodes plus. Vous pouvez utiliser les méthodes de touchesShouldBegin et touchesShouldCancelInContentView qui ne sont pas les mêmes.

Si vous voulez vraiment obtenir cette touche, ont un bidouille qui permettent cela.

Dans votre sous-classe de UIScrollView remplacer la méthode hitTest comme ceci:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

  UIView *result = nil;
  for (UIView *child in self.subviews)
    if ([child pointInside:point withEvent:event])
      if ((result = [child hitTest:point withEvent:event]) != nil)
        break;

  return result;
}

passera à vous sous-classe cette touche, mais vous ne pouvez pas annuler les touches à UIScrollView super classe.

J'ai eu un problème similaire avec un simpleView et il est ajouté à un scrollView, et chaque fois que je touchais le simpleView, le scrollView utilisé pour obtenir le toucher et au lieu du SimpleView, le scrollView déplacé. Pour éviter cela, j'ai désactivé la srcolling du scrollView lorsque l'utilisateur a touché le simpleView et sinon le défilement est activé.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    UIView *result = [super hitTest:point withEvent:event] ;
    if (result == simpleView)
    {
        scrollView.scrollEnabled = NO ;
    }
    else
    {
        scrollView.scrollEnabled = YES ;
    }

    return result ;

}

Cela pourrait être lié à un bug dans iOS 7 s'il vous plaît examiner ma question (rapport de bogue soumis)

UIScrollView sous-classe a changé le comportement en iOS 7

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top