Otter-App-Android-Funkwhale/app/src/main/java/com/github/apognu/otter/views/ExplodeReveal.kt

79 lines
2.3 KiB
Kotlin

package com.github.apognu.otter.views
import android.animation.Animator
import android.animation.ObjectAnimator
import android.graphics.Rect
import android.view.View
import android.view.ViewGroup
import androidx.transition.TransitionValues
import androidx.transition.Visibility
class ExplodeReveal : Visibility() {
val SCREEN_BOUNDS = "screenBounds"
private val locations = IntArray(2)
override fun captureStartValues(transitionValues: TransitionValues) {
super.captureStartValues(transitionValues)
capture(transitionValues)
}
override fun captureEndValues(transitionValues: TransitionValues) {
super.captureEndValues(transitionValues)
capture(transitionValues)
}
override fun onAppear(sceneRoot: ViewGroup, view: View, startValues: TransitionValues?, endValues: TransitionValues?): Animator? {
if (endValues == null) return null
val bounds = endValues.values[SCREEN_BOUNDS] as Rect
val endY = view.translationY
val distance = calculateDistance(sceneRoot, bounds)
val startY = endY + distance
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[SCREEN_BOUNDS] as Rect
val startY = view.translationY
val distance = calculateDistance(sceneRoot, bounds)
val endY = startY + distance
return ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, startY, endY)
}
private fun capture(transitionValues: TransitionValues) {
transitionValues.view.also {
it.getLocationOnScreen(locations)
val left = locations[0]
val top = locations[1]
val right = left + it.width
val bottom = top + it.height
transitionValues.values[SCREEN_BOUNDS] = Rect(left, top, right, bottom)
}
}
private fun calculateDistance(sceneRoot: View, viewBounds: Rect): Int {
sceneRoot.getLocationOnScreen(locations)
val sceneRootY = locations[1]
return when (epicenter) {
is Rect -> return when {
viewBounds.top <= (epicenter as Rect).top -> sceneRootY - (epicenter as Rect).top
else -> sceneRootY + sceneRoot.height - (epicenter as Rect).bottom
}
else -> -sceneRoot.height
}
}
}