Bladeren bron

Shared element refactor (#6146)

* Declare animator options once
* Fix <Image> sometimes losing its dimensions during the transition
Guy Carmeli 4 jaren geleden
bovenliggende
commit
0b3209bd59
No account linked to committer's email address

+ 0
- 57
lib/android/app/src/main/java/com/reactnativenavigation/parse/SharedElementTransitionOptions.java Bestand weergeven

@@ -1,57 +0,0 @@
1
-package com.reactnativenavigation.parse;
2
-
3
-import com.reactnativenavigation.parse.params.Interpolation;
4
-import com.reactnativenavigation.parse.params.NullNumber;
5
-import com.reactnativenavigation.parse.params.NullText;
6
-import com.reactnativenavigation.parse.params.Number;
7
-import com.reactnativenavigation.parse.params.Text;
8
-import com.reactnativenavigation.parse.parsers.InterpolationParser;
9
-import com.reactnativenavigation.parse.parsers.NumberParser;
10
-import com.reactnativenavigation.parse.parsers.TextParser;
11
-
12
-import org.json.JSONObject;
13
-
14
-import androidx.annotation.Nullable;
15
-
16
-public class SharedElementTransitionOptions {
17
-    public Text fromId = new NullText();
18
-    public Text toId = new NullText();
19
-    public Number duration = new NullNumber();
20
-    public Number startDelay = new NullNumber();
21
-    public Interpolation interpolation = Interpolation.NO_VALUE;
22
-
23
-    public static SharedElementTransitionOptions parse(@Nullable JSONObject json) {
24
-        SharedElementTransitionOptions transition = new SharedElementTransitionOptions();
25
-        if (json == null) return transition;
26
-
27
-        transition.fromId = TextParser.parse(json, "fromId");
28
-        transition.toId = TextParser.parse(json, "toId");
29
-        transition.duration = NumberParser.parse(json, "duration");
30
-        transition.startDelay = NumberParser.parse(json, "startDelay");
31
-        transition.interpolation = InterpolationParser.parse(json, "interpolation");
32
-
33
-        return transition;
34
-    }
35
-
36
-    void mergeWith(SharedElementTransitionOptions other) {
37
-        if (other.fromId.hasValue()) fromId = other.fromId;
38
-        if (other.toId.hasValue()) toId = other.toId;
39
-        if (other.duration.hasValue()) duration = other.duration;
40
-        if (other.startDelay.hasValue()) startDelay = other.startDelay;
41
-    }
42
-
43
-    void mergeWithDefault(SharedElementTransitionOptions defaultOptions) {
44
-        if (!fromId.hasValue()) fromId = defaultOptions.fromId;
45
-        if (!toId.hasValue()) toId = defaultOptions.toId;
46
-        if (!duration.hasValue()) duration = defaultOptions.duration;
47
-        if (!startDelay.hasValue()) startDelay = defaultOptions.startDelay;
48
-    }
49
-
50
-    public long getDuration() {
51
-        return duration.get(0).longValue();
52
-    }
53
-
54
-    public long getStartDelay() {
55
-        return startDelay.get(0).longValue();
56
-    }
57
-}

+ 35
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/SharedElementTransitionOptions.kt Bestand weergeven

@@ -0,0 +1,35 @@
1
+package com.reactnativenavigation.parse
2
+
3
+import android.animation.TimeInterpolator
4
+import com.reactnativenavigation.parse.params.*
5
+import com.reactnativenavigation.parse.params.Number
6
+import com.reactnativenavigation.parse.parsers.InterpolationParser
7
+import com.reactnativenavigation.parse.parsers.NumberParser
8
+import com.reactnativenavigation.parse.parsers.TextParser
9
+import org.json.JSONObject
10
+
11
+class SharedElementTransitionOptions {
12
+    var fromId: Text = NullText()
13
+    var toId: Text = NullText()
14
+    var duration: Number = NullNumber()
15
+    var startDelay: Number = NullNumber()
16
+    var interpolation = Interpolation.NO_VALUE
17
+
18
+    fun getDuration() = duration[0].toLong()
19
+    fun getStartDelay() = startDelay[0].toLong()
20
+    fun getInterpolator(): TimeInterpolator = interpolation.interpolator
21
+
22
+    companion object {
23
+        @JvmStatic
24
+        fun parse(json: JSONObject?): SharedElementTransitionOptions {
25
+            val transition = SharedElementTransitionOptions()
26
+            if (json == null) return transition
27
+            transition.fromId = TextParser.parse(json, "fromId")
28
+            transition.toId = TextParser.parse(json, "toId")
29
+            transition.duration = NumberParser.parse(json, "duration")
30
+            transition.startDelay = NumberParser.parse(json, "startDelay")
31
+            transition.interpolation = InterpolationParser.parse(json, "interpolation")
32
+            return transition
33
+        }
34
+    }
35
+}

+ 0
- 19
lib/android/app/src/main/java/com/reactnativenavigation/utils/Animator.kt Bestand weergeven

@@ -1,19 +0,0 @@
1
-package com.reactnativenavigation.utils
2
-
3
-import android.animation.Animator
4
-import android.animation.TimeInterpolator
5
-
6
-fun Animator.withStartDelay(delay: Long): Animator {
7
-    startDelay = delay
8
-    return this
9
-}
10
-
11
-fun Animator.withDuration(duration: Long): Animator {
12
-    this.duration = duration
13
-    return this
14
-}
15
-
16
-fun Animator.withInterpolator(interpolator: TimeInterpolator): Animator {
17
-    this.interpolator = interpolator
18
-    return this
19
-}

+ 5
- 1
lib/android/app/src/main/java/com/reactnativenavigation/views/element/SharedElementTransition.kt Bestand weergeven

@@ -22,7 +22,11 @@ class SharedElementTransition(appearing: ViewController<*>, private val options:
22 22
     override fun createAnimators(): AnimatorSet {
23 23
         val animators = animators()
24 24
                 .filter { it.shouldAnimateProperty() }
25
-                .map { it.create(options) }
25
+                .map { it.create(options).apply {
26
+                    duration = options.getDuration()
27
+                    startDelay = options.getStartDelay()
28
+                    interpolator = options.getInterpolator()
29
+                } }
26 30
         val set = AnimatorSet()
27 31
         set.playTogether(animators)
28 32
         return set

+ 2
- 4
lib/android/app/src/main/java/com/reactnativenavigation/views/element/TransitionAnimatorCreator.kt Bestand weergeven

@@ -116,10 +116,8 @@ open class TransitionAnimatorCreator {
116 116
             val lp = FrameLayout.LayoutParams(view.layoutParams)
117 117
             lp.topMargin = loc.y
118 118
             lp.leftMargin = loc.x
119
-            if (view !is ReactImageView) {
120
-                lp.width = view.width
121
-                lp.height = view.height
122
-            }
119
+            lp.width = view.width
120
+            lp.height = view.height
123 121
             view.layoutParams = lp
124 122
             transition.viewController.requireParentController().addOverlay(view)
125 123
         }

+ 1
- 9
lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/BackgroundColorAnimator.kt Bestand weergeven

@@ -26,14 +26,6 @@ class BackgroundColorAnimator(from: View, to: View) : PropertyAnimatorCreator<Vi
26 26
         val toColor = ColorUtils.colorToLAB(ViewUtils.getBackgroundColor(to))
27 27
 
28 28
         backgroundColorEvaluator.evaluate(0f, fromColor, toColor)
29
-        return ObjectAnimator
30
-                .ofObject(
31
-                        backgroundColorEvaluator,
32
-                        fromColor,
33
-                        toColor
34
-                )
35
-                .withDuration(options.getDuration())
36
-                .withStartDelay(options.getStartDelay())
37
-                .withInterpolator(options.interpolation.interpolator)
29
+        return ObjectAnimator.ofObject(backgroundColorEvaluator, fromColor, toColor)
38 30
     }
39 31
 }

+ 7
- 14
lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/MatrixAnimator.kt Bestand weergeven

@@ -9,9 +9,6 @@ import com.facebook.drawee.drawable.ScalingUtils.InterpolatingScaleType
9 9
 import com.facebook.react.views.image.ReactImageView
10 10
 import com.reactnativenavigation.parse.SharedElementTransitionOptions
11 11
 import com.reactnativenavigation.utils.ViewUtils
12
-import com.reactnativenavigation.utils.withDuration
13
-import com.reactnativenavigation.utils.withInterpolator
14
-import com.reactnativenavigation.utils.withStartDelay
15 12
 
16 13
 class MatrixAnimator(from: View, to: View) : PropertyAnimatorCreator<ReactImageView>(from, to) {
17 14
     override fun shouldAnimateProperty(fromChild: ReactImageView, toChild: ReactImageView): Boolean {
@@ -27,17 +24,13 @@ class MatrixAnimator(from: View, to: View) : PropertyAnimatorCreator<ReactImageV
27 24
                     calculateBounds(to)
28 25
             )
29 26
 
30
-            return ObjectAnimator
31
-                    .ofObject(TypeEvaluator<Float> { fraction: Float, _: Any, _: Any ->
32
-                        hierarchy.actualImageScaleType?.let {
33
-                            (hierarchy.actualImageScaleType as InterpolatingScaleType?)!!.value = fraction
34
-                            to.invalidate()
35
-                        }
36
-                        null
37
-                    }, 0, 1)
38
-                    .withDuration(options.getDuration())
39
-                    .withStartDelay(options.getStartDelay())
40
-                    .withInterpolator(options.interpolation.interpolator)
27
+            return ObjectAnimator.ofObject(TypeEvaluator<Float> { fraction: Float, _: Any, _: Any ->
28
+                hierarchy.actualImageScaleType?.let {
29
+                    (hierarchy.actualImageScaleType as InterpolatingScaleType?)!!.value = fraction
30
+                    to.invalidate()
31
+                }
32
+                null
33
+            }, 0, 1)
41 34
         }
42 35
     }
