前回の続き。日々ScrollViewネタで更新を続けている、、
今回はdeceleration、scrollしながら指を離すと、その瞬間はすぐにscrollが止まらず、勢いを保ったまま徐々にscrollのスピードが落ちる機能のこと。
SwiftUI
のDragGesture
は、これを実装するのに便利な変数が用意されている。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の終了位置として代用する。
ちなみにlocation
とtranslation
の違いは、location
が現在のdrag位置を表しているのに対して、translation
がtranslation = startLocation — location
として表される移動ベクトルであるという点だ。そのため、location
はCGPoint
で、translation
はCGSize
で表現される。
気をつけなければいけないのが、decelerationの有無判定。スクロールを途中で止めて指を離した場合は、decelerationは発生して欲しくない。
実際にdecelerationが必要かどうかは、ドラッグイベントの終了時に、直前との移動量が一定量を超過しているかによって判定する。
abs(value.predictedEndLocation.x — value.location.x) < minDelta
最終的な実装は以下。条件によってはやや不自然な挙動が残るが、雰囲気は再現することができた。
