Comprobación de la velocidad del iPhone UIScrollView


Sé cómo obtener el contentOffset en movimiento para un UIScrollView, ¿puede alguien explicarme cómo puedo obtener un número real que representa la velocidad actual de un UIScrollView mientras se está rastreando o desacelerando?

Author: NoodleOfDeath, 2010-09-15

8 answers

Tenga estas propiedades en su UIScrollViewDelegate

CGPoint lastOffset;
NSTimeInterval lastOffsetCapture;
BOOL isScrollingFast;

Entonces 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 de esto estoy obteniendo píxeles por milisegundo, que si es mayor que 0.5, he registrado tan rápido, y cualquier cosa a continuación se registra como lento.

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

 54
Author: bandejapaisa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-27 11:57:49

Hay una manera más fácil: compruebe el reconocedor de gestos de panorámica de UIScrollView. Con él, puedes obtener la velocidad así:

CGPoint scrollVelocity = [[_scrollView panGestureRecognizer] velocityInView:self];
 74
Author: karstux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-26 15:05:28

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;
}
 10
Author: Roland Keesom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-25 15:59:35

Respuesta de @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

    }
}
 10
Author: Mat0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-12 16:06:57

Puede ser esto sería útil

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
 6
Author: FunkyKat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-23 12:46:45

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

El contentOffset on movement se puede obtener del método UIScrollViewDelegate, llamado - (void)scrollViewDidScroll:(UIScrollView *)scrollView, consultando scrollView.contentOffset. La velocidad actual puede ser calculada por delta_offset y delta_time.

  • Delta_offset = current_offset-pre_offset;
  • Delta_time = current_time-pre_time;
 3
Author: AechoLiu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-25 15:55:01

2017...

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

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 a digamos 200 - 400 pps (en dispositivos de 2017).

1000 - 3000 es un lanzamiento rápido.

A medida que se ralentiza hasta detenerse, 20 - 30 es común.

Así que 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 móviles. (Que es un gran y difícil tema.)

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

 3
Author: Fattie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-14 10:39:54

Aquí hay 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 te desplazas verticalmente debes usar velocidad.y y también si se está desplazando horizontalmente se debe utilizar la velocidad.x . Generalmente si el valor es más que 1 y menos que -1, representa generalmente desplazamiento rápido. Así que puedes cambiar la velocidad como quieras. +valor significa desplazarse hacia arriba y-valor significa desplazarse hacia abajo.

 0
Author: Chathuranga Silva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-29 10:23:14