Je sais comment obtenir le contentOffset en mouvement pour un UIScrollView, quelqu'un peut-il m'expliquer comment obtenir un nombre réel qui représente la vitesse actuelle d'un UIScrollView pendant le suivi ou la décélération?
Ayez ces propriétés sur votre UIScrollViewDelegate
CGPoint lastOffset;
NSTimeInterval lastOffsetCapture;
BOOL isScrollingFast;
Ensuite, ayez ce code pour votre scrollViewDidScroll:
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint currentOffset = scrollView.contentOffset;
NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval timeDiff = currentTime - lastOffsetCapture;
if(timeDiff > 0.1) {
CGFloat distance = currentOffset.y - lastOffset.y;
//The multiply by 10, / 1000 isn't really necessary.......
CGFloat scrollSpeedNotAbs = (distance * 10) / 1000; //in pixels per millisecond
CGFloat scrollSpeed = fabsf(scrollSpeedNotAbs);
if (scrollSpeed > 0.5) {
isScrollingFast = YES;
NSLog(@"Fast");
} else {
isScrollingFast = NO;
NSLog(@"Slow");
}
lastOffset = currentOffset;
lastOffsetCapture = currentTime;
}
}
Et à partir de cela, j'obtiens des pixels par milliseconde, ce qui est supérieur à 0,5, je me suis connecté aussi rapidement et tout ce qui est ci-dessous est enregistré comme lent.
Je l'utilise pour charger quelques cellules sur une vue tableau animée. Il ne défile pas si bien si je les charge lorsque l'utilisateur défile rapidement.
Il existe un moyen plus simple: vérifiez la reconnaissance des mouvements de panoramique de UISCrollview. Avec lui, vous pouvez obtenir la vitesse comme suit:
CGPoint scrollVelocity = [[_scrollView panGestureRecognizer] velocityInView:self];
Réponse @bandejapaisa convertie en Swift 2.2:
Propriétés utilisées par UIScrollViewDelegate:
var lastOffset:CGPoint? = CGPointMake(0, 0)
var lastOffsetCapture:NSTimeInterval? = 0
var isScrollingFast: Bool = false
Et la fonction scrollViewDidScroll:
func scrollViewDidScroll(scrollView: UIScrollView) {
let currentOffset = scrollView.contentOffset
let currentTime = NSDate().timeIntervalSinceReferenceDate
let timeDiff = currentTime - lastOffsetCapture!
let captureInterval = 0.1
if(timeDiff > captureInterval) {
let distance = currentOffset.y - lastOffset!.y // calc distance
let scrollSpeedNotAbs = (distance * 10) / 1000 // pixels per ms*10
let scrollSpeed = fabsf(Float(scrollSpeedNotAbs)) // absolute value
if (scrollSpeed > 0.5) {
isScrollingFast = true
print("Fast")
}
else {
isScrollingFast = false
print("Slow")
}
lastOffset = currentOffset
lastOffsetCapture = currentTime
}
}
Pour un calcul de vitesse simple (toutes les autres réponses sont plus compliquées):
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat scrollSpeed = scrollView.contentOffset.y - previousScrollViewYOffset;
previousTableViewYOffset = scrollView.contentOffset.y;
}
Cela pourrait être utile
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
C'est très facile à faire avec Swift/iOS moderne:
var previousScrollMoment: Date = Date()
var previousScrollX: CGFloat = 0
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let d = Date()
let x = scrollView.contentOffset.x
let elapsed = Date().timeIntervalSince(previousScrollMoment)
let distance = (x - previousScrollX)
let velocity = (elapsed == 0) ? 0 : fabs(distance / CGFloat(elapsed))
previousScrollMoment = d
previousScrollX = x
print("vel \(velocity)")
Bien sûr, vous voulez la vitesse en points par seconde, c'est ce que c'est.
Les humains traînent, disons, 200 à 400 points par seconde (sur les appareils de 2017).
1000 - 3000 est un lancer rapide.
Comme il ralentit jusqu'à un arrêt, 20 - 30 est courant.
Donc, très souvent, vous verrez du code comme celui-ci ..
if velocity > 300 {
// the display is >skimming<
some_global_doNotMakeDatabaseCalls = true
some_global_doNotRenderDiagrams = true
}
else {
// we are not skimming, ok to do calculations
some_global_doNotMakeDatabaseCalls = false
some_global_doNotRenderDiagrams = false
}
C'est la base de "l'ingénierie d'écrémage" sur les mobiles. (Ce qui est un sujet vaste et difficile.)
Notez que ce n'est pas une solution d'écrémage complète; vous devez également prendre soin de cas inhabituels comme "il s'est arrêté" "l'écran vient de se fermer", etc., etc.
Vous pouvez voir PageControl exemple de code sur la façon d'obtenir le contentOffset de scrollview.
La contentOffset
en mouvement peut être obtenue à partir de la méthode UIScrollViewDelegate
, nommée - (void)scrollViewDidScroll:(UIScrollView *)scrollView
, en interrogeant scrollView.contentOffset
. La vitesse actuelle peut être calculée par delta_offset et delta_time.
Voici une autre façon intelligente de le faire dans Swift: -
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if velocity.y > 1.0 || velocity.y < -1.0 && self.sendMessageView.isFirstResponder() {
// Somthing you want to do when scrollin fast.
// Generally fast Vertical scrolling.
}
}
Donc, si vous faites défiler verticalement, vous devez utiliser velocity.y et aussi si vous faites défiler horizontalement, vous devez utiliser velocity.x. Généralement, si la valeur est supérieure à 1 et inférieure à -1, elle représente un défilement généralement rapide. Vous pouvez donc modifier la vitesse comme vous le souhaitez. + value signifie défiler vers le haut et -value signifie défiler vers le bas.