Guy Carmeli 7 년 전
부모
커밋
3bce9c9711

+ 2
- 2
android/app/src/main/java/com/reactnativenavigation/screens/CollapsingSingleScreen.java 파일 보기

81
                     @Override
81
                     @Override
82
                     public void onFling(CollapseAmount amount) {
82
                     public void onFling(CollapseAmount amount) {
83
                         if (screenParams.styleParams.drawScreenBelowTopBar) {
83
                         if (screenParams.styleParams.drawScreenBelowTopBar) {
84
-                            ((CollapsingView) contentView).collapse(amount);
84
+                            ((CollapsingView) contentView).fling(amount);
85
                         }
85
                         }
86
-                        topBar.collapse(amount);
86
+                        topBar.fling(amount);
87
                     }
87
                     }
88
                 },
88
                 },
89
                 getCollapseBehaviour()
89
                 getCollapseBehaviour()

+ 2
- 2
android/app/src/main/java/com/reactnativenavigation/screens/CollapsingViewPagerScreen.java 파일 보기

80
 
80
 
81
                     @Override
81
                     @Override
82
                     public void onFling(CollapseAmount amount) {
82
                     public void onFling(CollapseAmount amount) {
83
-                        topBar.collapse(amount);
84
-                        ((CollapsingView) viewPager).collapse(amount);
83
+                        topBar.fling(amount);
84
+                        ((CollapsingView) viewPager).fling(amount);
85
                     }
85
                     }
86
                 },
86
                 },
87
                 getCollapseBehaviour()
87
                 getCollapseBehaviour()

+ 5
- 0
android/app/src/main/java/com/reactnativenavigation/views/CollapsingContentView.java 파일 보기

57
         viewCollapser.collapse(amount);
57
         viewCollapser.collapse(amount);
58
     }
58
     }
59
 
59
 
