iPhone UIScrollView Verificación de velocidad

Sé cómo hacer que contentOffset se mueva en UIScrollView, ¿alguien me puede explicar cómo puedo obtener un número real que represente la velocidad actual de UIScrollView mientras se está rastreando o desacelerando?

Tener estas propiedades en su UIScrollViewDelegate

CGPoint lastOffset; NSTimeInterval lastOffsetCapture; BOOL isScrollingFast; 

Luego tenga este código para su 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; } } 

Y a partir de esto obtengo píxeles por milisegundo, que si es mayor que 0.5, he iniciado sesión tan rápido, y todo lo demás se registra como lento.

Lo uso para cargar algunas celdas en una vista de tabla animada. No se desplaza tan bien si los cargo cuando el usuario se desplaza rápidamente.

Hay una manera más fácil: verifique el reconocedor de gestos panorámicos de UISCrollview. Con él, puedes obtener la velocidad de la siguiente manera:

 CGPoint scrollVelocity = [[_scrollView panGestureRecognizer] velocityInView:self]; 

Para un cálculo de velocidad simple (todas las otras respuestas son más complicadas):

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat scrollSpeed = scrollView.contentOffset.y - previousScrollViewYOffset; previousTableViewYOffset = scrollView.contentOffset.y; } 

Respuesta @bandejapaisa convertida a Swift 2.2:

Propiedades utilizadas por UIScrollViewDelegate:

 var lastOffset:CGPoint? = CGPointMake(0, 0) var lastOffsetCapture:NSTimeInterval? = 0 var isScrollingFast: Bool = false 

Y la función 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 } } 

Puede ser esto sería útil

 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset 

Puede ver el código de muestra de PageControl sobre cómo obtener el contentOffset de scrollview.

El contentOffset en movimiento se puede obtener del método UIScrollViewDelegate , llamado - (void)scrollViewDidScroll:(UIScrollView *)scrollView , al consultar scrollView.contentOffset . La velocidad actual se puede calcular mediante delta_offset y delta_time.

  • Delta_offset = current_offset – pre_offset;
  • Delta_time = current_time – pre_time;

2017 …

Es muy fácil hacer esto con el moderno Swift / iOS:

 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)") 

Por supuesto que quieres la velocidad en puntos por segundo, que es lo que es.

Los humanos arrastran, digamos, 200 – 400 pps (en dispositivos 2017).

1000 – 3000 es un lanzamiento rápido.

A medida que desacelera hasta detenerse, 20 – 30 es común.

Muy a menudo verás código como este ..

  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 } 

Esta es la base para la "ingeniería de skimming" en los teléfonos móviles. (Que es un tema grande y difícil)

Tenga en cuenta que eso no es una solución de desnatado completa; también debe ocuparse de casos inusuales como "se ha detenido", "la pantalla se ha cerrado", etc.

Aquí hay otra forma inteligente de hacerlo en SWIFT:

 func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { if velocity.y > 1.0 || velocity.y < -1.0 && self.sendMessageView.isFirstResponder() { // Somthing you want to do when scrollin fast. // Generally fast Vertical scrolling. } } 

Entonces, si se desplaza verticalmente, debe usar velocity.y y también, si está desplazándose horizontalmente, debe usar velocity.x. En general, si el valor es más de 1 y menor que -1, generalmente representa un desplazamiento rápido. Entonces puedes cambiar la velocidad como quieras. + valor significa desplazarse hacia arriba y -valor significa desplazarse hacia abajo.