Prédire le décalage au repos dans un UIScrollView après décélération
-
22-07-2019 - |
Question
J'aimerais pouvoir prédire le décalage de repos final dans un UIScrollView après un geste rapide. Il n’a pas besoin d’être précis au pixel près, mais suffisamment proche pour que l’utilisateur ne perçoive pas de différence (c’est-à-dire qu’il ne se déplace pas excessivement moins ou plus qu’avant).
Je sais que quelqu'un demandera, alors: pourquoi? J'ai un contrôle de menu semblable à une vue de tableau à l'intérieur d'un UIScrollView. Je voudrais faire en sorte que l'élément de menu le plus en haut soit entièrement affiché et aligné au sommet de UIScrollView. La fonctionnalité de pagination d’UIScrollView n’est pas tout à fait ce que je veux, car un puissant film ne dépasse pas les multiples des limites de la vue.
La gestion des événements tactiles normaux est assez simple. Sur touchesEnded: withEvent:
, je peux faire défiler jusqu'à l'élément de menu complet le plus proche. La partie difficile est la décélération.
Il existe deux constantes pour le taux de décélération, UIScrollViewDecelerationRateNormal
et UIScrollViewDecelerationRateFast
. Leurs valeurs sont 0,998 et 0,990 dans iPhone OS 3.0. J'ai essayé de comprendre le calcul utilisé par Apple pour ralentir les mouvements, mais j'arrive vide.
Si je peux prédire avec une certaine précision le décalage de repos final, je peux simplement utiliser scrollRectToVisible: animated:
au début de la décélération pour passer à un décalage avec un élément de menu affleurant au haut de la vue. limites.
Est-ce que des personnes douées pour les mathématiques savent ce que Apple peut faire pendant la décélération? Devrais-je collecter un grand nombre d'événements de décélération, les représenter graphiquement et trouver quelque chose de proche?
La solution
Contrôle le targetContentOffset d'UIScrollView sous iOS 5
iOS5 UIScrollViewDelegate
> a une nouvelle méthode: scrollViewWillEndDragging: withVelocity: targetContentOffset:
.
Cela correspond parfaitement à ce que vous voulez faire.
Cette méthode n'est pas appelée lorsque la valeur de la vue de défilement & # 8217; s La propriété pagingEnabled a la valeur YES. Votre application peut changer la valeur du paramètre targetContentOffset pour ajuster où le scrollview termine son animation de défilement.
Solution alternative pour iOS4 et inférieur
Modifiez la UIScrollView
decelerationRate
à UIScrollViewDecelerationFast
, puis dans scrollViewDidEndDecelerating
déplacez le curseur sur la page " la plus proche.
La décélération rapide rend l’arrêt complet / glissant sur un peu plus naturel / moins odieux.
Autres conseils
Vous pouvez regarder la vitesse de défilement pendant le ralentissement de UIScrollView et lorsque la vitesse tombe sous une certaine valeur, accrochez-vous sur l'élément de menu le plus proche.
Vous souhaiterez probablement implémenter UIScrollViewDelegate
méthodes scrollViewDidEndDragging: willDecelerate:
et . : //developer.apple.com/library/ios/documentation/uikit/reference/UIScrollViewDelegate_Protocol/Reference/UIScrollViewDelegate.html#//apple_ref/occ/intfm/UIScrollViewDelegate/scrollViewDidScrollView 3 scrollViewDidScroll: . Lorsque l'utilisateur lève le doigt pour terminer un geste de défilement, scrollViewDidEndDragging: willDecelerate:
sera appelé. Commencez à surveiller les événements scrollViewDidScroll:
et observez le delta entre la position actuelle de UIScrollView
et sa position précédente, divisées par le delta temporel:
float velocity = (currentPosition - lastPosition) / (currentTime - lastTime);
Lorsque la vélocité tombe en dessous d'une valeur minimale, appelez scrollRectToVisible: animated:
sur UIScrollView
.
Je ne peux pas commenter (je suppose qu'il me faut 50 reps), ce n'est donc pas une réponse complète, mais étant donné les valeurs de décélération de 0,998 et 0,990, mon instinct est qu'elles ne font que multiplier la vitesse actuelle par la vitesse de décélération de chaque image.