Daniel Zlotin 8 years ago
parent
commit
0f2bf32a66

+ 1
- 1
android/app/src/main/java/com/reactnativenavigation/screens/FragmentScreen.java View File

38
     }
38
     }
39
 
39
 
40
     private void addContent() {
40
     private void addContent() {
41
-        ContentView contentView = new ContentView(getContext(), screenParams.screenId, screenParams.passProps, screenParams.navigationParams, null);
41
+        ContentView contentView = new ContentView(getContext(), screenParams.screenId, screenParams.passProps, screenParams.navigationParams, topBar);
42
         addView(contentView, 0, 0);
42
         addView(contentView, 0, 0);
43
         LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
43
         LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
44
         if (screenParams.styleParams.drawScreenBelowTopBar) {
44
         if (screenParams.styleParams.drawScreenBelowTopBar) {

+ 3
- 24
android/app/src/main/java/com/reactnativenavigation/screens/Screen.java View File

9
 import android.view.Window;
9
 import android.view.Window;
10
 import android.widget.RelativeLayout;
10
 import android.widget.RelativeLayout;
11
 
11
 
12
-import com.reactnativenavigation.animation.VisibilityAnimator;
13
 import com.reactnativenavigation.params.ScreenParams;
12
 import com.reactnativenavigation.params.ScreenParams;
14
 import com.reactnativenavigation.params.StyleParams;
13
 import com.reactnativenavigation.params.StyleParams;
15
 import com.reactnativenavigation.params.TitleBarButtonParams;
14
 import com.reactnativenavigation.params.TitleBarButtonParams;
16
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
15
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
17
 import com.reactnativenavigation.utils.SdkSupports;
16
 import com.reactnativenavigation.utils.SdkSupports;
18
-import com.reactnativenavigation.utils.ViewUtils;
19
-import com.reactnativenavigation.views.ScrollDirectionListener;
20
 import com.reactnativenavigation.views.TitleBarBackButtonListener;
17
 import com.reactnativenavigation.views.TitleBarBackButtonListener;
21
 import com.reactnativenavigation.views.TopBar;
18
 import com.reactnativenavigation.views.TopBar;
22
 
19
 
25
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
22
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
26
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
23
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
27
 
24
 
28
-public abstract class Screen extends RelativeLayout implements ScrollDirectionListener.OnScrollChanged {
25
+public abstract class Screen extends RelativeLayout {
29
 
26
 
30
     protected final AppCompatActivity activity;
27
     protected final AppCompatActivity activity;
31
     protected final ScreenParams screenParams;
28
     protected final ScreenParams screenParams;
32
     protected TopBar topBar;
29
     protected TopBar topBar;
33
     private final TitleBarBackButtonListener titleBarBackButtonListener;
30
     private final TitleBarBackButtonListener titleBarBackButtonListener;
34
-    private VisibilityAnimator topBarVisibilityAnimator;
35
 
31
 
36
     public Screen(AppCompatActivity activity, ScreenParams screenParams, TitleBarBackButtonListener titleBarBackButtonListener) {
32
     public Screen(AppCompatActivity activity, ScreenParams screenParams, TitleBarBackButtonListener titleBarBackButtonListener) {
37
         super(activity);
33
         super(activity);
59
 
55
 
60
     private void createTopBar() {
56
     private void createTopBar() {
61
         topBar = new TopBar(getContext());
57
         topBar = new TopBar(getContext());
62
-        createTopBarVisibilityAnimator();
63
         addView(topBar, new LayoutParams(MATCH_PARENT, WRAP_CONTENT));
58
         addView(topBar, new LayoutParams(MATCH_PARENT, WRAP_CONTENT));
64
     }
59
     }
65
 
60
 
66
-    private void createTopBarVisibilityAnimator() {
67
-        ViewUtils.runOnPreDraw(topBar, new Runnable() {
68
-            @Override
69
-            public void run() {
70
-                if (topBarVisibilityAnimator == null) {
71
-                    topBarVisibilityAnimator = new VisibilityAnimator(topBar, VisibilityAnimator.HideDirection.Up, topBar.getHeight());
72
-                }
73
-            }
74
-        });
75
-    }
76
-
77
-    private void setStyle(StyleParams styleParams) {
61
+    private void setStyle(ScreenStyleParams styleParams) {
78
         setStatusBarColor(styleParams.statusBarColor);
62
         setStatusBarColor(styleParams.statusBarColor);
79
         setNavigationBarColor(styleParams.navigationBarColor);
63
         setNavigationBarColor(styleParams.navigationBarColor);
80
         topBar.setStyle(styleParams);
64
         topBar.setStyle(styleParams);
122
         Log.d("LOG", "Screen.onDetachedFromWindow " + this);
106
         Log.d("LOG", "Screen.onDetachedFromWindow " + this);
123
     }
107
     }
124
 
108
 
125
-    @Override
126
-    public void onScrollChanged(ScrollDirectionListener.Direction direction) {
127
-        topBarVisibilityAnimator.onScrollChanged(direction);
128
-    }
129
-
130
     public abstract void ensureUnmountOnDetachedFromWindow();
109
     public abstract void ensureUnmountOnDetachedFromWindow();
131
 
110
 
132
     public abstract void preventUnmountOnDetachedFromWindow();
111
     public abstract void preventUnmountOnDetachedFromWindow();
138
     }
117
     }
139
 
118
 
140
     public void setTopBarVisible(boolean visible, boolean animate) {
119
     public void setTopBarVisible(boolean visible, boolean animate) {
141
-        topBarVisibilityAnimator.setVisible(visible, animate);
120
+//        topBarVisibilityAnimator.setVisible(visible, animate); TODO
142
     }
121
     }
143
 
122
 
144
     public void setTitleBarTitle(String title) {
123
     public void setTitleBarTitle(String title) {

+ 1
- 1
android/app/src/main/java/com/reactnativenavigation/screens/SingleScreen.java View File

19
 
19
 
20
     @Override
20
     @Override
21
     protected void createContent() {
21
     protected void createContent() {
22
-        contentView = new ContentView(getContext(), screenParams.screenId, screenParams.passProps, screenParams.navigationParams, this);
22
+        contentView = new ContentView(getContext(), screenParams.screenId, screenParams.passProps, screenParams.navigationParams, topBar);
23
         LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
23
         LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
24
         if (screenParams.styleParams.drawScreenBelowTopBar) {
24
         if (screenParams.styleParams.drawScreenBelowTopBar) {
25
             params.addRule(BELOW, topBar.getId());
25
             params.addRule(BELOW, topBar.getId());

+ 1
- 2
android/app/src/main/java/com/reactnativenavigation/screens/ViewPagerScreen.java View File

39
             ContentView contentView = new ContentView(getContext(),
39
             ContentView contentView = new ContentView(getContext(),
40
                     topTabParam.screenId,
40
                     topTabParam.screenId,
41
                     screenParams.passProps,
41
                     screenParams.passProps,
42
-                    screenParams.navigationParams,
43
-                    this);
42
+                    screenParams.navigationParams, topBar);
44
             addContent(contentView);
43
             addContent(contentView);
45
             contentViews.add(contentView);
44
             contentViews.add(contentView);
46
         }
45
         }

+ 4
- 0
android/app/src/main/java/com/reactnativenavigation/utils/SdkSupports.java View File

7
     public static boolean lollipop() {
7
     public static boolean lollipop() {
8
         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
8
         return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
9
     }
9
     }
10
+
11
+    public static boolean marshmallow() {
12
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
13
+    }
10
 }
14
 }

+ 47
- 8
android/app/src/main/java/com/reactnativenavigation/views/ContentView.java View File

3
 import android.content.Context;
3
 import android.content.Context;
4
 import android.os.Bundle;
4
 import android.os.Bundle;
5
 import android.view.View;
5
 import android.view.View;
6
+import android.widget.ScrollView;
6
 
7
 
7
 import com.facebook.react.ReactInstanceManager;
8
 import com.facebook.react.ReactInstanceManager;
8
 import com.facebook.react.ReactRootView;
9
 import com.facebook.react.ReactRootView;
14
     private final String screenId;
15
     private final String screenId;
15
     private final Bundle passProps;
16
     private final Bundle passProps;
16
     private Bundle navigationParams;
17
     private Bundle navigationParams;
17
-    private ScrollViewAttacher scrollViewAttacher;
18
+    private ScrollViewDelegate scrollViewDelegate = new ScrollViewDelegate();
18
 
19
 
19
-    public ContentView(Context context, String screenId, Bundle passProps, Bundle navigationParams, ScrollDirectionListener.OnScrollChanged scrollListener) {
20
+    public ContentView(Context context, final String screenId, Bundle passProps, Bundle navigationParams, final TopBar topBar) {
20
         super(context);
21
         super(context);
21
         this.screenId = screenId;
22
         this.screenId = screenId;
22
         this.passProps = passProps;
23
         this.passProps = passProps;
23
         this.navigationParams = navigationParams;
24
         this.navigationParams = navigationParams;
24
-        if (scrollListener != null) {
25
-            scrollViewAttacher = new ScrollViewAttacher(scrollListener);
26
-        }
27
         attachToJS();
25
         attachToJS();
26
+
27
+        scrollViewDelegate.setListener(new ScrollViewDelegate.OnScrollListener() {
28
+
29
+            private ScrollDirection scrollDirectionComputer;
30
+
31
+
32
+            @Override
33
+            public void onScroll(ScrollView scrollView) {
34
+                /**
35
+                 * do our magic
36
+                 */
37
+                if (scrollDirectionComputer == null) {
38
+                    scrollDirectionComputer = new ScrollDirection(scrollView);
39
+                }
40
+
41
+                int currentTopBarTranslation = (int) topBar.getTranslationY();
42
+                int delta = scrollDirectionComputer.getScrollDelta();
43
+
44
+                int minTranslation = -topBar.getTitleBar().getHeight();
45
+                int maxTranslation = 0;
46
+
47
+                ScrollDirection.Direction direction = scrollDirectionComputer.getScrollDirection();
48
+
49
+                boolean reachedMinimum = direction == ScrollDirection.Direction.Up && currentTopBarTranslation <= minTranslation;
50
+                boolean reachedMaximum = direction == ScrollDirection.Direction.Down && currentTopBarTranslation >= maxTranslation;
51
+
52
+                if (direction == ScrollDirection.Direction.None || reachedMinimum || reachedMaximum) {
53
+                    if (reachedMinimum) {
54
+                        topBar.animate().translationY(minTranslation);
55
+                    }
56
+                    if (reachedMaximum) {
57
+                        topBar.animate().translationY(maxTranslation);
58
+                    }
59
+                } else {
60
+
61
+                    int target = currentTopBarTranslation - delta;
62
+                    int bound = Math.min(Math.max(minTranslation, target), maxTranslation);
63
+
64
+                    topBar.setTranslationY(bound);
65
+                }
66
+
67
+            }
68
+        });
28
     }
69
     }
29
 
70
 
30
     private void attachToJS() {
71
     private void attachToJS() {
35
     @Override
76
     @Override
36
     public void onViewAdded(View child) {
77
     public void onViewAdded(View child) {
37
         super.onViewAdded(child);
78
         super.onViewAdded(child);
38
-        if (scrollViewAttacher != null) {
39
-            scrollViewAttacher.onViewAdded(child);
40
-        }
79
+        scrollViewDelegate.onViewAdded(child);
41
     }
80
     }
42
 
81
 
43
     private Bundle mergePropsAndNavigationParams() {
82
     private Bundle mergePropsAndNavigationParams() {

+ 50
- 0
android/app/src/main/java/com/reactnativenavigation/views/ScrollDirection.java View File

1
+package com.reactnativenavigation.views;
2
+
3
+import android.widget.ScrollView;
4
+
5
+public class ScrollDirection {
6
+
7
+    public enum Direction {
8
+        Up, Down, None
9
+    }
10
+
11
+    private final ScrollView scrollView;
12
+    private int lastScrollY = 0;
13
+
14
+    public ScrollDirection(ScrollView scrollView) {
15
+        this.scrollView = scrollView;
16
+    }
17
+
18
+    public Direction getScrollDirection() {
19
+        Direction direction = Direction.None;
20
+
21
+        final int scrollY = scrollView.getScrollY();
22
+        if (isScrollPositionChanged(scrollY) && !isTopOverscroll(scrollY) && !isBottomOverscroll(scrollY)) {
23
+            direction = getScrollDirection(scrollY);
24
+            lastScrollY = scrollY;
25
+        }
26
+        return direction;
27
+    }
28
+
29
+    public int getScrollDelta() {
30
+        return scrollView.getScrollY() - lastScrollY;
31
+    }
32
+
33
+
34
+    private Direction getScrollDirection(int scrollY) {
35
+        return scrollY > lastScrollY ? Direction.Up : Direction.Down;
36
+    }
37
+
38
+    private boolean isBottomOverscroll(int scrollY) {
39
+        return scrollY >= (scrollView.getChildAt(0).getHeight() - scrollView.getHeight());
40
+    }
41
+
42
+    private boolean isTopOverscroll(int scrollY) {
43
+        return scrollY <= 0;
44
+    }
45
+
46
+    private boolean isScrollPositionChanged(int scrollY) {
47
+        return scrollY != lastScrollY;
48
+    }
49
+
50
+}

+ 0
- 32
android/app/src/main/java/com/reactnativenavigation/views/ScrollViewAttacher.java View File

1
-package com.reactnativenavigation.views;
2
-
3
-import android.view.View;
4
-import android.widget.ScrollView;
5
-
6
-public class ScrollViewAttacher {
7
-
8
-    private final ScrollDirectionListener.OnScrollChanged onChanged;
9
-    private ScrollView scrollView;
10
-    private ScrollDirectionListener scrollDirectionListener;
11
-
12
-    public ScrollViewAttacher(ScrollDirectionListener.OnScrollChanged onChanged) {
13
-        this.onChanged = onChanged;
14
-    }
15
-
16
-    public void onViewAdded(View child) {
17
-        if (child instanceof ScrollView) {
18
-            detach();
19
-            scrollView = (ScrollView) child;
20
-            scrollDirectionListener = new ScrollDirectionListener(scrollView, onChanged);
21
-            scrollView.getViewTreeObserver().addOnScrollChangedListener(scrollDirectionListener);
22
-        }
23
-    }
24
-
25
-    private void detach() {
26
-        if (scrollView != null) {
27
-            scrollView.getViewTreeObserver().removeOnScrollChangedListener(scrollDirectionListener);
28
-            scrollDirectionListener = null;
29
-            scrollView = null;
30
-        }
31
-    }
32
-}

+ 59
- 0
android/app/src/main/java/com/reactnativenavigation/views/ScrollViewDelegate.java View File

1
+package com.reactnativenavigation.views;
2
+
3
+import android.view.View;
4
+import android.view.ViewTreeObserver;
5
+import android.widget.ScrollView;
6
+
7
+import com.reactnativenavigation.utils.SdkSupports;
8
+
9
+public class ScrollViewDelegate implements ViewTreeObserver.OnScrollChangedListener {
10
+
11
+    public interface OnScrollListener {
12
+        void onScroll(ScrollView scrollView);
13
+    }
14
+
15
+    private ScrollView scrollView;
16
+    private OnScrollListener listener;
17
+
18
+    public ScrollViewDelegate() {
19
+    }
20
+
21
+    public void onViewAdded(View child) {
22
+        if (child instanceof ScrollView) {
23
+            detach();
24
+            scrollView = (ScrollView) child;
25
+            if (SdkSupports.marshmallow()) {
26
+                scrollView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
27
+                    @Override
28
+                    public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
29
+                        ScrollViewDelegate.this.onScrollChanged();
30
+                    }
31
+                });
32
+            } else {
33
+                scrollView.getViewTreeObserver().addOnScrollChangedListener(this);
34
+            }
35
+        }
36
+    }
37
+
38
+    private void detach() {
39
+        if (scrollView != null) {
40
+            if (SdkSupports.marshmallow()) {
41
+                scrollView.setOnScrollChangeListener(null);
42
+            } else {
43
+                scrollView.getViewTreeObserver().removeOnScrollChangedListener(this);
44
+            }
45
+            scrollView = null;
46
+        }
47
+    }
48
+
49
+    public void setListener(OnScrollListener listener) {
50
+        this.listener = listener;
51
+    }
52
+
53
+    @Override
54
+    public void onScrollChanged() {
55
+        if (this.listener != null) {
56
+            this.listener.onScroll(scrollView);
57
+        }
58
+    }
59
+}

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

58
                                        TitleBarLeftButtonParams titleBarLeftButtonParams) {
58
                                        TitleBarLeftButtonParams titleBarLeftButtonParams) {
59
         titleBar.setLeftButton(titleBarLeftButtonParams, titleBarBackButtonListener, navigatorEventId);
59
         titleBar.setLeftButton(titleBarLeftButtonParams, titleBarBackButtonListener, navigatorEventId);
60
     }
60
     }
61
+
62
+    public TitleBar getTitleBar() {
63
+        return titleBar;
64
+    }
61
 }
65
 }