Je suis aux prises avec le problème suivant. Je vais avoir un contrôleur de vue avec vue défilement. Avec cette vue de défilement, l'utilisateur devrait être en mesure de glisser à travers un ensemble de «pages» - comme dans l'application météo d'Apple, donc rien de rare. Ensuite, chaque "page" dans la vue de défilement est vue de la table, montrant une liste d'éléments. Et là, je commence à avoir des problèmes.Comment acheminer correctement les événements UITouch dans la chaîne du répondeur?
La vue de défilement intercepte toutes les touches pour voir si l'utilisateur a déplacé son doigt ou a appuyé sur un point dans une sous-vue, et ne passe pas les événements à ses sous-vues au cas où il reconnaîtrait un mouvement. Ce comportement pose un vrai problème dans mon cas (vue de la table en mode défilement), parce que la vue de table est descendante de la vue de défilement et c'est une vue qui est retournée par le hit-test dans des circonstances normales, ce qui provoque tous les événements sont saisis par la vue de la table, de sorte que la vue de défilement des parents n'est jamais appelée - donc aucun balayage n'est jamais effectué.
Naturellement, lorsque je remplace la méthode hitTest: withEvent: dans ma sous-classe de vue tableau et renvoie une vue supérieure (la vue défilement, en fait), la situation est opposée - l'utilisateur peut parcourir les pages, mais ne peut pas faire défiler la vue tableau. Donc, ce que je dois comprendre est comment - à tout niveau - déterminer quelle action l'utilisateur veut prendre (glisser ou faire défiler vers le haut/le haut de la vue de la table), puis passer le flux d'événements au composant approprié.
Je me bats avec ce problème quelques jours maintenant, mais je ne peux pas surmonter. Voici ce que j'ai fini avec jusqu'à présent. C'est très simplifié ici. Il fait presque ce dont j'ai besoin - sauf que la vue de la table n'est jamais défilée ... S'il vous plaît noter que ma sous-classe vue de la table retourne toujours self.superview, qui est la vue de défilement.
/// UIViewController
- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event {
[super touchesBegan: touches withEvent: event];
/// Save initial touch location for later use
_motionStart = [[touches anyObject] locationInView: self.scrollView];
/// Save reference to initial event
_initialEvent = event;
/// Fire timer
_gestureTimer = [NSTimer scheduledTimerWithTimeInterval: 0.2
target:self selector:@selector(gestureTimer:)
userInfo: touches repeats: NO];
}
- (void) touchesMoved: (NSSet *) touches withEvent: (UIEvent *) event {
if(!_gestureTimer && !_forwardingTouchesToTableView) {
/// If no timer is running and no event forwarding is performed, pass to super
[super touchesMoved: touches withEvent: event];
}
else {
/// Pass event to currently visible tableview
[self.scrollView.centerPage touchesMoved: touches withEvent: event];
}
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded: touches withEvent: event];
if(_forwardingTouchesToTableView) {
[self.scrollView.centerPage touchesEnded: touches withEvent: event];
}
/// Reset state
_motionStart = CGPointZero;
_forwardingTouchesToTableView = NO;
}
- (void) gestureTimer: (NSTimer *) timer {
_gestureTimer = nil;
NSSet *touches = (NSSet *)timer.userInfo;
UITouch *touch = (UITouch *)[touches anyObject];
CGPoint currentTouchLocation = [touch locationInView: self.scrollView];
float deltaX = fabs(_motionStart.x - currentTouchLocation.x);
float deltaY = fabs(_motionStart.y - currentTouchLocation.y);
if(deltaY >= 4.0 && deltaX <= 12.0) {
/// Vertical move, forward to tableview
[self.scrollView cancelTouches];
_forwardingTouchesToTableView = YES;
[self.scrollView.centerPage touchesBegan: touches withEvent: _initialEvent];
_initialEvent = nil;
}
else {
/// Horizontal swipe - just reset state
_initialEvent = nil;
_forwardingTouchesToTableView = NO;
}
}
Pour être honnête, je ne sais pas encore quoi faire. J'ai essayé pas mal de solutions à ce problème, mais aucun d'entre eux n'a vraiment fonctionné. J'apprécierai fortement n'importe quel conseil ou conseil sur ceci. Peut-être que cela suffirait si quelqu'un pouvait expliquer comment la gestion des événements est implémentée par UIScrollView ou UITableView?
Merci pour votre suggestion.
Merci pour votre suggestion, Eiko, mais malheureusement, l'application doit être compatible 3.0 +, c'est pourquoi je suis en train de jouer avec ce genre de choses. J'ai essayé d'implémenter touchesBegan: ... et co. dans les sous-classes personnalisées de UITableView, UIScrollView et UIViewController, mais sans chance jusqu'à présent.la documentation UIScrollView mentionne qu'il utilise des minuteries pour vérifier si elle doit commencer à « glisser » des touches passe aux sous-vues, ce qui est sous-jacente essentiellement ce que je dois faire aussi bien, à l'exception d'ajouter la reconnaissance de geste horizontal/vertical à elle. Je me demande comment il est implémenté dans UIScrollView! – Matthes