Programmatically triggers scrollViewDidScroll
j'ai quelques UIScrollView
sur une page. Vous pouvez les faire défiler indépendamment ou les verrouiller ensemble et les faire défiler comme un seul. Le problème se produit lorsqu'ils sont verrouillés.
j'utilise UIScrollViewDelegate
et scrollViewDidScroll:
pour suivre le mouvement. Je pose une question sur le contentOffset
du UIScrollView
qui a changé puis reflète le changement à d'autres vues de défilement en définissant leur propriété contentOffset
pour correspondre.
Super.... sauf que j'ai remarqué beaucoup de extra appeler. Changer programmatiquement le contentOffset
de mes vues de défilement déclenche la méthode de délégué scrollViewDidScroll:
à appeler. J'ai essayé d'utiliser setContentOffset:animated:
à la place, mais j'ai toujours la gâchette sur le délégué.
Comment puis-je modifier mon contentOffsets programmatiquement pour ne pas déclencher scrollViewDidScroll:
?
notes de mise en Œuvre....
Chaque UIScrollView
fait partie d'une coutume UIView
qui utilise le motif de délégué pour rappeler à la présentation UIViewController
sous-classe qui coordonne les différentes valeurs contentOffset
.
6 réponses
il est possible de modifier le décalage de contenu d'un UIScrollView
sans déclencher le rappel délégué scrollViewDidScroll:
, en réglant les limites du UIScrollView
avec l'origine réglée sur le décalage de contenu désiré.
CGRect scrollBounds = scrollView.bounds;
scrollBounds.origin = desiredContentOffset;
scrollView.bounds = scrollBounds;
Essayer
id scrollDelegate = scrollView.delegate;
scrollView.delegate = nil;
scrollView.contentOffset = point;
scrollView.delegate = scrollDelegate;
travaillait pour moi.
Qu'en est-il de l'utilisation des propriétés existantes D'UIScrollView?
if(scrollView.isTracking || scrollView.isDragging || scrollView.isDecelerating) {
//your code
}
en simplifiant la réponse de @Tark, vous pouvez positionner le scrollview sans tirer scrollViewDidScroll
sur une ligne comme celle-ci:
scrollView.bounds.origin = CGPoint(x:0, y:100); // whatever values you'd like
une autre approche consiste à ajouter une certaine logique dans votre scrollViewDidScroll delegate pour déterminer si oui ou non le changement de décalage de contenu a été déclenché programatiquement ou par le toucher de l'utilisateur.
- ajouter une variable booléenne "isManualScroll" à votre classe.
- définit sa valeur initiale à false.
- dans scrollviewwillbegindraging l'a mis à true.
- dans votre scrollViewDidScroll vérifiez que est-ce vrai et ne répond que si c'est le cas?
- dans scrollviewdidenddedecelerating le met à false.
- dans scrollviewwillenddraging ajoute de la logique pour la mettre à false si la vitesse est 0 (comme scrollViewDidEndDecelerating ne sera pas appelé dans ce cas).
ce n'est pas une réponse directe à la question, mais si vous recevez ce qui semble être de faux messages de ce genre, cela peut aussi être parce que vous changez les limites. J'utilise un code D'échantillon D'Apple avec une méthode de "tilePages" qui supprime et ajoute subview à un scrollview. Cela résulte rarement en scrollViewDidScroll supplémentaire: messages appelés immédiatement, de sorte que vous obtenez dans une récursion que vous ne vous attendiez certainement pas. Dans mon cas, j'ai eu un méchant impossible de trouver la panne.
ce que j'ai fini par faire était de faire la file d'attente sur la file d'attente principale:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if(scrollView == yourScrollView) {
// dispatch fixes some recursive call to scrollViewDidScroll in tilePages (related to removeFromSuperView)
// The reason can be found here: http://stackoverflow.com/questions/9418311
dispatch_async(dispatch_get_main_queue(), ^{ [self tilePages]; });
}
}