Browse Source

Refactor NavigationAnimator

Guy Carmeli 6 years ago
parent
commit
33fb8343f7

+ 0
- 6
lib/android/app/src/main/java/com/reactnativenavigation/anim/AnimationListener.java View File

1
-package com.reactnativenavigation.anim;
2
-
3
-
4
-public interface AnimationListener {
5
-    void onAnimationEnd();
6
-}

+ 8
- 7
lib/android/app/src/main/java/com/reactnativenavigation/anim/NavigationAnimator.java View File

1
 package com.reactnativenavigation.anim;
1
 package com.reactnativenavigation.anim;
2
 
2
 
3
 import android.animation.Animator;
3
 import android.animation.Animator;
4
+import android.animation.Animator.AnimatorListener;
4
 import android.animation.AnimatorListenerAdapter;
5
 import android.animation.AnimatorListenerAdapter;
5
 import android.animation.AnimatorSet;
6
 import android.animation.AnimatorSet;
6
 import android.content.Context;
7
 import android.content.Context;
20
         this.options = options;
21
         this.options = options;
21
     }
22
     }
22
 
23
 
23
-    public void push(final View view, AnimationListener animationListener) {
24
+    public void push(final View view, Runnable onAnimationEnd) {
24
         view.setVisibility(View.INVISIBLE);
25
         view.setVisibility(View.INVISIBLE);
25
         AnimatorSet set = options.push.content.getAnimation(view, getDefaultPushAnimation(view));
26
         AnimatorSet set = options.push.content.getAnimation(view, getDefaultPushAnimation(view));
26
         set.addListener(new AnimatorListenerAdapter() {
27
         set.addListener(new AnimatorListenerAdapter() {
31
 
32
 
32
             @Override
33
             @Override
33
             public void onAnimationEnd(Animator animation) {
34
             public void onAnimationEnd(Animator animation) {
34
-                animationListener.onAnimationEnd();
35
+                onAnimationEnd.run();
35
             }
36
             }
36
         });
37
         });
37
         set.start();
38
         set.start();
38
     }
39
     }
39
 
40
 
40
-    public void pop(View view, AnimationListener animationListener) {
41
+    public void pop(View view, Runnable onAnimationEnd) {
41
         AnimatorSet set = options.pop.content.getAnimation(view, getDefaultPopAnimation(view));
42
         AnimatorSet set = options.pop.content.getAnimation(view, getDefaultPopAnimation(view));
42
         set.addListener(new AnimatorListenerAdapter() {
43
         set.addListener(new AnimatorListenerAdapter() {
43
             @Override
44
             @Override
44
             public void onAnimationEnd(Animator animation) {
45
             public void onAnimationEnd(Animator animation) {
45
-                animationListener.onAnimationEnd();
46
+                onAnimationEnd.run();
46
             }
47
             }
47
         });
48
         });
48
         set.start();
49
         set.start();
49
     }
50
     }
50
 
51
 
51
-    public void animateStartApp(View view, AnimationListener animationListener) {
52
+    public void animateStartApp(View view, AnimatorListener listener) {
52
         view.setVisibility(View.INVISIBLE);
53
         view.setVisibility(View.INVISIBLE);
53
-        AnimatorSet set = options.startApp.getAnimation(view, null);
54
+        AnimatorSet set = options.startApp.getAnimation(view);
54
         set.addListener(new AnimatorListenerAdapter() {
55
         set.addListener(new AnimatorListenerAdapter() {
55
             @Override
56
             @Override
56
             public void onAnimationStart(Animator animation) {
57
             public void onAnimationStart(Animator animation) {
59
 
60
 
60
             @Override
61
             @Override
61
             public void onAnimationEnd(Animator animation) {
62
             public void onAnimationEnd(Animator animation) {
62
-                if (animationListener != null) animationListener.onAnimationEnd();
63
+                listener.onAnimationEnd(animation);
63
             }
64
             }
64
         });
65
         });
65
         set.start();
66
         set.start();

+ 8
- 10
lib/android/app/src/main/java/com/reactnativenavigation/anim/TopBarAnimator.java View File

9
 import android.view.View;
9
 import android.view.View;
10
 import android.view.animation.AccelerateInterpolator;
10
 import android.view.animation.AccelerateInterpolator;
11
 import android.view.animation.DecelerateInterpolator;
11
 import android.view.animation.DecelerateInterpolator;
12
+import android.view.animation.LinearInterpolator;
12
 
13
 
13
 import com.reactnativenavigation.parse.AnimationOptions;
14
 import com.reactnativenavigation.parse.AnimationOptions;
14
 import com.reactnativenavigation.views.topbar.TopBar;
15
 import com.reactnativenavigation.views.topbar.TopBar;
21
     private static final int DURATION_TOPBAR = 300;
22
     private static final int DURATION_TOPBAR = 300;
22
     private final DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();
23
     private final DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();
23
     private final AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator();
24
     private final AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator();
25
+    private final LinearInterpolator linearInterpolator = new LinearInterpolator();
24
 
26
 
25
     private TopBar topBar;
27
     private TopBar topBar;
26
     private String stackId;
28
     private String stackId;
46
     }
48
     }
47
 
49
 
48
     public void show(float startTranslation) {
50
     public void show(float startTranslation) {
49
-        showAnimator = getDefaultShowAnimator(startTranslation, null, DEFAULT_COLLAPSE_DURATION);
51
+        showAnimator = getDefaultShowAnimator(startTranslation, linearInterpolator, DEFAULT_COLLAPSE_DURATION);
50
         show();
52
         show();
51
     }
53
     }
52
 
54
 
69
         return set;
71
         return set;
70
     }
72
     }