43 36
 

+ 1
- 8
lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/RotationAnimator.kt Bestand weergeven

@@ -5,9 +5,6 @@ import android.animation.ObjectAnimator
5 5
 import android.view.View
6 6
 import com.facebook.react.views.image.ReactImageView
7 7
 import com.reactnativenavigation.parse.SharedElementTransitionOptions
8
-import com.reactnativenavigation.utils.withDuration
9
-import com.reactnativenavigation.utils.withInterpolator
10
-import com.reactnativenavigation.utils.withStartDelay
11 8
 
12 9
 class RotationAnimator(from: View, to: View) : PropertyAnimatorCreator<ReactImageView>(from, to) {
13 10
     private val fromRotation = from.rotation
@@ -21,10 +18,6 @@ class RotationAnimator(from: View, to: View) : PropertyAnimatorCreator<ReactImag
21 18
         to.rotation = fromRotation
22 19
         to.pivotX = 0f
23 20
         to.pivotY = 0f
24
-        return ObjectAnimator
25
-                .ofFloat(to, View.ROTATION, fromRotation, toRotation)
26
-                .withDuration(options.getDuration())
27
-                .withStartDelay(options.getStartDelay())
28
-                .withInterpolator(options.interpolation.interpolator)
21
+        return ObjectAnimator.ofFloat(to, View.ROTATION, fromRotation, toRotation)
29 22
     }
