web-dev-qa-db-ja.com

iPhone UIScrollView速度チェック

UIScrollViewの移動時にcontentOffsetを取得する方法を知っています。追跡または減速しているときに、UIScrollViewの現在の速度を表す実際の数値を取得する方法を誰かに説明してもらえますか?

36
NoodleOfDeath

あなたの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を超える場合、高速でログに記録し、それ以下は低速でログに記録します。

これを使用して、アニメーション化されたテーブルビューのいくつかのセルをロードします。ユーザーが高速でスクロールしているときにロードすると、スクロールがうまくいきません。

56
bandejapaisa

より簡単な方法があります。UISCrollviewのパンジェスチャー認識機能を確認してください。それを使用すると、次のように速度を取得できます。

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

変換された@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

    }
}
14
Mat0

単純な速度計算の場合(他のすべての答えはより複雑です):

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

これは役に立つかもしれません

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

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

もちろん、1秒あたりのポイント数で速度を求めています。

人間は約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
    }

これは、携帯電話の「スキミングエンジニアリング」の基礎です。 (これは大きくて難しいトピックです。)

これは完全なスキミングソリューションではないことに注意してください。また、「停止した」「画面を閉じた」などの異常なケースにも注意する必要があります。

5
Fattie

ScrollviewのcontentOffsetを取得する方法についての PageControl サンプルコードを確認できます。

動きのcontentOffsetは、_scrollView.contentOffset_をクエリすることにより、- (void)scrollViewDidScroll:(UIScrollView *)scrollViewという名前のUIScrollViewDelegateメソッドから取得できます。現在の速度は、delta_offsetおよびdelta_timeによって計算できます。

  • Delta_offset = current_offset-pre_offset;
  • Delta_time = current_time-pre_time;
3
AechoLiu

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.
    }
}

したがって、垂直方向にスクロールする場合は、velocity.yを使用し、水平方向にスクロールする場合は、velocity.xを使用する必要があります。一般に、値が1より大きく-1より小さい場合、一般的に高速スクロールを表します。したがって、速度を好きなように変更できます。 + valueは上にスクロールすることを意味し、-valueは下にスクロールすることを意味します。

1