Guest User

Untitled

a guest
Feb 17th, 2018
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.16 KB | None | 0 0
  1. import android.animation.Animator
  2. import android.animation.AnimatorListenerAdapter
  3. import android.animation.AnimatorSet
  4. import android.animation.ObjectAnimator
  5. import android.annotation.TargetApi
  6. import android.graphics.Outline
  7. import android.graphics.Rect
  8. import android.os.Build
  9. import android.transition.Transition
  10. import android.transition.TransitionValues
  11. import android.view.View
  12. import android.view.ViewAnimationUtils
  13. import android.view.ViewGroup
  14. import android.view.ViewOutlineProvider
  15. import android.view.animation.LinearInterpolator
  16. import kotlin.math.roundToInt
  17.  
  18.  
  19. @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  20. class CircularReveal : Transition() {
  21.  
  22. companion object {
  23.  
  24. private const val DEFAULT_DURATION = 200L
  25. private const val BOUNDS = "BOUNDS"
  26. private val TRANSITION_PROPERTIES = arrayOf(BOUNDS)
  27. }
  28.  
  29. init {
  30. duration = DEFAULT_DURATION
  31. interpolator = LinearInterpolator()
  32. }
  33.  
  34. override fun getTransitionProperties() = TRANSITION_PROPERTIES
  35.  
  36. override fun captureStartValues(transitionValues: TransitionValues) {
  37. captureValues(transitionValues)
  38. }
  39.  
  40. override fun captureEndValues(transitionValues: TransitionValues) {
  41. captureValues(transitionValues)
  42. }
  43.  
  44. override fun createAnimator(
  45. sceneRoot: ViewGroup,
  46. startValues: TransitionValues?,
  47. endValues: TransitionValues?
  48. ): Animator? {
  49. if (startValues == null || endValues == null) return null
  50.  
  51. val startBounds = startValues.values[BOUNDS] as Rect
  52. val endBounds = endValues.values[BOUNDS] as Rect
  53.  
  54. val isReveal = endBounds.width() > startBounds.width()
  55. val view = endValues.view
  56.  
  57. val translationX = startBounds.centerX() - endBounds.centerX()
  58. val translationY = startBounds.centerY() - endBounds.centerY()
  59. if (isReveal) {
  60. view.translationX = translationX.toFloat()
  61. view.translationY = translationY.toFloat()
  62. }
  63.  
  64. val translate = ObjectAnimator.ofFloat(
  65. view,
  66. View.TRANSLATION_X,
  67. View.TRANSLATION_Y,
  68. if (isReveal) pathMotion.getPath(translationX.toFloat(), translationY.toFloat(), 0f, 0f)
  69. else pathMotion.getPath(0f, 0f, (-translationX).toFloat(), (-translationY).toFloat())
  70. )
  71. val startScale = startBounds.width() / endBounds.width().toFloat()
  72. val endScale = endBounds.width() / startBounds.width().toFloat()
  73. val resize = AnimatorSet().apply {
  74. if (isReveal) {
  75. play(ObjectAnimator.ofFloat(view, View.SCALE_X, startScale, 1F))
  76. .with(ObjectAnimator.ofFloat(view, View.SCALE_Y, startScale, 1F))
  77. } else {
  78. play(ObjectAnimator.ofFloat(view, View.SCALE_X, endScale))
  79. .with(ObjectAnimator.ofFloat(view, View.SCALE_Y, endScale))
  80. }
  81. }
  82.  
  83. val circularReveal: Animator = if (isReveal) {
  84. ViewAnimationUtils.createCircularReveal(
  85. view,
  86. view.width / 2,
  87. view.height / 2,
  88. startBounds.width() / 2F * endScale,
  89. Math.hypot(endBounds.width().toDouble(), endBounds.height().toDouble()).toFloat()
  90. )
  91. } else {
  92. view.layout(startBounds.left, startBounds.top, startBounds.right, startBounds.bottom)
  93. ViewAnimationUtils.createCircularReveal(
  94. view,
  95. view.width / 2,
  96. view.height / 2,
  97. Math.hypot(startBounds.width().toDouble(), startBounds.height().toDouble()).toFloat(),
  98. endBounds.width() / 2F * startScale
  99. ).apply {
  100. addListener(object : AnimatorListenerAdapter() {
  101. override fun onAnimationEnd(animation: Animator) {
  102. view.outlineProvider = object : ViewOutlineProvider() {
  103. override fun getOutline(view: View, outline: Outline) {
  104. val left = ((view.width - endBounds.width() * startScale) / 2).roundToInt()
  105. val top = ((view.height - endBounds.height() * startScale) / 2).roundToInt()
  106. val right = left + Math.min(view.width, view.height)
  107. val bottom = top + Math.min(view.width, view.height)
  108. outline.setOval(left, top, right, bottom)
  109. view.clipToOutline = true
  110. }
  111. }
  112. }
  113. })
  114. }
  115. }
  116. val transition = AnimatorSet().apply {
  117. playTogether(translate, circularReveal, resize)
  118. addListener(object : AnimatorListenerAdapter() {
  119. override fun onAnimationEnd(animation: Animator) {
  120. view.overlay.clear()
  121. }
  122. })
  123. }
  124. return NoPauseAnimator(transition)
  125. }
  126.  
  127. private fun captureValues(transitionValues: TransitionValues) {
  128. val view = transitionValues.view
  129. if (view == null || view.width <= 0 || view.height <= 0) return
  130. transitionValues.values[BOUNDS] = Rect(view.left, view.top, view.right, view.bottom)
  131. }
  132. }
Add Comment
Please, Sign In to add comment