Skip to content

Instantly share code, notes, and snippets.

@huan-nguyen
Created September 24, 2018 13:16
Show Gist options
  • Save huan-nguyen/d772119f2694489216feac33d5b0f094 to your computer and use it in GitHub Desktop.
Save huan-nguyen/d772119f2694489216feac33d5b0f094 to your computer and use it in GitHub Desktop.
SlideExplode
import android.animation.Animator
import android.animation.ObjectAnimator
import android.graphics.Rect
import android.transition.TransitionValues
import android.transition.Visibility
import android.view.View
import android.view.ViewGroup
private const val KEY_SCREEN_BOUNDS = "screenBounds"
/**
* A simple Transition which allows the views above the epic centre to transition upwards and views
* below the epic centre to transition downwards.
*/
class SlideExplode : Visibility() {
private val mTempLoc = IntArray(2)
private fun captureValues(transitionValues: TransitionValues) {
val view = transitionValues.view
view.getLocationOnScreen(mTempLoc)
val left = mTempLoc[0]
val top = mTempLoc[1]
val right = left + view.width
val bottom = top + view.height
transitionValues.values[KEY_SCREEN_BOUNDS] = Rect(left, top, right, bottom)
}
override fun captureStartValues(transitionValues: TransitionValues) {
super.captureStartValues(transitionValues)
captureValues(transitionValues)
}
override fun captureEndValues(transitionValues: TransitionValues) {
super.captureEndValues(transitionValues)
captureValues(transitionValues)
}
override fun onAppear(sceneRoot: ViewGroup, view: View,
startValues: TransitionValues?, endValues: TransitionValues?): Animator? {
if (endValues == null) return null
val bounds = endValues.values[KEY_SCREEN_BOUNDS] as Rect
val endY = view.translationY
val startY = endY + calculateDistance(sceneRoot, bounds)
return ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, startY, endY)
}
override fun onDisappear(sceneRoot: ViewGroup, view: View,
startValues: TransitionValues?, endValues: TransitionValues?): Animator? {
if (startValues == null) return null
val bounds = startValues.values[KEY_SCREEN_BOUNDS] as Rect
val startY = view.translationY
val endY = startY + calculateDistance(sceneRoot, bounds)
return ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, startY, endY)
}
private fun calculateDistance(sceneRoot: View, viewBounds: Rect): Int {
sceneRoot.getLocationOnScreen(mTempLoc)
val sceneRootY = mTempLoc[1]
return when {
epicenter == null -> -sceneRoot.height
viewBounds.top <= epicenter.top -> sceneRootY - epicenter.top
else -> sceneRootY + sceneRoot.height - epicenter.bottom
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment