Skip to content

Instantly share code, notes, and snippets.

@vadiole
Last active September 30, 2021 00:08
Show Gist options
  • Save vadiole/25a9457066d93ddd8d807fba663eea09 to your computer and use it in GitHub Desktop.
Save vadiole/25a9457066d93ddd8d807fba663eea09 to your computer and use it in GitHub Desktop.
IOS-like shaking animation
import android.animation.ValueAnimator
import android.view.View
import java.lang.ref.WeakReference
class ShakeController(v: View) {
val view: WeakReference<View> = WeakReference(v)
private var isShaking = false
// rotate and translate bounds, params for random duration
private val rotate = 1f
private val translate = 0.01f
private val minDuration = 120L
private val maxDuration = 150L
private val rotateAnimator: ValueAnimator = ValueAnimator.ofFloat(-rotate, rotate).apply {
val rotateDuration = (minDuration..maxDuration).random()
repeatCount = ValueAnimator.INFINITE
repeatMode = ValueAnimator.REVERSE
duration = rotateDuration
currentPlayTime = (rotateDuration / 2)
}
private val translateAnimator: ValueAnimator = ValueAnimator.ofFloat(
(-translate) * v.resources.displayMetrics.density,
translate * v.resources.displayMetrics.density
).apply {
val rotateDuration = (minDuration..maxDuration).random()
repeatCount = ValueAnimator.INFINITE
repeatMode = ValueAnimator.REVERSE
duration = rotateDuration
currentPlayTime = (rotateDuration / 2)
}
private val rotationListener = ValueAnimator.AnimatorUpdateListener {
if (view.get()?.isAttachedToWindow == true) {
val dX = it.animatedValue as Float
view.get()?.rotation = dX
}
}
private val translateListener = ValueAnimator.AnimatorUpdateListener {
if (view.get()?.isAttachedToWindow == true) {
val dX = it.animatedValue as Float
view.get()?.translationX = dX
}
}
init {
rotateAnimator.addUpdateListener(rotationListener)
translateAnimator.addUpdateListener(translateListener)
}
fun startShaking() {
if (!isShaking) {
isShaking = true
rotateAnimator.start()
translateAnimator.start()
view.get()?.rotation = 0f
view.get()?.translationX = 0f
}
}
fun stopShaking() {
if (isShaking) {
isShaking = false
rotateAnimator.cancel()
translateAnimator.cancel()
view.get()?.rotation = 0f
view.get()?.translationX = 0f
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment