SwiftUI: contentOffsetの指定が可能なScrollViewを実装する(4. deceleration編)

p0dee
3 min readJun 7, 2020

--

前回の続き。日々ScrollViewネタで更新を続けている、、

今回はdeceleration、scrollしながら指を離すと、その瞬間はすぐにscrollが止まらず、勢いを保ったまま徐々にscrollのスピードが落ちる機能のこと。

SwiftUIDragGestureは、これを実装するのに便利な変数が用意されている。DragGesture.Value.predictedEndLocation, predictedEndTranslationだ。

A prediction, based on the current drag velocity, of what the final location/translation will be if dragging stopped now.

ドキュメントの記す通り、これらの値は、dragがこの瞬間に終了したと仮定して、現在のdrag速度からscrollの最終位置を推定したものであるため、これをdecelerationの終了位置として代用する。

ちなみにlocationtranslationの違いは、locationが現在のdrag位置を表しているのに対して、translationtranslation = startLocation — locationとして表される移動ベクトルであるという点だ。そのため、locationCGPointで、translationCGSizeで表現される。

気をつけなければいけないのが、decelerationの有無判定。スクロールを途中で止めて指を離した場合は、decelerationは発生して欲しくない。

実際にdecelerationが必要かどうかは、ドラッグイベントの終了時に、直前との移動量が一定量を超過しているかによって判定する。

abs(value.predictedEndLocation.x — value.location.x) < minDelta

最終的な実装は以下。条件によってはやや不自然な挙動が残るが、雰囲気は再現することができた。

--

--

No responses yet