60
+    @Override
61
+    public void fling(CollapseAmount amount) {
62
+        viewCollapser.fling(amount);
63
+    }
64
+
60
     public void destroy() {
65
     public void destroy() {
61
         if (scrollViewDetector != null) {
66
         if (scrollViewDetector != null) {
62
             scrollViewDetector.destroy();
67
             scrollViewDetector.destroy();

+ 2
- 2
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapseAmount.java 파일 보기

24
         return amount != null;
24
         return amount != null;
25
     }
25
     }
26
 
26
 
27
-    public boolean collapseToTop() {
27
+    boolean collapseToTop() {
28
         return direction == CollapseCalculator.Direction.Up;
28
         return direction == CollapseCalculator.Direction.Up;
29
     }
29
     }
30
 
30
 
31
-    public boolean collapseToBottom() {
31
+    boolean collapseToBottom() {
32
         return direction == CollapseCalculator.Direction.Down;
32
         return direction == CollapseCalculator.Direction.Down;
33
     }
33
     }
34
 
34
 

+ 31
- 8
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapseCalculator.java 파일 보기

2
 
2
 
3
 import android.support.annotation.NonNull;
3
 import android.support.annotation.NonNull;
4
 import android.support.annotation.Nullable;
4
 import android.support.annotation.Nullable;
5
+import android.util.Log;
5
 import android.view.GestureDetector;
6
 import android.view.GestureDetector;
6
 import android.view.MotionEvent;
7
 import android.view.MotionEvent;
7
 import android.view.ViewConfiguration;
8
 import android.view.ViewConfiguration;
12
 import com.reactnativenavigation.views.collapsingToolbar.behaviours.TitleBarHideOnScrollBehaviour;
13
 import com.reactnativenavigation.views.collapsingToolbar.behaviours.TitleBarHideOnScrollBehaviour;
13
 
14
 
14
 public class CollapseCalculator {
15
 public class CollapseCalculator {
16
+    private static final int FLING_DISTANCE_PIXELS_THRESHOLD = 200;
17
+
15
     public enum Direction {
18
     public enum Direction {
16
         Up, Down, None
19
         Up, Down, None
17
     }
20
     }
33
     private float totalCollapse = 0;
36
     private float totalCollapse = 0;
34
     private float totalCollapseDeltaSinceTouchDown = 0;
37
     private float totalCollapseDeltaSinceTouchDown = 0;
35
     private final int scaledTouchSlop;
38
     private final int scaledTouchSlop;
39
+    private final int minimumFlingVelocity;
36
 
40
 
37
     public CollapseCalculator(final CollapsingView collapsingView, CollapseBehaviour collapseBehaviour) {
41
     public CollapseCalculator(final CollapsingView collapsingView, CollapseBehaviour collapseBehaviour) {
38
         this.view = collapsingView;
42
         this.view = collapsingView;
39
         this.collapseBehaviour = collapseBehaviour;
43
         this.collapseBehaviour = collapseBehaviour;
40
-        scaledTouchSlop = ViewConfiguration.get(NavigationApplication.instance).getScaledTouchSlop();
44
+        ViewConfiguration vc = ViewConfiguration.get(NavigationApplication.instance);
45
+        scaledTouchSlop = vc.getScaledTouchSlop();
46
+        minimumFlingVelocity = vc.getScaledMinimumFlingVelocity();
41
         setFlingDetector();
47
         setFlingDetector();
42
     }
48
     }
43
 
49
 
46
             flingDetector =
52
             flingDetector =
47
                     new GestureDetector(NavigationApplication.instance, new GestureDetector.SimpleOnGestureListener() {
53
                     new GestureDetector(NavigationApplication.instance, new GestureDetector.SimpleOnGestureListener() {
48
                         @Override
54
                         @Override
49
-                        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
55
+                        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, final float velocityY) {
50
                             final Direction direction = getScrollDirection(e1, e2);
56
                             final Direction direction = getScrollDirection(e1, e2);
51
-                            if (canCollapse(direction) && totalCollapse != 0) {
57
+                            final float diff = Math.abs(e2.getRawY() - e1.getRawY());
58
+
59
+                            if (Math.abs(velocityY) <  minimumFlingVelocity || diff < FLING_DISTANCE_PIXELS_THRESHOLD) {
60
+                                Log.w("FLING", "Consuming fling v: [" + velocityY + "] dy: [" + diff + "]");
61
+                                return true;
62
+                            }
63
+
64
+                            if (canCollapse && totalCollapse != 0) {
52
                                 flingListener.onFling(new CollapseAmount(direction));
65
                                 flingListener.onFling(new CollapseAmount(direction));
66
+                                if (direction == Direction.Up) {
67
+                                    view.asView().postOnAnimation(new Runnable() {
68
+                                        @Override
69
+                                        public void run() {
70
+                                            Log.v("FLING", "v: [" + velocityY + "] dy: [" + diff + "]");
71
+                                            scrollView.fling((int) Math.abs(velocityY));
72
+                                        }
73
+                                    });
74
+                                }
53
                                 return true;
75
                                 return true;
54
                             }
76
                             }
55
-                            return false;
77
+
78
+                            return true;
56
                         }
79
                         }
57
 
80
 
58
                         private Direction getScrollDirection(MotionEvent e1, MotionEvent e2) {
81
                         private Direction getScrollDirection(MotionEvent e1, MotionEvent e2) {
76
     @NonNull
99
     @NonNull
77
     CollapseAmount calculate(MotionEvent event) {
100
     CollapseAmount calculate(MotionEvent event) {
78
         updateInitialTouchY(event);
101
         updateInitialTouchY(event);
79
-        CollapseAmount touchUpCollapse = shouldCollapseOnTouchUp(event);
102
+        final boolean isFling = flingDetector.onTouchEvent(event);
103
+        CollapseAmount touchUpCollapse = shouldCollapseOnTouchUp(event, isFling);
80
         if (touchUpCollapse != CollapseAmount.None) {
104
         if (touchUpCollapse != CollapseAmount.None) {
81
             previousTouchEvent = MotionEvent.obtain(event);
105
             previousTouchEvent = MotionEvent.obtain(event);
82
             return touchUpCollapse;
106
             return touchUpCollapse;
97
         }
121
         }
98
     }
122
     }
99
 
123
 
100
-    private CollapseAmount shouldCollapseOnTouchUp(MotionEvent event) {
101
-        if ((collapseBehaviour.shouldCollapseOnTouchUp())
102
-            && !flingDetector.onTouchEvent(event) && isTouchUp(event)) {
124
+    private CollapseAmount shouldCollapseOnTouchUp(MotionEvent event, boolean isFling) {
125
+        if (isTouchUp(event) && collapseBehaviour.shouldCollapseOnTouchUp() && !isFling) {
103
             final float visibilityPercentage = view.getCurrentCollapseValue() / view.getFinalCollapseValue();
126
             final float visibilityPercentage = view.getCurrentCollapseValue() / view.getFinalCollapseValue();
104
             Direction direction = visibilityPercentage >= 0.5f ? Direction.Up : Direction.Down;
127
             Direction direction = visibilityPercentage >= 0.5f ? Direction.Up : Direction.Down;
105
             if (canCollapse(direction) && totalCollapse != 0) {
128
             if (canCollapse(direction) && totalCollapse != 0) {

+ 9
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingTopBar.java 파일 보기

138
         }
138
         }
139
     }
139
     }
140
 
140
 
141
+    @Override
142
+    public void fling(CollapseAmount amount) {
143
+        if (titleBar instanceof CollapsingTitleBar) {
144
+            viewCollapser.fling(amount, (CollapsingTitleBar) titleBar, header);
145
+        } else {
146
+            viewCollapser.collapse(amount);
147
+        }
148
+    }
149
+
141
     public void onScrollViewAdded(ScrollView scrollView) {
150
     public void onScrollViewAdded(ScrollView scrollView) {
142
         scrollListener.onScrollViewAdded(scrollView);
151
         scrollListener.onScrollViewAdded(scrollView);
143
     }
152
     }

+ 1
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingTopBarReactHeader.java 파일 보기

115
     }
115
     }
116
 
116
 
117
     private void onTouchDown(MotionEvent ev) {
117
     private void onTouchDown(MotionEvent ev) {
118
+        listener.onTouch(ev);
118
         if (touchDown == -1) {
119
         if (touchDown == -1) {
119
             touchDown = (int) ev.getRawY();
120
             touchDown = (int) ev.getRawY();
120
         }
121
         }

+ 2
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingView.java 파일 보기

10
     View asView();
10
     View asView();
11
 
11
 
12
     void collapse(CollapseAmount amount);
12
     void collapse(CollapseAmount amount);
13
+
14
+    void fling(CollapseAmount amount);
13
 }
15
 }

+ 5
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingViewPager.java 파일 보기

43
     public void collapse(CollapseAmount amount) {
43
     public void collapse(CollapseAmount amount) {
44
         viewCollapser.collapse(amount);
44
         viewCollapser.collapse(amount);
45
     }
45
     }
46
+
47
+    @Override
48
+    public void fling(CollapseAmount amount) {
49
+        viewCollapser.fling(amount);
50
+    }
46
 }
51
 }

+ 67
- 3
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/ViewCollapser.java 파일 보기

2
 
2
 
3
 import android.animation.Animator;
3
 import android.animation.Animator;
4
 import android.animation.AnimatorListenerAdapter;
4
 import android.animation.AnimatorListenerAdapter;
5
+import android.animation.ObjectAnimator;
6
+import android.animation.ValueAnimator;
7
+import android.support.annotation.NonNull;
8
+import android.view.View;
5
 import android.view.ViewPropertyAnimator;
9
 import android.view.ViewPropertyAnimator;
10
+import android.view.animation.DecelerateInterpolator;
6
 
11
 
7
 public class ViewCollapser {
12
 public class ViewCollapser {
8
     private static final int DURATION = 160;
13
     private static final int DURATION = 160;
14
+    private static final int FLING_DURATION = 160;
9
     private CollapsingView view;
15
     private CollapsingView view;
16
+
17
+    private final ValueAnimator.AnimatorUpdateListener LISTENER =
18
+            new ValueAnimator.AnimatorUpdateListener() {
19
+                @Override
20
+                public void onAnimationUpdate(ValueAnimator animation) {
21
+                }
22
+            };
10
     private ViewPropertyAnimator animator;
23
     private ViewPropertyAnimator animator;
24
+    private ObjectAnimator flingAnimator;
11
 
25
 
12
     public ViewCollapser(CollapsingView view) {
26
     public ViewCollapser(CollapsingView view) {
13
         this.view = view;
27
         this.view = view;
32
     }
46
     }
33
 
47
 
34
     public void collapse(float amount) {
48
     public void collapse(float amount) {
35
-        if (animator != null) {
36
-            animator.cancel();
37
-        }
49
+        cancelAnimator();
38
         view.asView().setTranslationY(amount);
50
         view.asView().setTranslationY(amount);
39
     }
51
     }
40
 
52
 
55
                 });
67
                 });
56
         animator.start();
68
         animator.start();
57
     }
69
     }
70
+
71
+    void fling(final CollapseAmount amount, final CollapsingTitleBar titleBar, final CollapsingTopBarReactHeader header) {
72
+        fling(amount, new ValueAnimator.AnimatorUpdateListener() {
73
+            @Override
74
+            public void onAnimationUpdate(ValueAnimator animation) {
75
+                titleBar.collapse(new CollapseAmount((Float) animation.getAnimatedValue()));
76
+                header.collapse((Float) animation.getAnimatedValue());
77
+            }
78
+        });
79
+    }
80
+
81
+    public void fling(CollapseAmount amount) {
82
+        fling(amount, LISTENER);
83
+    }
84
+
85
+    private void fling(final CollapseAmount amount, @NonNull final ValueAnimator.AnimatorUpdateListener updateListener) {
86
+        cancelAnimator();
87
+        final float translation = amount.collapseToTop() ? view.getFinalCollapseValue() : 0;
88
+        flingAnimator = ObjectAnimator.ofFloat(view.asView(), View.TRANSLATION_Y, translation);
89
+        flingAnimator.setDuration(FLING_DURATION);
90
+        flingAnimator.setInterpolator(new DecelerateInterpolator());
91
+        flingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
92
+            @Override
93
+            public void onAnimationUpdate(ValueAnimator animation) {
94
+                updateListener.onAnimationUpdate(animation);
95
+            }
96
+        });
97
+        flingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
98
+            @Override
99
+            public void onAnimationUpdate(ValueAnimator animation) {
100
+                updateListener.onAnimationUpdate(animation);
101
+            }
102
+        });
103
+        flingAnimator.addListener(new AnimatorListenerAdapter() {
104
+            @Override
105
+            public void onAnimationCancel(Animator animation) {
106
+                flingAnimator = null;
107
+            }
108
+            @Override
109
+            public void onAnimationEnd(Animator animation) {
110
+                flingAnimator = null;
111
+            }
112
+        });
113
+        flingAnimator.start();
114
+
115
+    }
116
+
117
+    private void cancelAnimator() {
118
+        if (animator != null) {
119
+            animator.cancel();
120
+        }
121
+    }
58
 }
122
 }

+ 1
- 1
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/behaviours/CollapseTopBarBehaviour.java 파일 보기

3
 public class CollapseTopBarBehaviour implements CollapseBehaviour {
3
 public class CollapseTopBarBehaviour implements CollapseBehaviour {
4
     @Override
4
     @Override
5
     public boolean shouldCollapseOnFling() {
5
     public boolean shouldCollapseOnFling() {
6
-        return false;
6
+        return true;
7
     }
7
     }
8
 
8
 
9
     @Override
9
     @Override