I've made a simple class with gestures and I use it in a view.
I'm trying to do a simple swipe to dismiss effect but in the end, it's not that smooth. the translation is great but when the finger release happens, the velocity from the onFling function looks wrong..
class SwipeGestureListener : SimpleOnGestureListener, OnTouchListener {
var context: Context? = null
lateinit var flingDetector: GestureDetector
lateinit var flingY: FlingAnimation
lateinit var springBackTranslationYAnimation: SpringAnimation
var lastY = 0f
val minDistanceUp = 40
val friction = 0.1f
var minFlingArea = 0f
var isItUpDirection = false
constructor(
context: Context?,
dialog: View?
) {
this.context = context
dialog?.let {
it.viewTreeObserver
?.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
minFlingArea = -(it.height + it.top).toFloat() - 100f
it.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
})
}
flingDetector = GestureDetector(context, flingListener)
springBackTranslationYAnimation = SpringAnimation(dialog,
object : FloatPropertyCompat<View>("translationY") {
override fun getValue(view: View): Float {
return view.translationY
}
override fun setValue(
view: View,
value: Float
) {
view.translationY = value
}
})
val springForceY = SpringForce(0f)
springForceY.stiffness = SpringForce.STIFFNESS_VERY_LOW
springForceY.dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY
springBackTranslationYAnimation.spring = springForceY
springBackTranslationYAnimation.addUpdateListener(dynamicAnimationCallback())
flingY = FlingAnimation(dialog, DynamicAnimation.TRANSLATION_Y)
}
private val flingListener: GestureDetector.OnGestureListener =
object : SimpleOnGestureListener() {
override fun onDown(e: MotionEvent?): Boolean {
return true
}
override fun onFling(
downEvent: MotionEvent,
moveEvent: MotionEvent,
velocityX: Float,
velocityY: Float
): Boolean {
val distanceY = downEvent.rawY - moveEvent.rawY
if (distanceY >= minDistanceUp && isItUpDirection) {
flingY.setStartVelocity(if (velocityY > 0) -(velocityY) else velocityY)
.setMinValue(minFlingArea)
.setFriction(friction)
.start()
} else {
springBackTranslationYAnimation.start()
}
return true
}
}
override fun onTouch(view: View, event: MotionEvent): Boolean {
view.performClick()
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
flingY.cancel()
springBackTranslationYAnimation.cancel()
}
MotionEvent.ACTION_MOVE -> {
val deltaY = event.rawY - lastY
view.translationY = deltaY + view.translationY
isItUpDirection = event.rawY < lastY
}
MotionEvent.ACTION_UP -> {
if (!isItUpDirection) {
springBackTranslationYAnimation.start()
}
}
}
lastY = event.rawY
flingDetector.onTouchEvent(event)
return true
}
}
Any idea what's wrong here?
Thanks in advance!
I have implemented gesture for swipe left and swipe right.Please try this one.
Call from your view