30 23
 }

+ 1
- 10
lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/ScaleXAnimator.kt Bestand weergeven

@@ -4,13 +4,8 @@ import android.animation.Animator
4 4
 import android.animation.ObjectAnimator
5 5
 import android.view.View
6 6
 import android.view.ViewGroup
7
-import androidx.core.animation.addListener
8
-import androidx.core.animation.doOnStart
9 7
 import com.facebook.react.views.text.ReactTextView
10 8
 import com.reactnativenavigation.parse.SharedElementTransitionOptions
11
-import com.reactnativenavigation.utils.withDuration
12
-import com.reactnativenavigation.utils.withInterpolator
13
-import com.reactnativenavigation.utils.withStartDelay
14 9
 
15 10
 class ScaleXAnimator(from: View, to: View) : PropertyAnimatorCreator<ViewGroup>(from, to) {
16 11
     override fun shouldAnimateProperty(fromChild: ViewGroup, toChild: ViewGroup): Boolean {
@@ -21,10 +16,6 @@ class ScaleXAnimator(from: View, to: View) : PropertyAnimatorCreator<ViewGroup>(
21 16
 
22 17
     override fun create(options: SharedElementTransitionOptions): Animator {
23 18
         to.scaleX = from.width.toFloat() / to.width
24
-        return ObjectAnimator
25
-                .ofFloat(to, View.SCALE_X, from.width.toFloat() / to.width, 1f)
26
-                .withDuration(options.getDuration())
27
-                .withStartDelay(options.getStartDelay())
28
-                .withInterpolator(options.interpolation.interpolator)
19
+        return ObjectAnimator.ofFloat(to, View.SCALE_X, from.width.toFloat() / to.width, 1f)
29 20
     }
30 21
 }

+ 1
- 8
lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/ScaleYAnimator.kt Bestand weergeven

@@ -6,9 +6,6 @@ import android.view.View
6 6
 import android.view.ViewGroup
7 7
 import com.facebook.react.views.text.ReactTextView
8 8
 import com.reactnativenavigation.parse.SharedElementTransitionOptions
9
-import com.reactnativenavigation.utils.withDuration
10
-import com.reactnativenavigation.utils.withInterpolator
11
-import com.reactnativenavigation.utils.withStartDelay
12 9
 
13 10
 class ScaleYAnimator(from: View, to: View) : PropertyAnimatorCreator<ViewGroup>(from, to) {
14 11
     override fun shouldAnimateProperty(fromChild: ViewGroup, toChild: ViewGroup): Boolean {
@@ -19,10 +16,6 @@ class ScaleYAnimator(from: View, to: View) : PropertyAnimatorCreator<ViewGroup>(
19 16
 
20 17
     override fun create(options: SharedElementTransitionOptions): Animator {
21 18
         to.scaleY = from.height.toFloat() / to.height
22
-        return ObjectAnimator
23
-                .ofFloat(to, View.SCALE_Y, from.height.toFloat() / to.height, 1f)
24
-                .withDuration(options.getDuration())
25
-                .withStartDelay(options.getStartDelay())
26
-                .withInterpolator(options.interpolation.interpolator)
19
+        return ObjectAnimator.ofFloat(to, View.SCALE_Y, from.height.toFloat() / to.height, 1f)
27 20
     }
28 21
 }

+ 1
- 4
lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/TextChangeAnimator.kt Bestand weergeven

@@ -35,9 +35,6 @@ class TextChangeAnimator(from: View, to: View) : PropertyAnimatorCreator<ReactTe
35 35
                 }
36 36
                 .setTextColorGetter {
37 37
                     TextViewUtils.getTextColor(it)
38
-                }
39
-                .buildAnimator()
40
-                .setDuration(options.getDuration())
41
-                .withInterpolator(options.interpolation.interpolator)
38
+                }.buildAnimator()
42 39
     }
43 40
 }

