Skip to content

Instantly share code, notes, and snippets.

@valkriaine
Last active May 26, 2022 17:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save valkriaine/bb0672445f9b20fcc5594a071f3c7cce to your computer and use it in GitHub Desktop.
Save valkriaine/bb0672445f9b20fcc5594a071f3c7cce to your computer and use it in GitHub Desktop.
Add bouncy effect to any recyclerview
// add bouncy effect to this view
var overscrollAnimationSize = 0.5f
var flingAnimationSize = 0.5f
@Suppress("MemberVisibilityCanBePrivate")
var dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY
set(value)
{
field = value
this.spring.spring = SpringForce()
.setFinalPosition(0f)
.setDampingRatio(value)
.setStiffness(stiffness)
}
@Suppress("MemberVisibilityCanBePrivate")
var stiffness = SpringForce.STIFFNESS_LOW
set(value)
{
field = value
this.spring.spring = SpringForce()
.setFinalPosition(0f)
.setDampingRatio(dampingRatio)
.setStiffness(value)
}
var spring: SpringAnimation = SpringAnimation(this, SpringAnimation.TRANSLATION_Y)
.setSpring(
SpringForce()
.setFinalPosition(0f)
.setDampingRatio(dampingRatio)
.setStiffness(stiffness)
)
var touched: Boolean = false
var orientation : Int? = 1
set(value)
{
field = value
setupDirection(value)
}
override fun setLayoutManager(layout: LayoutManager?)
{
super.setLayoutManager(layout)
if (layout is LinearLayoutManager)
{
orientation = layout.orientation
setupDirection(orientation)
}
}
private fun setupDirection(orientation : Int?)
{
if (stiffness > 0)
{
when (orientation)
{
HORIZONTAL -> spring = SpringAnimation(this, SpringAnimation.TRANSLATION_X)
.setSpring(SpringForce()
.setFinalPosition(0f)
.setDampingRatio(dampingRatio)
.setStiffness(stiffness))
VERTICAL -> spring = SpringAnimation(this, SpringAnimation.TRANSLATION_Y)
.setSpring(SpringForce()
.setFinalPosition(0f)
.setDampingRatio(dampingRatio)
.setStiffness(stiffness))
}
}
}
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(e: MotionEvent?): Boolean
{
touched = when (e?.actionMasked)
{
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> false
else -> true
}
return super.onTouchEvent(e)
}
// call this at the end of init{...}
// example: configureEdgeEffect(this)
private fun configureEdgeEffect(rc : RecyclerView)
{
//create edge effect
this.edgeEffectFactory = object : EdgeEffectFactory()
{
override fun createEdgeEffect(recyclerView: RecyclerView, direction: Int): EdgeEffect
{
return object : EdgeEffect(recyclerView.context)
{
override fun onPull(deltaDistance: Float)
{
super.onPull(deltaDistance)
onPullAnimation(deltaDistance)
}
override fun onPull(deltaDistance: Float, displacement: Float)
{
super.onPull(deltaDistance, displacement)
onPullAnimation(deltaDistance)
}
private fun onPullAnimation(deltaDistance: Float)
{
if (orientation == VERTICAL)
{
val delta: Float =
if (direction == DIRECTION_BOTTOM)
-1 * recyclerView.width * deltaDistance * overscrollAnimationSize
else
1 * recyclerView.width * deltaDistance * overscrollAnimationSize
rc.translationY += delta
spring.cancel()
}
else
{
val delta: Float =
if (direction == DIRECTION_RIGHT)
-1 * recyclerView.width * deltaDistance * overscrollAnimationSize
else
1 * recyclerView.width * deltaDistance * overscrollAnimationSize
rc.translationX += delta
spring.cancel()
}
}
override fun onRelease()
{
super.onRelease()
if (touched)
return
spring.start()
}
override fun onAbsorb(velocity: Int)
{
super.onAbsorb(velocity)
if (orientation == VERTICAL)
{
val v: Float = if (direction == DIRECTION_BOTTOM)
-1 * velocity * flingAnimationSize
else
1 * velocity * flingAnimationSize
spring.setStartVelocity(v).start()
}
else
{
val v: Float = if (direction == DIRECTION_RIGHT)
-1 * velocity * flingAnimationSize
else
1 * velocity * flingAnimationSize
spring.setStartVelocity(v).start()
}
}
override fun draw(canvas: Canvas?): Boolean
{
setSize(0, 0)
return super.draw(canvas)
}
}
}
}
@valkriaine
Copy link
Author

copy and paste this code anywhere in your recyclerview class, and call configureEdgeEffect() under init{...}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment