2010-09-15 18 views
32

Sé cómo hacer que contentOffset se mueva para UIScrollView, ¿alguien me puede explicar cómo puedo obtener un número real que represente la velocidad actual de UIScrollView mientras se rastrea o desacelera?iPhone UIScrollView Speed ​​Check

+0

No es un gran problema, pero le puse la solución moderna a esta vieja pregunta en la parte inferior. – Fattie

Respuesta

51

tener estas propiedades en su UIScrollViewDelegate

CGPoint lastOffset; 
NSTimeInterval lastOffsetCapture; 
BOOL isScrollingFast; 

Luego tienen el 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 que estoy recibiendo píxeles por milisegundo, lo que si es mayor que 0.5, he iniciado sesión tan rápido, y todo lo que está debajo 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.

+0

Gracias por esto. Útil :) – Accatyyc

+1

brillante, esto era exactamente lo que estaba planeando. – jfisk

+4

gracias por una buena solución, lo único que cambiaría es reemplazar 0.1 con 'captureInterval' const y usarlo también en el cálculo de' scrollSpeedNotAbs' para aumentar la legibilidad del algoritmo (ya que el cerebro se detiene en '* 10' porque la fórmula general de velocidad es distancia/tiempo). – zubko

3

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

El contentOffset en movimiento puede obtenerse del método UIScrollViewDelegate, llamado - (void)scrollViewDidScroll:(UIScrollView *)scrollView, mediante la consulta 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;
+0

Oh, tengo una velocidad en tiempo real usando la distancia en el tiempo Supongo –

+1

La hora actual puede ser obtenida por CACurrentMediaTime() en el marco de QuartzCore. Entonces puedes calcular la velocidad por distancia y tiempo. – AechoLiu

70

Hay una manera más fácil: revise el reconocedor de gestos panorámicos de UISCrollview. Con ella, se puede obtener la velocidad de este modo:

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

¡Práctico! El único inconveniente es que 'scrollVelocity' será 0.0f inmediatamente después de que el usuario levanta su dedo (porque esto termina el gesto de panoramización). Por lo tanto, es una buena manera de medir la velocidad mientras se arrastra la vista de desplazamiento, pero no funciona si se hace clic. –

+2

..y, por supuesto, el reconocimiento panGesture solo está expuesto en iOS 5 en adelante. – bandejapaisa

+0

es la velocidad de desplazamiento un punto porque registra velocidades verticales y horizontales? –

9

Para un cálculo sencillo de la velocidad (Todas las otras respuestas son más complicadas):

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

Eso era exactamente lo que necesitaba, gracias ! – Giovanni

+0

Esto me ayudó también, ¡gracias! Otras personas podrían considerar tirar un fabsf() allí, solo para obtener el valor absoluto. – Andrew

+1

Debe tener en cuenta el tiempo, de lo contrario, la velocidad fluctuará. –

6

puede ser esto sería útil

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

quiero mencionar, este es un ejemplo de salida de velocidad: '(0.0, -5.35356)'. Desplazarse por el eje y, 5.35 .. -> 15 puntos por 'desplazamiento de scrollViewDidScroll' :) Entonces, 5 es muy rápido. –

9

Antiguo @bandejapaisa respuesta 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 

    } 
} 
0

Aquí es otra forma inteligente de hacer esto en 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. 
    } 
} 

Así que si el desplazamiento vertical se debería 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.

+0

¿Cómo ajustar la velocidad? –

+0

¿Qué quieres decir? :) –

+0

dijiste en tu respuesta 'Entonces puedes cambiar la velocidad como quieras'. Entonces me preguntaba, ¿cómo cambias la velocidad del rollo? –

1

2017 ...

Es muy fácil de hacer esto con moderna 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 quieren que la velocidad en puntos por segundo, que es lo que es.

Humanos arrastran a decir 200 - 400 pps (en dispositivos 2017).

1000 - 3000 es un lanzamiento rápido.

Cuando desacelera hasta detenerse, 20 - 30 es común.

Así que muy a menudo verá 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 
    } 

Ésta es la base para el "skimming ingeniería" en los móviles. (Que es un tema extenso y difícil.)

Tenga en cuenta que no es una solución de desnatado completa; también tiene que preocuparse por casos inusuales como "se ha detenido", "la pantalla acaba de cerrarse", etc.

Cuestiones relacionadas