+ 1
- 12
lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/XAnimator.kt Bestand weergeven

@@ -1,19 +1,12 @@
1 1
 package com.reactnativenavigation.views.element.animators
2 2
 
3 3
 import android.animation.Animator
4
-import android.animation.AnimatorListenerAdapter
5 4
 import android.animation.ObjectAnimator
6 5
 import android.view.View
7 6
 import android.view.View.TRANSLATION_X
8
-import androidx.core.animation.addListener
9
-import androidx.core.animation.doOnStart
10
-import com.facebook.react.views.image.ReactImageView
11 7
 import com.facebook.react.views.text.ReactTextView
12 8
 import com.reactnativenavigation.parse.SharedElementTransitionOptions
13 9
 import com.reactnativenavigation.utils.ViewUtils
14
-import com.reactnativenavigation.utils.withDuration
15
-import com.reactnativenavigation.utils.withInterpolator
16
-import com.reactnativenavigation.utils.withStartDelay
17 10
 
18 11
 class XAnimator(from: View, to: View) : PropertyAnimatorCreator<View>(from, to) {
19 12
     private val dx: Int
@@ -31,10 +24,6 @@ class XAnimator(from: View, to: View) : PropertyAnimatorCreator<View>(from, to)
31 24
     override fun create(options: SharedElementTransitionOptions): Animator {
32 25
         to.translationX = dx.toFloat()
33 26
         to.pivotX = 0f
34
-        return ObjectAnimator
35
-                .ofFloat(to, TRANSLATION_X, dx.toFloat(), 0f)
36
-                .withDuration(options.getDuration())
37
-                .withStartDelay(options.getStartDelay())
38
-                .withInterpolator(options.interpolation.interpolator)
27
+        return ObjectAnimator.ofFloat(to, TRANSLATION_X, dx.toFloat(), 0f)
39 28
     }
40 29
 }

+ 1
- 9
lib/android/app/src/main/java/com/reactnativenavigation/views/element/animators/YAnimator.kt Bestand weergeven

@@ -8,10 +8,6 @@ import android.view.ViewGroup
8 8
 import com.facebook.react.views.text.ReactTextView
9 9
 import com.reactnativenavigation.parse.SharedElementTransitionOptions
10 10
 import com.reactnativenavigation.utils.ViewUtils
11
-import com.reactnativenavigation.utils.withDuration
12
-
13
-import com.reactnativenavigation.utils.withInterpolator
14
-import com.reactnativenavigation.utils.withStartDelay
15 11
 
16 12
 class YAnimator(from: View, to: View) : PropertyAnimatorCreator<View>(from, to) {
17 13
     private val dy: Int
@@ -29,10 +25,6 @@ class YAnimator(from: View, to: View) : PropertyAnimatorCreator<View>(from, to)
29 25
     override fun create(options: SharedElementTransitionOptions): Animator {
30 26
         to.translationY = dy.toFloat()
31 27
         to.pivotY = 0f
32
-        return ObjectAnimator
33
-                .ofFloat(to, TRANSLATION_Y, dy.toFloat(), 0f)
34
-                .withDuration(options.getDuration())
35
-                .withStartDelay(options.getStartDelay())
36
-                .withInterpolator(options.interpolation.interpolator)
28
+        return ObjectAnimator.ofFloat(to, TRANSLATION_Y, dy.toFloat(), 0f)
37 29
     }
38 30
 }