iPhone UIScrollView Проверка скорости - PullRequest
35 голосов
/ 15 сентября 2010

Я знаю, как получить contentOffset при перемещении для UIScrollView, может кто-нибудь объяснить мне, как я могу получить фактическое число, представляющее текущую скорость UIScrollView, пока он отслеживает или замедляет?

Ответы [ 8 ]

75 голосов
/ 26 марта 2012

Есть более простой способ: проверить распознаватель жестов панорамирования UISCrollview. С его помощью вы можете получить скорость примерно так:

CGPoint scrollVelocity = [[_scrollView panGestureRecognizer] velocityInView:self];
56 голосов
/ 14 марта 2012

Имейте эти свойства на вашем UIScrollViewDelegate

CGPoint lastOffset;
NSTimeInterval lastOffsetCapture;
BOOL isScrollingFast;

Затем получите этот код для вашего 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;
    }
}

И из этого я получаю пиксели в миллисекунду, что, если большечем 0,5, я вошел в систему как быстрый, а все, что ниже, записано как медленное.

Я использую это для загрузки некоторых ячеек в анимированном виде таблицы.Он не так хорошо прокручивается, если я загружаю их, когда пользователь быстро прокручивает.

12 голосов
/ 12 апреля 2016

Преобразованный ответ @bandejapaisa в Swift 2.2:

Свойства, используемые UIScrollViewDelegate:

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

И функция 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 голосов
/ 25 марта 2013

Для простого расчета скорости (все остальные ответы более сложные):

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat scrollSpeed = scrollView.contentOffset.y - previousScrollViewYOffset;
    previousTableViewYOffset = scrollView.contentOffset.y;
}
6 голосов
/ 23 апреля 2013

Может быть, это будет полезно

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
3 голосов
/ 14 июля 2017

2017 ...

Это очень легко сделать с современной версией 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)")

Конечно, вам нужна скорость в пунктах в секунду, что и есть.

Люди тянут, скажем, 200 - 400 pps (на устройствах 2017 года).

1000 - 3000 - быстрый бросок.

Когда он замедляется до остановки, 20- 30 часто встречается.

Так что очень часто вы будете видеть такой код ..

    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
    }

Это основа для "скимминга" на мобильных телефонах.(Это большая и сложная тема.)

Обратите внимание, что это не полное решение скимминга;Вы также должны заботиться о необычных случаях, таких как «он остановился», «только что закрытый экран» и т. д. и т. д.

3 голосов
/ 15 сентября 2010

Вы можете увидеть Пример кода PageControl о том, как получить contentOffset scrollview.

Движение contentOffset можно получить с помощью метода UIScrollViewDelegate с именем - (void)scrollViewDidScroll:(UIScrollView *)scrollView, запросив scrollView.contentOffset. Текущая скорость может быть рассчитана с помощью delta_offset и delta_time.

  • Delta_offset = current_offset - pre_offset;
  • Delta_time = current_time - pre_time;
0 голосов
/ 29 апреля 2016

Вот еще один умный способ сделать это в 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.
    }
}

Так что, если вы прокручиваете вертикально, вы должны использовать speed.y, а также, если вы прокручиваете горизонтально, вы должны использовать Speed.x Как правило, если значение больше 1 и меньше -1, это обычно означает быструю прокрутку. Таким образом, вы можете изменить скорость, как вы хотите. + значение означает прокрутку вверх, а -значение означает прокрутку вниз.

...