71
 
73
 
72
-    public void hide(AnimationOptions options, AnimationListener listener) {
74
+    public void hide(AnimationOptions options, Runnable onAnimationEnd) {
73
         if (options.hasValue() && (!options.id.hasValue() || options.id.get().equals(stackId))) {
75
         if (options.hasValue() && (!options.id.hasValue() || options.id.get().equals(stackId))) {
74
             hideAnimator = options.getAnimation(topBar);
76
             hideAnimator = options.getAnimation(topBar);
75
         } else {
77
         } else {
76
             hideAnimator = getDefaultHideAnimator(0, accelerateInterpolator, DURATION_TOPBAR);
78
             hideAnimator = getDefaultHideAnimator(0, accelerateInterpolator, DURATION_TOPBAR);
77
         }
79
         }
78
-        hide(listener);
80
+        hide(onAnimationEnd);
79
     }
81
     }
80
 
82
 
81
     void hide(float startTranslation) {
83
     void hide(float startTranslation) {
82
         hideAnimator = getDefaultHideAnimator(startTranslation, null, DEFAULT_COLLAPSE_DURATION);
84
         hideAnimator = getDefaultHideAnimator(startTranslation, null, DEFAULT_COLLAPSE_DURATION);
83
-        hide(null);
85
+        hide(() -> {});
84
     }
86
     }
85
 
87
 
86
-    private void hide(AnimationListener listener) {
88
+    private void hide(Runnable onAnimationEnd) {
87
         hideAnimator.addListener(new AnimatorListenerAdapter() {
89
         hideAnimator.addListener(new AnimatorListenerAdapter() {
88
             @Override
90
             @Override
89
             public void onAnimationEnd(Animator animation) {
91
             public void onAnimationEnd(Animator animation) {
90
                 topBar.setVisibility(View.GONE);
92
                 topBar.setVisibility(View.GONE);
91
-                if (listener != null) listener.onAnimationEnd();
93
+                onAnimationEnd.run();
92
             }
94
             }
93
         });
95
         });
94
         hideAnimator.start();
96
         hideAnimator.start();
102
         set.play(hideAnimator);
104
         set.play(hideAnimator);
103
         return set;
105
         return set;
104
     }
106
     }
105
-
106
-    public boolean isRunning() {
107
-        return (hideAnimator != null && hideAnimator.isRunning()) || (showAnimator != null && showAnimator.isRunning());
108
-    }
109
 }
107
 }

+ 4
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/AnimationOptions.java View File

61
         return hasValue;
61
         return hasValue;
62
     }
62
     }
63
 
63
 
64
+    public AnimatorSet getAnimation(View view) {
65
+        return getAnimation(view, null);
66
+    }
67
+
64
     public AnimatorSet getAnimation(View view, AnimatorSet defaultAnimation) {
68
     public AnimatorSet getAnimation(View view, AnimatorSet defaultAnimation) {
65
         if (!hasValue()) return defaultAnimation;
69
         if (!hasValue()) return defaultAnimation;
66
         AnimatorSet animationSet = new AnimatorSet();
70
         AnimatorSet animationSet = new AnimatorSet();

+ 1
- 2
lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java View File

2
 
2
 
3
 import android.app.Activity;
3
 import android.app.Activity;
4
 import android.graphics.Color;
4
 import android.graphics.Color;
5
-import android.support.annotation.NonNull;
6
 
5
 
7
 import com.reactnativenavigation.interfaces.ChildDisappearListener;
6
 import com.reactnativenavigation.interfaces.ChildDisappearListener;
8
 import com.reactnativenavigation.parse.AnimationsOptions;
7
 import com.reactnativenavigation.parse.AnimationsOptions;
106
         if (topTabOptions.fontFamily != null) topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
105
         if (topTabOptions.fontFamily != null) topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
107
     }
106
     }
