瀏覽代碼

Collapsing view pager screen (#448)

Implement collapsing TopTabs on Android

specify `navBarHideOnScroll: true` in your `TopTabsScreen`
Guy Carmeli 8 年之前
父節點
當前提交
3dbcc28d86
共有 26 個檔案被更改,包括 327 行新增63 行删除
  1. 9
    0
      android/app/src/main/java/com/reactnativenavigation/events/ViewPagerScreenScrollStartEvent.java
  2. 2
    2
      android/app/src/main/java/com/reactnativenavigation/params/CollapsingTopBarParams.java
  3. 11
    2
      android/app/src/main/java/com/reactnativenavigation/params/parsers/CollapsingTopBarParamsParser.java
  4. 1
    0
      android/app/src/main/java/com/reactnativenavigation/params/parsers/TopTabParamsParser.java
  5. 6
    5
      android/app/src/main/java/com/reactnativenavigation/screens/CollapsingSingleScreen.java
  6. 107
    0
      android/app/src/main/java/com/reactnativenavigation/screens/CollapsingViewPagerScreen.java
  7. 4
    1
      android/app/src/main/java/com/reactnativenavigation/screens/ContentViewPagerAdapter.java
  8. 9
    5
      android/app/src/main/java/com/reactnativenavigation/screens/ScreenFactory.java
  9. 20
    7
      android/app/src/main/java/com/reactnativenavigation/screens/ViewPagerScreen.java
  10. 1
    0
      android/app/src/main/java/com/reactnativenavigation/views/CollapsingContentView.java
  11. 4
    1
      android/app/src/main/java/com/reactnativenavigation/views/ContentView.java
  12. 1
    1
      android/app/src/main/java/com/reactnativenavigation/views/TopBar.java
  13. 3
    3
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapseAmount.java
  14. 11
    10
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapseCalculator.java
  15. 8
    3
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingTopBar.java
  16. 2
    0
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingView.java
  17. 11
    5
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingViewMeasurer.java
  18. 46
    0
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingViewPager.java
  19. 4
    2
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/ScrollListener.java
  20. 16
    15
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/ViewCollapser.java
  21. 7
    0
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/behaviours/CollapseBehaviour.java
  22. 13
    0
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/behaviours/CollapseTitleBarBehaviour.java
  23. 13
    0
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/behaviours/CollapseTopBarBehaviour.java
  24. 13
    0
      android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/behaviours/TitleBarHideOnScrollBehaviour.java
  25. 3
    1
      android/app/src/main/java/com/reactnativenavigation/views/utils/ScrollViewDetector.java
  26. 2
    0
      src/deprecated/platformSpecificDeprecated.android.js

+ 9
- 0
android/app/src/main/java/com/reactnativenavigation/events/ViewPagerScreenScrollStartEvent.java 查看文件

@@ -0,0 +1,9 @@
1
+package com.reactnativenavigation.events;
2
+
3
+public class ViewPagerScreenScrollStartEvent implements Event {
4
+    public static final String TYPE = "ViewPagerScreenScrollStartEvent";
5
+    @Override
6
+    public String getType() {
7
+        return TYPE;
8
+    }
9
+}

+ 2
- 2
android/app/src/main/java/com/reactnativenavigation/params/CollapsingTopBarParams.java 查看文件

@@ -2,9 +2,9 @@ package com.reactnativenavigation.params;
2 2
 
3 3
 import android.support.annotation.Nullable;
4 4
 
5
-public class CollapsingTopBarParams {
6
-    public enum CollapseBehaviour {TitleBarHideOnScroll, CollapseTopBar}
5
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseBehaviour;
7 6
 
7
+public class CollapsingTopBarParams {
8 8
     public @Nullable String imageUri;
9 9
     public StyleParams.Color scrimColor;
10 10
     public CollapseBehaviour collapseBehaviour;

+ 11
- 2
android/app/src/main/java/com/reactnativenavigation/params/parsers/CollapsingTopBarParamsParser.java 查看文件

@@ -4,8 +4,11 @@ import android.graphics.Color;
4 4
 import android.os.Bundle;
5 5
 
6 6
 import com.reactnativenavigation.params.CollapsingTopBarParams;
7
-import com.reactnativenavigation.params.CollapsingTopBarParams.CollapseBehaviour;
8 7
 import com.reactnativenavigation.params.StyleParams;
8
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseBehaviour;
9
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseTitleBarBehaviour;
10
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseTopBarBehaviour;
11
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.TitleBarHideOnScrollBehaviour;
9 12
 
10 13
 class CollapsingTopBarParamsParser extends Parser {
11 14
     private Bundle params;
@@ -29,7 +32,13 @@ class CollapsingTopBarParamsParser extends Parser {
29 32
     }
30 33
 
31 34
     private CollapseBehaviour getCollapseBehaviour() {
32
-        return shouldHideTitleBarOnScroll() ? CollapseBehaviour.TitleBarHideOnScroll : CollapseBehaviour.CollapseTopBar;
35
+        if (hasBackgroundImage()) {
36
+            return new CollapseTopBarBehaviour();
37
+        }
38
+        if (shouldHideTitleBarOnScroll() && params.getBoolean("drawBelowTopBar", false)) {
39
+            return new CollapseTitleBarBehaviour();
40
+        }
41
+        return new TitleBarHideOnScrollBehaviour();
33 42
     }
34 43
 
35 44
     private boolean hasBackgroundImage() {

+ 1
- 0
android/app/src/main/java/com/reactnativenavigation/params/parsers/TopTabParamsParser.java 查看文件

@@ -32,6 +32,7 @@ public class TopTabParamsParser extends Parser {
32 32
         result.leftButton = ButtonParser.parseLeftButton(params);
33 33
         result.rightButtons = ButtonParser.parseRightButton(params);
34 34
         result.fabParams = ButtonParser.parseFab(params, result.navigationParams.navigatorEventId);
35
+        result.styleParams = new StyleParamsParser(params.getBundle("styleParams")).parse();
35 36
         return result;
36 37
     }
37 38
 }

+ 6
- 5
android/app/src/main/java/com/reactnativenavigation/screens/CollapsingSingleScreen.java 查看文件

@@ -3,17 +3,18 @@ package com.reactnativenavigation.screens;
3 3
 import android.support.v7.app.AppCompatActivity;
4 4
 import android.widget.ScrollView;
5 5
 
6
-import com.reactnativenavigation.params.CollapsingTopBarParams;
7 6
 import com.reactnativenavigation.params.ScreenParams;
8 7
 import com.reactnativenavigation.views.CollapsingContentView;
9 8
 import com.reactnativenavigation.views.LeftButtonOnClickListener;
10 9
 import com.reactnativenavigation.views.collapsingToolbar.CollapseAmount;
11 10
 import com.reactnativenavigation.views.collapsingToolbar.CollapseCalculator;
12
-import com.reactnativenavigation.views.collapsingToolbar.CollapsingContentViewMeasurer;
11
+import com.reactnativenavigation.views.collapsingToolbar.CollapsingViewMeasurer;
13 12
 import com.reactnativenavigation.views.collapsingToolbar.CollapsingTopBar;
13
+import com.reactnativenavigation.views.collapsingToolbar.CollapsingView;
14 14
 import com.reactnativenavigation.views.collapsingToolbar.OnScrollListener;
15 15
 import com.reactnativenavigation.views.collapsingToolbar.OnScrollViewAddedListener;
16 16
 import com.reactnativenavigation.views.collapsingToolbar.ScrollListener;
17
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseBehaviour;
17 18
 
18 19
 public class CollapsingSingleScreen extends SingleScreen {
19 20
 
@@ -38,7 +39,7 @@ public class CollapsingSingleScreen extends SingleScreen {
38 39
     protected void createContent() {
39 40
         contentView = new CollapsingContentView(getContext(), screenParams.screenId, screenParams.navigationParams);
40 41
         if (screenParams.styleParams.drawScreenBelowTopBar) {
41
-            contentView.setViewMeasurer(new CollapsingContentViewMeasurer((CollapsingTopBar) topBar, this));
42
+            contentView.setViewMeasurer(new CollapsingViewMeasurer((CollapsingTopBar) topBar, this));
42 43
         }
43 44
         setupCollapseDetection((CollapsingTopBar) topBar);
44 45
         addView(contentView, createLayoutParams());
@@ -59,7 +60,7 @@ public class CollapsingSingleScreen extends SingleScreen {
59 60
                     @Override
60 61
                     public void onScroll(CollapseAmount amount) {
61 62
                         if (!screenParams.styleParams.titleBarHideOnScroll) {
62
-                            ((CollapsingContentView) contentView).collapse(amount);
63
+                            ((CollapsingView) contentView).collapse(amount);
63 64
                         }
64 65
                         topBar.collapse(amount);
65 66
                     }
@@ -73,7 +74,7 @@ public class CollapsingSingleScreen extends SingleScreen {
73 74
         );
74 75
     }
75 76
 
76
-    private CollapsingTopBarParams.CollapseBehaviour getCollapseBehaviour() {
77
+    private CollapseBehaviour getCollapseBehaviour() {
77 78
         return screenParams.styleParams.collapsingTopBarParams.collapseBehaviour;
78 79
     }
79 80
 }

+ 107
- 0
android/app/src/main/java/com/reactnativenavigation/screens/CollapsingViewPagerScreen.java 查看文件

@@ -0,0 +1,107 @@
1
+package com.reactnativenavigation.screens;
2
+
3
+import android.content.Context;
4
+import android.support.v4.view.ViewPager;
5
+import android.support.v7.app.AppCompatActivity;
6
+import android.widget.ScrollView;
7
+
8
+import com.reactnativenavigation.events.Event;
9
+import com.reactnativenavigation.events.ViewPagerScreenScrollStartEvent;
10
+import com.reactnativenavigation.params.PageParams;
11
+import com.reactnativenavigation.params.ScreenParams;
12
+import com.reactnativenavigation.views.CollapsingContentView;
13
+import com.reactnativenavigation.views.ContentView;
14
+import com.reactnativenavigation.views.LeftButtonOnClickListener;
15
+import com.reactnativenavigation.views.collapsingToolbar.CollapseAmount;
16
+import com.reactnativenavigation.views.collapsingToolbar.CollapseCalculator;
17
+import com.reactnativenavigation.views.collapsingToolbar.CollapsingTopBar;
18
+import com.reactnativenavigation.views.collapsingToolbar.CollapsingView;
19
+import com.reactnativenavigation.views.collapsingToolbar.CollapsingViewMeasurer;
20
+import com.reactnativenavigation.views.collapsingToolbar.CollapsingViewPager;
21
+import com.reactnativenavigation.views.collapsingToolbar.OnScrollListener;
22
+import com.reactnativenavigation.views.collapsingToolbar.OnScrollViewAddedListener;
23
+import com.reactnativenavigation.views.collapsingToolbar.ScrollListener;
24
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseBehaviour;
25
+
26
+public class CollapsingViewPagerScreen extends ViewPagerScreen {
27
+
28
+    public CollapsingViewPagerScreen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener backButtonListener) {
29
+        super(activity, screenParams, backButtonListener);
30
+    }
31
+
32
+    @Override
33
+    protected void createTopBar() {
34
+        final CollapsingTopBar topBar = new CollapsingTopBar(getContext(), styleParams.collapsingTopBarParams);
35
+        topBar.setScrollListener(getScrollListener());
36
+        this.topBar = topBar;
37
+    }
38
+
39
+    @Override
40
+    protected ViewPager createViewPager(Context context) {
41
+        CollapsingViewPager viewPager = new CollapsingViewPager(context);
42
+        if (screenParams.styleParams.drawScreenBelowTopBar) {
43
+            viewPager.setViewMeasurer(new CollapsingViewMeasurer((CollapsingTopBar) topBar, this));
44
+        }
45
+        return viewPager;
46
+    }
47
+
48
+    protected ContentView createContentView(PageParams tab) {
49
+        if (tab.hasCollapsingTopBar()) {
50
+            CollapsingContentView contentView = new CollapsingContentView(getContext(), tab.screenId, tab.navigationParams);
51
+            contentView.setViewMeasurer(new CollapsingViewMeasurer((CollapsingTopBar) topBar, this));
52
+            setupCollapseDetection(contentView);
53
+            return contentView;
54
+        } else {
55
+            return new ContentView(getContext(), tab.screenId, tab.navigationParams);
56
+        }
57
+    }
58
+
59
+    private void setupCollapseDetection(CollapsingContentView contentView) {
60
+        contentView.setupCollapseDetection(getScrollListener(), new OnScrollViewAddedListener() {
61
+            @Override
62
+            public void onScrollViewAdded(ScrollView scrollView) {
63
+                ((CollapsingTopBar) topBar).onScrollViewAdded(scrollView);
64
+            }
65
+        });
66
+    }
67
+
68
+    private ScrollListener getScrollListener() {
69
+        return new ScrollListener(new CollapseCalculator((CollapsingView) topBar, getCollapseBehaviour()),
70
+                new OnScrollListener() {
71
+                    @Override
72
+                    public void onScroll(CollapseAmount amount) {
73
+                        ((CollapsingView) topBar).collapse(amount);
74
+                        ((CollapsingView) viewPager).collapse(amount);
75
+                    }
76
+
77
+                    @Override
78
+                    public void onFling(CollapseAmount amount) {
79
+                        ((CollapsingView) topBar).collapse(amount);
80
+                        ((CollapsingView) viewPager).collapse(amount);
81
+                    }
82
+                },
83
+                getCollapseBehaviour()
84
+        );
85
+    }
86
+
87
+    private CollapseBehaviour getCollapseBehaviour() {
88
+        return screenParams.styleParams.collapsingTopBarParams.collapseBehaviour;
89
+    }
90
+
91
+    @Override
92
+    public void onEvent(Event event) {
93
+        super.onEvent(event);
94
+        if (ViewPagerScreenScrollStartEvent.TYPE.equals(event.getType())) {
95
+            ((CollapsingView) topBar).collapse(new CollapseAmount(CollapseCalculator.Direction.Down));
96
+            ((CollapsingView) viewPager).collapse(new CollapseAmount(CollapseCalculator.Direction.Down));
97
+        }
98
+    }
99
+
100
+    @Override
101
+    public void destroy() {
102
+        super.destroy();
103
+        for (ContentView contentView : contentViews) {
104
+            ((CollapsingContentView) contentView).destroy();
105
+        }
106
+    }
107
+}

+ 4
- 1
android/app/src/main/java/com/reactnativenavigation/screens/ContentViewPagerAdapter.java 查看文件

@@ -11,6 +11,7 @@ import com.reactnativenavigation.NavigationApplication;
11 11
 import com.reactnativenavigation.events.EventBus;
12 12
 import com.reactnativenavigation.events.ScreenChangedEvent;
13 13
 import com.reactnativenavigation.events.ViewPagerScreenChangedEvent;
14
+import com.reactnativenavigation.events.ViewPagerScreenScrollStartEvent;
14 15
 import com.reactnativenavigation.params.PageParams;
15 16
 import com.reactnativenavigation.views.ContentView;
16 17
 
@@ -61,7 +62,9 @@ class ContentViewPagerAdapter extends PagerAdapter implements ViewPager.OnPageCh
61 62
 
62 63
     @Override
63 64
     public void onPageScrollStateChanged(int state) {
64
-
65
+        if (state == ViewPager.SCROLL_STATE_DRAGGING) {
66
+            EventBus.instance.post(new ViewPagerScreenScrollStartEvent());
67
+        }
65 68
     }
66 69
 
67 70
     private void sendTabSelectedEventToJs() {

+ 9
- 5
android/app/src/main/java/com/reactnativenavigation/screens/ScreenFactory.java 查看文件

@@ -5,14 +5,18 @@ import android.support.v7.app.AppCompatActivity;
5 5
 import com.reactnativenavigation.params.ScreenParams;
6 6
 import com.reactnativenavigation.views.LeftButtonOnClickListener;
7 7
 
8
-public class ScreenFactory {
9
-    public static Screen create(AppCompatActivity activity,
10
-                                ScreenParams screenParams,
11
-                                LeftButtonOnClickListener leftButtonOnClickListener) {
8
+class ScreenFactory {
9
+    static Screen create(AppCompatActivity activity,
10
+                         ScreenParams screenParams,
11
+                         LeftButtonOnClickListener leftButtonOnClickListener) {
12 12
         if (screenParams.isFragmentScreen()) {
13 13
             return new FragmentScreen(activity, screenParams, leftButtonOnClickListener);
14 14
         } else if (screenParams.hasTopTabs()) {
15
-            return new ViewPagerScreen(activity, screenParams, leftButtonOnClickListener);
15
+            if (screenParams.hasCollapsingTopBar()) {
16
+                return new CollapsingViewPagerScreen(activity, screenParams, leftButtonOnClickListener);
17
+            } else {
18
+                return new ViewPagerScreen(activity, screenParams, leftButtonOnClickListener);
19
+            }
16 20
         } else if (screenParams.hasCollapsingTopBar()) {
17 21
             return new CollapsingSingleScreen(activity, screenParams, leftButtonOnClickListener);
18 22
         } else {

+ 20
- 7
android/app/src/main/java/com/reactnativenavigation/screens/ViewPagerScreen.java 查看文件

@@ -1,12 +1,13 @@
1 1
 package com.reactnativenavigation.screens;
2 2
 
3
+import android.content.Context;
3 4
 import android.support.design.widget.TabLayout;
4 5
 import android.support.v4.view.ViewPager;
5 6
 import android.support.v7.app.AppCompatActivity;
6 7
 
7 8
 import com.reactnativenavigation.params.BaseScreenParams;
8
-import com.reactnativenavigation.params.ScreenParams;
9 9
 import com.reactnativenavigation.params.PageParams;
10
+import com.reactnativenavigation.params.ScreenParams;
10 11
 import com.reactnativenavigation.views.ContentView;
11 12
 import com.reactnativenavigation.views.LeftButtonOnClickListener;
12 13
 
@@ -18,8 +19,8 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
18 19
 public class ViewPagerScreen extends Screen {
19 20
 
20 21
     private static final int OFFSCREEN_PAGE_LIMIT = 99;
21
-    private List<ContentView> contentViews;
22
-    private ViewPager viewPager;
22
+    protected List<ContentView> contentViews;
23
+    protected ViewPager viewPager;
23 24
 
24 25
     public ViewPagerScreen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener backButtonListener) {
25 26
         super(activity, screenParams, backButtonListener);
@@ -39,7 +40,7 @@ public class ViewPagerScreen extends Screen {
39 40
     }
40 41
 
41 42
     private void createViewPager() {
42
-        viewPager = new ViewPager(getContext());
43
+        viewPager = createViewPager(getContext());
43 44
         viewPager.setOffscreenPageLimit(OFFSCREEN_PAGE_LIMIT);
44 45
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
45 46
         if (screenParams.styleParams.drawScreenBelowTopBar) {
@@ -48,15 +49,27 @@ public class ViewPagerScreen extends Screen {
48 49
         addView(viewPager, lp);
49 50
     }
50 51
 
52
+    protected ViewPager createViewPager(Context context) {
53
+        return new ViewPager(context);
54
+    }
55
+
51 56
     private void addPages() {
52 57
         contentViews = new ArrayList<>();
53 58
         for (PageParams tab : screenParams.topTabParams) {
54
-            ContentView contentView = new ContentView(getContext(), tab.screenId, tab.navigationParams);
55
-            addContent(contentView);
56
-            contentViews.add(contentView);
59
+            addPage(tab);
57 60
         }
58 61
     }
59 62
 
63
+    private void addPage(PageParams tab) {
64
+        ContentView contentView = createContentView(tab);
65
+        addContent(contentView);
66
+        contentViews.add(contentView);
67
+    }
68
+
69
+    protected ContentView createContentView(PageParams tab) {
70
+        return new ContentView(getContext(), tab.screenId, tab.navigationParams);
71
+    }
72
+
60 73
     private void setupViewPager(TabLayout tabLayout) {
61 74
         ContentViewPagerAdapter adapter = new ContentViewPagerAdapter(contentViews, screenParams.topTabParams);
62 75
         viewPager.setAdapter(adapter);

+ 1
- 0
android/app/src/main/java/com/reactnativenavigation/views/CollapsingContentView.java 查看文件

@@ -49,6 +49,7 @@ public class CollapsingContentView extends ContentView implements CollapsingView
49 49
         }
50 50
     }
51 51
 
52
+    @Override
52 53
     public void collapse(CollapseAmount amount) {
53 54
         viewCollapser.collapse(amount);
54 55
     }

+ 4
- 1
android/app/src/main/java/com/reactnativenavigation/views/ContentView.java 查看文件

@@ -1,6 +1,7 @@
1 1
 package com.reactnativenavigation.views;
2 2
 
3 3
 import android.content.Context;
4
+import android.util.Log;
4 5
 import android.view.View;
5 6
 
6 7
 import com.facebook.react.ReactRootView;
@@ -50,8 +51,10 @@ public class ContentView extends ReactRootView {
50 51
     @Override
51 52
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
52 53
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
54
+        int measuredHeight = viewMeasurer.getMeasuredHeight(heightMeasureSpec);
55
+        Log.i("Guy", "measuredHeight: " + measuredHeight + " " + getClass().getSimpleName());
53 56
         setMeasuredDimension(viewMeasurer.getMeasuredWidth(widthMeasureSpec),
54
-                viewMeasurer.getMeasuredHeight(heightMeasureSpec));
57
+                measuredHeight);
55 58
     }
56 59
 
57 60
     @Override

+ 1
- 1
android/app/src/main/java/com/reactnativenavigation/views/TopBar.java 查看文件

@@ -24,7 +24,7 @@ public class TopBar extends AppBarLayout {
24 24
     protected TitleBar titleBar;
25 25
     private ContextualMenu contextualMenu;
26 26
     protected FrameLayout titleBarAndContextualMenuContainer;
27
-    private TopTabs topTabs;
27
+    protected TopTabs topTabs;
28 28
 
29 29
     public TopBar(Context context) {
30 30
         super(context);

+ 3
- 3
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapseAmount.java 查看文件

@@ -12,7 +12,7 @@ public class CollapseAmount {
12 12
         this.amount = amount;
13 13
     }
14 14
 
15
-    CollapseAmount(CollapseCalculator.Direction direction) {
15
+    public CollapseAmount(CollapseCalculator.Direction direction) {
16 16
         this.direction = direction;
17 17
     }
18 18
 
@@ -20,11 +20,11 @@ public class CollapseAmount {
20 20
         return amount != null || this != None;
21 21
     }
22 22
 
23
-    boolean collapseToTop() {
23
+    public boolean collapseToTop() {
24 24
         return direction == CollapseCalculator.Direction.Up;
25 25
     }
26 26
 
27
-    boolean collapseToBottom() {
27
+    public boolean collapseToBottom() {
28 28
         return direction == CollapseCalculator.Direction.Down;
29 29
     }
30 30
 

+ 11
- 10
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapseCalculator.java 查看文件

@@ -7,12 +7,12 @@ import android.view.MotionEvent;
7 7
 import android.widget.ScrollView;
8 8
 
9 9
 import com.reactnativenavigation.NavigationApplication;
10
-import com.reactnativenavigation.params.CollapsingTopBarParams.CollapseBehaviour;
11
-
12
-import static com.reactnativenavigation.params.CollapsingTopBarParams.CollapseBehaviour.TitleBarHideOnScroll;
10
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseBehaviour;
11
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseTitleBarBehaviour;
12
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.TitleBarHideOnScrollBehaviour;
13 13
 
14 14
 public class CollapseCalculator {
15
-    enum Direction {
15
+    public enum Direction {
16 16
         Up, Down, None
17 17
     }
18 18
 
@@ -35,11 +35,11 @@ public class CollapseCalculator {
35 35
     public CollapseCalculator(final CollapsingView collapsingView, CollapseBehaviour collapseBehaviour) {
36 36
         this.view = collapsingView;
37 37
         this.collapseBehaviour = collapseBehaviour;
38
-        setFlingDetector(collapseBehaviour);
38
+        setFlingDetector();
39 39
     }
40 40
 
41
-    private void setFlingDetector(CollapseBehaviour collapseBehaviour) {
42
-        if (collapseBehaviour == TitleBarHideOnScroll) {
41
+    private void setFlingDetector() {
42
+        if (collapseBehaviour.shouldCollapseOnFling()) {
43 43
             flingDetector =
44 44
                     new GestureDetector(NavigationApplication.instance, new GestureDetector.SimpleOnGestureListener() {
45 45
                         @Override
@@ -95,7 +95,8 @@ public class CollapseCalculator {
95 95
     }
96 96
 
97 97
     private CollapseAmount shouldCollapseOnTouchUp(MotionEvent event) {
98
-        if (collapseBehaviour == TitleBarHideOnScroll && !flingDetector.onTouchEvent(event) && isTouchUp(event)) {
98
+        if ((collapseBehaviour.shouldCollapseOnTouchUp())
99
+            && !flingDetector.onTouchEvent(event) && isTouchUp(event)) {
99 100
             final float visibilityPercentage = view.getCurrentCollapseValue() / view.getFinalCollapseValue();
100 101
             Direction direction = visibilityPercentage >= 0.5f ? Direction.Up : Direction.Down;
101 102
             if (canCollapse(direction) && totalCollapse != 0) {
@@ -106,7 +107,7 @@ public class CollapseCalculator {
106 107
     }
107 108
 
108 109
     private boolean shouldCollapseAfterMoveEvent(Direction direction) {
109
-        if (collapseBehaviour == CollapseBehaviour.TitleBarHideOnScroll && !isScrolling()) {
110
+        if (collapseBehaviour instanceof TitleBarHideOnScrollBehaviour && !isScrolling()) {
110 111
             return false;
111 112
         }
112 113
         return canCollapse(direction);
@@ -155,7 +156,7 @@ public class CollapseCalculator {
155 156
     private boolean calculateCanExpend(float currentTopBarTranslation, float finalExpendedTranslation, float finalCollapsedTranslation) {
156 157
         return currentTopBarTranslation >= finalCollapsedTranslation &&
157 158
                currentTopBarTranslation < finalExpendedTranslation &&
158
-               (scrollView.getScrollY() == 0 || collapseBehaviour == CollapseBehaviour.TitleBarHideOnScroll);
159
+               (scrollView.getScrollY() == 0 || (collapseBehaviour instanceof TitleBarHideOnScrollBehaviour || collapseBehaviour instanceof CollapseTitleBarBehaviour));
159 160
     }
160 161
 
161 162
     private boolean isCollapsedAndScrollingDown(Direction direction) {

+ 8
- 3
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingTopBar.java 查看文件

@@ -65,6 +65,7 @@ public class CollapsingTopBar extends TopBar implements CollapsingView {
65 65
         return collapsingTopBarBackground;
66 66
     }
67 67
 
68
+    @Override
68 69
     public void collapse(CollapseAmount amount) {
69 70
         viewCollapser.collapse(amount);
70 71
         if (titleBar instanceof CollapsingTitleBar) {
@@ -85,9 +86,13 @@ public class CollapsingTopBar extends TopBar implements CollapsingView {
85 86
     }
86 87
 
87 88
     public int getCollapsedHeight() {
88
-        return params.hasBackgroundImage() ?
89
-                collapsingTopBarBackground.getCollapsedTopBarHeight() :
90
-                titleBar.getHeight();
89
+        if (params.hasBackgroundImage()) {
90
+            return collapsingTopBarBackground.getCollapsedTopBarHeight();
91
+        } else if (topTabs != null) {
92
+            return topTabs.getHeight();
93
+        } else {
94
+            return titleBar.getHeight();
95
+        }
91 96
     }
92 97
 
93 98
     @Override

+ 2
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingView.java 查看文件

@@ -8,4 +8,6 @@ public interface CollapsingView {
8 8
     float getCurrentCollapseValue();
9 9
 
10 10
     View asView();
11
+
12
+    void collapse(CollapseAmount amount);
11 13
 }

android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingContentViewMeasurer.java → android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingViewMeasurer.java 查看文件

@@ -4,15 +4,17 @@ import com.reactnativenavigation.screens.Screen;
4 4
 import com.reactnativenavigation.utils.ViewUtils;
5 5
 import com.reactnativenavigation.views.utils.ViewMeasurer;
6 6
 
7
-public class CollapsingContentViewMeasurer extends ViewMeasurer {
8
-    private int titleBarHeight;
7
+public class CollapsingViewMeasurer extends ViewMeasurer {
8
+    private int collapsedTopBarHeight;
9
+    private float getFinalCollapseValue;
9 10
     private int screenHeight;
10 11
 
11
-    public CollapsingContentViewMeasurer(final CollapsingTopBar topBar, final Screen collapsingSingleScreen) {
12
+    public CollapsingViewMeasurer(final CollapsingTopBar topBar, final Screen collapsingSingleScreen) {
12 13
         ViewUtils.runOnPreDraw(topBar, new Runnable() {
13 14
             @Override
14 15
             public void run() {
15
-                titleBarHeight = topBar.getCollapsedHeight();
16
+                collapsedTopBarHeight = topBar.getCollapsedHeight();
17
+                getFinalCollapseValue = topBar.getFinalCollapseValue();
16 18
             }
17 19
         });
18 20
 
@@ -24,8 +26,12 @@ public class CollapsingContentViewMeasurer extends ViewMeasurer {
24 26
         });
25 27
     }
26 28
 
29
+    public float getFinalCollapseValue() {
30
+        return getFinalCollapseValue;
31
+    }
32
+
27 33
     @Override
28 34
     public int getMeasuredHeight(int heightMeasureSpec) {
29
-        return screenHeight - titleBarHeight;
35
+        return screenHeight - collapsedTopBarHeight;
30 36
     }
31 37
 }

+ 46
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingViewPager.java 查看文件

@@ -0,0 +1,46 @@
1
+package com.reactnativenavigation.views.collapsingToolbar;
2
+
3
+import android.content.Context;
4
+import android.support.v4.view.ViewPager;
5
+import android.view.View;
6
+
7
+public class CollapsingViewPager extends ViewPager implements CollapsingView {
8
+    CollapsingViewMeasurer viewMeasurer;
9
+    ViewCollapser viewCollapser;
10
+
11
+    public CollapsingViewPager(Context context) {
12
+        super(context);
13
+        viewCollapser = new ViewCollapser(this);
14
+    }
15
+
16
+    public void setViewMeasurer(CollapsingViewMeasurer viewMeasurer) {
17
+        this.viewMeasurer = viewMeasurer;
18
+    }
19
+
20
+    @Override
21
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
22
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
23
+        setMeasuredDimension(viewMeasurer.getMeasuredWidth(widthMeasureSpec),
24
+                viewMeasurer.getMeasuredHeight(heightMeasureSpec));
25
+    }
26
+
27
+    @Override
28
+    public float getFinalCollapseValue() {
29
+        return viewMeasurer.getFinalCollapseValue();
30
+    }
31
+
32
+    @Override
33
+    public float getCurrentCollapseValue() {
34
+        return getTranslationY();
35
+    }
36
+
37
+    @Override
38
+    public View asView() {
39
+        return this;
40
+    }
41
+
42
+    @Override
43
+    public void collapse(CollapseAmount amount) {
44
+        viewCollapser.collapse(amount);
45
+    }
46
+}

+ 4
- 2
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/ScrollListener.java 查看文件

@@ -3,7 +3,9 @@ package com.reactnativenavigation.views.collapsingToolbar;
3 3
 import android.view.MotionEvent;
4 4
 import android.widget.ScrollView;
5 5
 
6
-import com.reactnativenavigation.params.CollapsingTopBarParams.CollapseBehaviour;
6
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseBehaviour;
7
+import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseTopBarBehaviour;
8
+
7 9
 
8 10
 public class ScrollListener {
9 11
     private CollapseCalculator collapseCalculator;
@@ -26,7 +28,7 @@ public class ScrollListener {
26 28
         CollapseAmount amount = collapseCalculator.calculate(event);
27 29
         if (amount.canCollapse()) {
28 30
             scrollListener.onScroll(amount);
29
-            return CollapseBehaviour.CollapseTopBar.equals(collapseBehaviour);
31
+            return collapseBehaviour instanceof CollapseTopBarBehaviour;
30 32
         }
31 33
         return false;
32 34
     }

+ 16
- 15
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/ViewCollapser.java 查看文件

@@ -2,11 +2,12 @@ package com.reactnativenavigation.views.collapsingToolbar;
2 2
 
3 3
 import android.animation.Animator;
4 4
 import android.animation.AnimatorListenerAdapter;
5
+import android.view.ViewPropertyAnimator;
5 6
 
6 7
 public class ViewCollapser {
7 8
     private static final int DURATION = 160;
8 9
     private CollapsingView view;
9
-    private boolean animating;
10
+    private ViewPropertyAnimator animator;
10 11
 
11 12
     public ViewCollapser(CollapsingView view) {
12 13
         this.view = view;
@@ -22,36 +23,36 @@ public class ViewCollapser {
22 23
         }
23 24
     }
24 25
 
25
-    public void collapse(float amount) {
26
-        view.asView().setTranslationY(amount);
27
-    }
28
-
29 26
     private void collapseView(boolean animate, float translation) {
30 27
         if (animate) {
31 28
             animate(translation);
32 29
         } else {
33
-            view.asView().setTranslationY(translation);
30
+            collapse(translation);
34 31
         }
35 32
     }
36 33
 
37
-    private void animate(final float translation) {
38
-        if (animating) {
39
-            return;
34
+    public void collapse(float amount) {
35
+        if (animator != null) {
36
+            animator.cancel();
40 37
         }
41
-        view.asView().animate()
38
+        view.asView().setTranslationY(amount);
39
+    }
40
+
41
+    private void animate(final float translation) {
42
+        animator = view.asView().animate()
42 43
                 .translationY(translation)
43 44
                 .setDuration(DURATION)
44 45
                 .setListener(new AnimatorListenerAdapter() {
45 46
                     @Override
46
-                    public void onAnimationStart(Animator animation) {
47
-                        animating = true;
47
+                    public void onAnimationCancel(Animator animation) {
48
+                        animator = null;
48 49
                     }
49 50
 
50 51
                     @Override
51 52
                     public void onAnimationEnd(Animator animation) {
52
-                        animating = false;
53
+                        animator = null;
53 54
                     }
54
-                })
55
-                .start();
55
+                });
56
+        animator.start();
56 57
     }
57 58
 }

+ 7
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/behaviours/CollapseBehaviour.java 查看文件

@@ -0,0 +1,7 @@
1
+package com.reactnativenavigation.views.collapsingToolbar.behaviours;
2
+
3
+public interface CollapseBehaviour {
4
+    boolean shouldCollapseOnFling();
5
+
6
+    boolean shouldCollapseOnTouchUp();
7
+}

+ 13
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/behaviours/CollapseTitleBarBehaviour.java 查看文件

@@ -0,0 +1,13 @@
1
+package com.reactnativenavigation.views.collapsingToolbar.behaviours;
2
+
3
+public class CollapseTitleBarBehaviour implements CollapseBehaviour {
4
+    @Override
5
+    public boolean shouldCollapseOnFling() {
6
+        return true;
7
+    }
8
+
9
+    @Override
10
+    public boolean shouldCollapseOnTouchUp() {
11
+        return true;
12
+    }
13
+}

+ 13
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/behaviours/CollapseTopBarBehaviour.java 查看文件

@@ -0,0 +1,13 @@
1
+package com.reactnativenavigation.views.collapsingToolbar.behaviours;
2
+
3
+public class CollapseTopBarBehaviour implements CollapseBehaviour {
4
+    @Override
5
+    public boolean shouldCollapseOnFling() {
6
+        return false;
7
+    }
8
+
9
+    @Override
10
+    public boolean shouldCollapseOnTouchUp() {
11
+        return false;
12
+    }
13
+}

+ 13
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/behaviours/TitleBarHideOnScrollBehaviour.java 查看文件

@@ -0,0 +1,13 @@
1
+package com.reactnativenavigation.views.collapsingToolbar.behaviours;
2
+
3
+public class TitleBarHideOnScrollBehaviour implements CollapseBehaviour {
4
+    @Override
5
+    public boolean shouldCollapseOnFling() {
6
+        return true;
7
+    }
8
+
9
+    @Override
10
+    public boolean shouldCollapseOnTouchUp() {
11
+        return true;
12
+    }
13
+}

+ 3
- 1
android/app/src/main/java/com/reactnativenavigation/views/utils/ScrollViewDetector.java 查看文件

@@ -59,6 +59,8 @@ public class ScrollViewDetector {
59 59
     }
60 60
 
61 61
     public void destroy() {
62
-        scrollViewDelegate.getScrollView().removeOnAttachStateChangeListener(stateChangeListener);
62
+        if (scrollViewDelegate.getScrollView() != null) {
63
+            scrollViewDelegate.getScrollView().removeOnAttachStateChangeListener(stateChangeListener);
64
+        }
63 65
     }
64 66
 }

+ 2
- 0
src/deprecated/platformSpecificDeprecated.android.js 查看文件

@@ -44,6 +44,8 @@ function adaptTopTabs(screen, navigatorID) {
44 44
     tab.screen = tab.screenId;
45 45
     addNavigatorButtons(tab);
46 46
     adaptNavigationParams(tab);
47
+    addNavigationStyleParams(tab);
48
+    tab = adaptNavigationStyleToScreenStyle(tab);
47 49
   });
48 50
 }
49 51