react-native-navigation的迁移库

TransitionAnimatorCreator.kt 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package com.reactnativenavigation.views.element
  2. import android.animation.Animator
  3. import android.animation.AnimatorListenerAdapter
  4. import android.animation.AnimatorSet
  5. import android.view.View
  6. import android.view.ViewGroup
  7. import android.widget.FrameLayout
  8. import androidx.core.animation.doOnCancel
  9. import androidx.core.animation.doOnEnd
  10. import com.facebook.react.uimanager.ViewGroupManager
  11. import com.reactnativenavigation.R
  12. import com.reactnativenavigation.parse.AnimationOptions
  13. import com.reactnativenavigation.utils.ViewTags
  14. import com.reactnativenavigation.utils.ViewUtils
  15. import java.util.*
  16. open class TransitionAnimatorCreator {
  17. fun create(fadeAnimation: AnimationOptions, transitions: TransitionSet): AnimatorSet {
  18. if (transitions.isEmpty) return AnimatorSet()
  19. recordIndices(transitions)
  20. reparentViews(transitions)
  21. val animators = ArrayList<Animator>()
  22. animators.addAll(createSharedElementTransitionAnimators(transitions.validSharedElementTransitions))
  23. animators.addAll(createElementTransitionAnimators(transitions.validElementTransitions))
  24. setAnimatorsDuration(animators, fadeAnimation)
  25. val set = AnimatorSet()
  26. set.doOnEnd { restoreViewsToOriginalState(transitions) }
  27. set.doOnCancel { restoreViewsToOriginalState(transitions) }
  28. set.playTogether(animators)
  29. return set
  30. }
  31. private fun recordIndices(transitions: TransitionSet) {
  32. transitions.forEach {
  33. it.view.setTag(R.id.original_index_in_parent, ViewUtils.getIndexInParent(it.view))
  34. }
  35. }
  36. private fun setAnimatorsDuration(animators: Collection<Animator>, fadeAnimation: AnimationOptions) {
  37. for (animator in animators) {
  38. if (animator is AnimatorSet) {
  39. setAnimatorsDuration(animator.childAnimations, fadeAnimation)
  40. } else if (animator.duration.toInt() <= 0) {
  41. animator.duration = fadeAnimation.duration.toLong()
  42. }
  43. }
  44. }
  45. private fun reparentViews(transitions: TransitionSet) {
  46. transitions.transitions
  47. .sortedBy { ViewGroupManager.getViewZIndex(it.view) }
  48. .forEach {
  49. reparent(it)
  50. }
  51. }
  52. private fun createSharedElementTransitionAnimators(transitions: List<SharedElementTransition>): List<AnimatorSet> {
  53. val animators: MutableList<AnimatorSet> = ArrayList()
  54. for (transition in transitions) {
  55. animators.add(createSharedElementAnimator(transition))
  56. }
  57. return animators
  58. }
  59. private fun createSharedElementAnimator(transition: SharedElementTransition): AnimatorSet {
  60. val set = AnimatorSet()
  61. set.playTogether(transition.createAnimators())
  62. set.addListener(object : AnimatorListenerAdapter() {
  63. override fun onAnimationStart(animation: Animator) {
  64. transition.from.alpha = 0f
  65. }
  66. })
  67. return set
  68. }
  69. private fun createElementTransitionAnimators(transitions: List<ElementTransition>): List<AnimatorSet> {
  70. val animators: MutableList<AnimatorSet> = ArrayList()
  71. for (transition in transitions) {
  72. animators.add(transition.createAnimators())
  73. }
  74. return animators
  75. }
  76. private fun restoreViewsToOriginalState(transitions: TransitionSet) {
  77. mutableListOf<Transition>().apply {
  78. addAll(transitions.validSharedElementTransitions)
  79. addAll(transitions.validElementTransitions)
  80. sortBy { ViewGroupManager.getViewZIndex(it.view) }
  81. sortBy { it.view.getTag(R.id.original_index_in_parent) as Int}
  82. forEach {
  83. it.viewController.requireParentController().removeOverlay(it.view)
  84. returnToOriginalParent(it.view)
  85. }
  86. }
  87. transitions.validSharedElementTransitions.forEach {
  88. it.from.alpha = 1f
  89. }
  90. }
  91. private fun reparent(transition: Transition) {
  92. with(transition) {
  93. val biologicalParent = view.parent as ViewGroup
  94. view.setTag(R.id.original_parent, biologicalParent)
  95. view.setTag(R.id.original_layout_params, view.layoutParams)
  96. view.setTag(R.id.original_top, view.top)
  97. view.setTag(R.id.original_bottom, view.bottom)
  98. view.setTag(R.id.original_right, view.right)
  99. view.setTag(R.id.original_left, view.left)
  100. val loc = ViewUtils.getLocationOnScreen(view)
  101. biologicalParent.removeView(view)
  102. val lp = FrameLayout.LayoutParams(view.layoutParams)
  103. lp.topMargin = loc.y + viewController.topInset
  104. lp.topMargin = loc.y
  105. lp.leftMargin = loc.x
  106. lp.width = view.width
  107. lp.height = view.height
  108. view.layoutParams = lp
  109. transition.viewController.requireParentController().addOverlay(view)
  110. }
  111. }
  112. private fun returnToOriginalParent(element: View) {
  113. ViewUtils.removeFromParent(element)
  114. element.top = ViewTags.get(element, R.id.original_top)
  115. element.bottom = ViewTags.get(element, R.id.original_bottom)
  116. element.right = ViewTags.get(element, R.id.original_right)
  117. element.left = ViewTags.get(element, R.id.original_left)
  118. val parent = ViewTags.get<ViewGroup>(element, R.id.original_parent)
  119. val lp = ViewTags.get<ViewGroup.LayoutParams>(element, R.id.original_layout_params)
  120. val index = ViewTags.get<Int>(element, R.id.original_index_in_parent)
  121. parent.addView(element, index, lp)
  122. }
  123. }