108
 
107
 
109
-    public void onChildWillDisappear(Options disappearing, Options appearing, @NonNull ChildDisappearListener childDisappearListener) {
108
+    public void onChildWillDisappear(Options disappearing, Options appearing, ChildDisappearListener childDisappearListener) {
110
         if (disappearing.topBarOptions.visible.isTrueOrUndefined() && appearing.topBarOptions.visible.isFalse()) {
109
         if (disappearing.topBarOptions.visible.isTrueOrUndefined() && appearing.topBarOptions.visible.isFalse()) {
111
             if (disappearing.topBarOptions.animate.isTrueOrUndefined()) {
110
             if (disappearing.topBarOptions.animate.isTrueOrUndefined()) {
112
                 topBar.hideAnimate(disappearing.animationsOptions.pop.topBar, childDisappearListener::childDisappear);
111
                 topBar.hideAnimate(disappearing.animationsOptions.pop.topBar, childDisappearListener::childDisappear);

+ 8
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/Navigator.java View File

1
 package com.reactnativenavigation.viewcontrollers;
1
 package com.reactnativenavigation.viewcontrollers;
2
 
2
 
3
+import android.animation.Animator;
4
+import android.animation.AnimatorListenerAdapter;
3
 import android.app.Activity;
5
 import android.app.Activity;
4
 import android.support.annotation.NonNull;
6
 import android.support.annotation.NonNull;
5
 import android.support.annotation.Nullable;
7
 import android.support.annotation.Nullable;
79
         if (animationsOptions.startApp.hasValue()) {
81
         if (animationsOptions.startApp.hasValue()) {
80
             getView().addView(view);
82
             getView().addView(view);
81
             new NavigationAnimator(viewController.getActivity(), animationsOptions)
83
             new NavigationAnimator(viewController.getActivity(), animationsOptions)
82
-                    .animateStartApp(view, () -> promise.resolve(viewController.getId()));
84
+                    .animateStartApp(view, new AnimatorListenerAdapter() {
85
+                        @Override
86
+                        public void onAnimationEnd(Animator animation) {
87
+                            promise.resolve(viewController.getId());
88
+                        }
89
+                    });
83
         } else {
90
         } else {
84
             getView().addView(view);
91
             getView().addView(view);
85
             promise.resolve(viewController.getId());
92
             promise.resolve(viewController.getId());

+ 1
- 4
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java View File

143
         );
143
         );
144
 
144
 
145
         if (disappearing.options.animated.isTrueOrUndefined()) {
145
         if (disappearing.options.animated.isTrueOrUndefined()) {
146
-            animator.pop(
147
-                    disappearing.getView(),
148
-                    () -> finishPopping(disappearing, listener)
149
-            );
146
+            animator.pop(disappearing.getView(), () -> finishPopping(disappearing, listener));
150
         } else {
147
         } else {
151
             finishPopping(disappearing, listener);
148
             finishPopping(disappearing, listener);
152
         }
149
         }

+ 4
- 4
lib/android/app/src/main/java/com/reactnativenavigation/views/topbar/TopBar.java View File

1
 package com.reactnativenavigation.views.topbar;
1
 package com.reactnativenavigation.views.topbar;
2
 
2
 
3
+import android.animation.Animator.AnimatorListener;
3
 import android.annotation.SuppressLint;
4
 import android.annotation.SuppressLint;
4
 import android.content.Context;
5
 import android.content.Context;
5
 import android.graphics.Typeface;
6
 import android.graphics.Typeface;
13
 import android.widget.RelativeLayout;
14
 import android.widget.RelativeLayout;
14
 import android.widget.TextView;
15
 import android.widget.TextView;
15
 
16
 
16
-import com.reactnativenavigation.anim.AnimationListener;
17
 import com.reactnativenavigation.anim.TopBarAnimator;
17
 import com.reactnativenavigation.anim.TopBarAnimator;
18
 import com.reactnativenavigation.anim.TopBarCollapseBehavior;
18
 import com.reactnativenavigation.anim.TopBarCollapseBehavior;
19
 import com.reactnativenavigation.interfaces.ScrollEventListener;
19
 import com.reactnativenavigation.interfaces.ScrollEventListener;
198
     }
198
     }
199
 
199
 
200
     public void hideAnimate(AnimationOptions options) {
200
     public void hideAnimate(AnimationOptions options) {
201
-        hideAnimate(options, null);
201
+        hideAnimate(options, () -> {});
202
     }
202
     }
203
 
203
 
204
-    public void hideAnimate(AnimationOptions options, AnimationListener listener) {
205
-        animator.hide(options, listener);
204
+    public void hideAnimate(AnimationOptions options, Runnable onAnimationEnd) {
205
+        animator.hide(options, onAnimationEnd);
206
     }
206
     }
207
 
207
 
208
     @Override
208
     @Override

+ 5
- 5
lib/android/app/src/test/java/com/reactnativenavigation/anim/ViewAnimationSetBuilderTest.java View File

22
     }
22
     }
23
 
23
 
24
     @Test
24
     @Test
25
-    public void implementsViewAnimationListener() throws Exception {
25
+    public void implementsViewAnimationListener() {
26
         assertThat(new ViewAnimationSetBuilder()).isInstanceOf(Animation.AnimationListener.class);
26
         assertThat(new ViewAnimationSetBuilder()).isInstanceOf(Animation.AnimationListener.class);
27
     }
27
     }
28
 
28
 
29
     @Test
29
     @Test
30
-    public void optionalCompletionListener() throws Exception {
30
+    public void optionalCompletionListener() {
31
         new ViewAnimationSetBuilder()
31
         new ViewAnimationSetBuilder()
32
                 .add(someView(), someAnimation())
32
                 .add(someView(), someAnimation())
33
                 .start();
33
                 .start();
35
     }
35
     }
36
 
36
 
37
     @Test
37
     @Test
38
-    public void startsAllAnimations() throws Exception {
38
+    public void startsAllAnimations() {
39
         Animation anim1 = someAnimation();
39
         Animation anim1 = someAnimation();
40
         Animation anim2 = someAnimation();
40
         Animation anim2 = someAnimation();
41
         new ViewAnimationSetBuilder()
41
         new ViewAnimationSetBuilder()
48
     }
48
     }
49
 
49
 
50
     @Test
50
     @Test
51
-    public void callsEndListenerOnlyAfterAllAnimationsFinish() throws Exception {
51
+    public void callsEndListenerOnlyAfterAllAnimationsFinish() {
52
         Animation anim1 = someAnimation();
52
         Animation anim1 = someAnimation();
53
         Animation anim2 = someAnimation();
53
         Animation anim2 = someAnimation();
54
         ViewAnimationSetBuilder uut = new ViewAnimationSetBuilder();
54
         ViewAnimationSetBuilder uut = new ViewAnimationSetBuilder();
60
     }
60
     }
61
 
61
 
62
     @Test
62
     @Test
63
-    public void clearsAnimationFromViewsAfterFinished() throws Exception {
63
+    public void clearsAnimationFromViewsAfterFinished() {
64
         View v1 = someView();
64
         View v1 = someView();
65
         View v2 = someView();
65
         View v2 = someView();
66
         new ViewAnimationSetBuilder()
66
         new ViewAnimationSetBuilder()

+ 0
- 24
lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestNavigationAnimator.java View File

1
-package com.reactnativenavigation.mocks;
2
-
3
-import android.view.*;
4
-
5
-import com.reactnativenavigation.anim.*;
6
-
7
-import org.robolectric.*;
8
-
9
-public class TestNavigationAnimator extends NavigationAnimator {
10
-
11
-    public TestNavigationAnimator() {
12
-        super(RuntimeEnvironment.application);
13
-    }
14
-
15
-    @Override
16
-    public void push(final View enteringView, AnimationListener animationListener) {
17
-        if (animationListener != null) animationListener.onAnimationEnd();
18
-    }
19
-
20
-    @Override
21
-    public void pop(final View enteringView, AnimationListener animationListener) {
22
-        if (animationListener != null) animationListener.onAnimationEnd();
23
-    }
24
-}

+ 3
- 1
lib/android/app/src/test/java/com/reactnativenavigation/views/TopBarTest.java View File

23
 import java.util.ArrayList;
23
 import java.util.ArrayList;
24
 
24
 
25
 import static org.assertj.core.api.Java6Assertions.assertThat;
25
 import static org.assertj.core.api.Java6Assertions.assertThat;
26
+import static org.mockito.ArgumentMatchers.any;
27
+import static org.mockito.ArgumentMatchers.eq;
26
 import static org.mockito.Mockito.spy;
28
 import static org.mockito.Mockito.spy;
27
 import static org.mockito.Mockito.times;
29
 import static org.mockito.Mockito.times;
28
 import static org.mockito.Mockito.verify;
30
 import static org.mockito.Mockito.verify;
87
     public void hide_animate() {
89
     public void hide_animate() {
88
         AnimationOptions options = new AnimationOptions();
90
         AnimationOptions options = new AnimationOptions();
89
         uut.hideAnimate(options);
91
         uut.hideAnimate(options);
90
-        verify(animator, times(1)).hide(options, null);
92
+        verify(animator, times(1)).hide(eq(options), any());
91
     }
93
     }
92
 
94
 
93
     @Test
95
     @Test