11package com.ease
22
3+ import android.animation.Animator
4+ import android.animation.AnimatorListenerAdapter
35import android.animation.ObjectAnimator
46import android.animation.TimeInterpolator
57import android.content.Context
8+ import android.view.View
69import android.view.animation.LinearInterpolator
710import android.view.animation.PathInterpolator
811import androidx.dynamicanimation.animation.DynamicAnimation
@@ -31,6 +34,11 @@ class EaseView(context: Context) : ReactViewGroup(context) {
3134 var transitionStiffness: Float = 120.0f
3235 var transitionMass: Float = 1.0f
3336
37+ // --- Hardware layer ---
38+ var useHardwareLayer: Boolean = true
39+ private var activeAnimationCount: Int = 0
40+ private var savedLayerType: Int = View .LAYER_TYPE_NONE
41+
3442 // --- Initial animate values (set by ViewManager) ---
3543 var initialAnimateOpacity: Float = 1.0f
3644 var initialAnimateTranslateX: Float = 0.0f
@@ -58,6 +66,26 @@ class EaseView(context: Context) : ReactViewGroup(context) {
5866 else -> PathInterpolator (0.42f , 0f , 0.58f , 1.0f )
5967 }
6068
69+ // --- Hardware layer management ---
70+
71+ private fun onEaseAnimationStart () {
72+ if (activeAnimationCount == 0 && useHardwareLayer) {
73+ savedLayerType = layerType
74+ setLayerType(View .LAYER_TYPE_HARDWARE , null )
75+ }
76+ activeAnimationCount++
77+ }
78+
79+ private fun onEaseAnimationEnd () {
80+ activeAnimationCount--
81+ if (activeAnimationCount <= 0 ) {
82+ activeAnimationCount = 0
83+ if (useHardwareLayer && layerType == View .LAYER_TYPE_HARDWARE ) {
84+ setLayerType(savedLayerType, null )
85+ }
86+ }
87+ }
88+
6189 fun applyPendingAnimateValues () {
6290 applyAnimateValues(pendingOpacity, pendingTranslateX, pendingTranslateY, pendingScale, pendingRotate)
6391 }
@@ -192,6 +220,14 @@ class EaseView(context: Context) : ReactViewGroup(context) {
192220 val animator = ObjectAnimator .ofFloat(this , propertyName, fromValue, toValue).apply {
193221 duration = transitionDuration.toLong()
194222 interpolator = getInterpolator(transitionEasing)
223+ addListener(object : AnimatorListenerAdapter () {
224+ override fun onAnimationStart (animation : Animator ) {
225+ this @EaseView.onEaseAnimationStart()
226+ }
227+ override fun onAnimationEnd (animation : Animator ) {
228+ this @EaseView.onEaseAnimationEnd()
229+ }
230+ })
195231 }
196232
197233 runningAnimators[propertyName] = animator
@@ -215,8 +251,18 @@ class EaseView(context: Context) : ReactViewGroup(context) {
215251 this .dampingRatio = dampingRatio
216252 this .stiffness = transitionStiffness
217253 }
254+ addUpdateListener { _, _, _ ->
255+ // First update — enable hardware layer
256+ if (activeAnimationCount == 0 ) {
257+ this @EaseView.onEaseAnimationStart()
258+ }
259+ }
260+ addEndListener { _, _, _, _ ->
261+ this @EaseView.onEaseAnimationEnd()
262+ }
218263 }
219264
265+ onEaseAnimationStart()
220266 runningSpringAnimations[viewProperty] = spring
221267 spring.start()
222268 }
@@ -266,6 +312,11 @@ class EaseView(context: Context) : ReactViewGroup(context) {
266312 }
267313 runningSpringAnimations.clear()
268314
315+ if (activeAnimationCount > 0 && layerType == View .LAYER_TYPE_HARDWARE ) {
316+ setLayerType(savedLayerType, null )
317+ }
318+ activeAnimationCount = 0
319+
269320 prevOpacity = null
270321 prevTranslateX = null
271322 prevTranslateY = null
0 commit comments