Browse Source

Collapsing view pager screen (#448)

Implement collapsing TopTabs on Android

specify `navBarHideOnScroll: true` in your `TopTabsScreen`
Guy Carmeli 8 years ago
parent
commit
3dbcc28d86
26 changed files with 327 additions and 63 deletions
  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 View File

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 View File

2
 
2
 
3
 import android.support.annotation.Nullable;
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
     public @Nullable String imageUri;
8
     public @Nullable String imageUri;
9
     public StyleParams.Color scrimColor;
9
     public StyleParams.Color scrimColor;
10
     public CollapseBehaviour collapseBehaviour;
10
     public CollapseBehaviour collapseBehaviour;

+ 11
- 2
android/app/src/main/java/com/reactnativenavigation/params/parsers/CollapsingTopBarParamsParser.java View File

4
 import android.os.Bundle;
4
 import android.os.Bundle;
5
 
5
 
6
 import com.reactnativenavigation.params.CollapsingTopBarParams;
6
 import com.reactnativenavigation.params.CollapsingTopBarParams;
7
-import com.reactnativenavigation.params.CollapsingTopBarParams.CollapseBehaviour;
8
 import com.reactnativenavigation.params.StyleParams;
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
 class CollapsingTopBarParamsParser extends Parser {
13
 class CollapsingTopBarParamsParser extends Parser {
11
     private Bundle params;
14
     private Bundle params;
29
     }
32
     }
30
 
33
 
31
     private CollapseBehaviour getCollapseBehaviour() {
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
     private boolean hasBackgroundImage() {
44
     private boolean hasBackgroundImage() {

+ 1
- 0
android/app/src/main/java/com/reactnativenavigation/params/parsers/TopTabParamsParser.java View File

32
         result.leftButton = ButtonParser.parseLeftButton(params);
32
         result.leftButton = ButtonParser.parseLeftButton(params);
33
         result.rightButtons = ButtonParser.parseRightButton(params);
33
         result.rightButtons = ButtonParser.parseRightButton(params);
34
         result.fabParams = ButtonParser.parseFab(params, result.navigationParams.navigatorEventId);
34
         result.fabParams = ButtonParser.parseFab(params, result.navigationParams.navigatorEventId);
35
+        result.styleParams = new StyleParamsParser(params.getBundle("styleParams")).parse();
35
         return result;
36
         return result;
36
     }
37
     }
37
 }
38
 }

+ 6
- 5
android/app/src/main/java/com/reactnativenavigation/screens/CollapsingSingleScreen.java View File

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

+ 107
- 0
android/app/src/main/java/com/reactnativenavigation/screens/CollapsingViewPagerScreen.java View File

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 View File

11
 import com.reactnativenavigation.events.EventBus;
11
 import com.reactnativenavigation.events.EventBus;
12
 import com.reactnativenavigation.events.ScreenChangedEvent;
12
 import com.reactnativenavigation.events.ScreenChangedEvent;
13
 import com.reactnativenavigation.events.ViewPagerScreenChangedEvent;
13
 import com.reactnativenavigation.events.ViewPagerScreenChangedEvent;
14
+import com.reactnativenavigation.events.ViewPagerScreenScrollStartEvent;
14
 import com.reactnativenavigation.params.PageParams;
15
 import com.reactnativenavigation.params.PageParams;
15
 import com.reactnativenavigation.views.ContentView;
16
 import com.reactnativenavigation.views.ContentView;
16
 
17
 
61
 
62
 
62
     @Override
63
     @Override
63
     public void onPageScrollStateChanged(int state) {
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
     private void sendTabSelectedEventToJs() {
70
     private void sendTabSelectedEventToJs() {

+ 9
- 5
android/app/src/main/java/com/reactnativenavigation/screens/ScreenFactory.java View File

5
 import com.reactnativenavigation.params.ScreenParams;
5
 import com.reactnativenavigation.params.ScreenParams;
6
 import com.reactnativenavigation.views.LeftButtonOnClickListener;
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
         if (screenParams.isFragmentScreen()) {
12
         if (screenParams.isFragmentScreen()) {
13
             return new FragmentScreen(activity, screenParams, leftButtonOnClickListener);
13
             return new FragmentScreen(activity, screenParams, leftButtonOnClickListener);
14
         } else if (screenParams.hasTopTabs()) {
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
         } else if (screenParams.hasCollapsingTopBar()) {
20
         } else if (screenParams.hasCollapsingTopBar()) {
17
             return new CollapsingSingleScreen(activity, screenParams, leftButtonOnClickListener);
21
             return new CollapsingSingleScreen(activity, screenParams, leftButtonOnClickListener);
18
         } else {
22
         } else {

+ 20
- 7
android/app/src/main/java/com/reactnativenavigation/screens/ViewPagerScreen.java View File

1
 package com.reactnativenavigation.screens;
1
 package com.reactnativenavigation.screens;
2
 
2
 
3
+import android.content.Context;
3
 import android.support.design.widget.TabLayout;
4
 import android.support.design.widget.TabLayout;
4
 import android.support.v4.view.ViewPager;
5
 import android.support.v4.view.ViewPager;
5
 import android.support.v7.app.AppCompatActivity;
6
 import android.support.v7.app.AppCompatActivity;
6
 
7
 
7
 import com.reactnativenavigation.params.BaseScreenParams;
8
 import com.reactnativenavigation.params.BaseScreenParams;
8
-import com.reactnativenavigation.params.ScreenParams;
9
 import com.reactnativenavigation.params.PageParams;
9
 import com.reactnativenavigation.params.PageParams;
10
+import com.reactnativenavigation.params.ScreenParams;
10
 import com.reactnativenavigation.views.ContentView;
11
 import com.reactnativenavigation.views.ContentView;
11
 import com.reactnativenavigation.views.LeftButtonOnClickListener;
12
 import com.reactnativenavigation.views.LeftButtonOnClickListener;
12
 
13
 
18
 public class ViewPagerScreen extends Screen {
19
 public class ViewPagerScreen extends Screen {
19
 
20
 
20
     private static final int OFFSCREEN_PAGE_LIMIT = 99;
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
     public ViewPagerScreen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener backButtonListener) {
25
     public ViewPagerScreen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener backButtonListener) {
25
         super(activity, screenParams, backButtonListener);
26
         super(activity, screenParams, backButtonListener);
39
     }
40
     }
40
 
41
 
41
     private void createViewPager() {
42
     private void createViewPager() {
42
-        viewPager = new ViewPager(getContext());
43
+        viewPager = createViewPager(getContext());
43
         viewPager.setOffscreenPageLimit(OFFSCREEN_PAGE_LIMIT);
44
         viewPager.setOffscreenPageLimit(OFFSCREEN_PAGE_LIMIT);
44
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
45
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
45
         if (screenParams.styleParams.drawScreenBelowTopBar) {
46
         if (screenParams.styleParams.drawScreenBelowTopBar) {
48
         addView(viewPager, lp);
49
         addView(viewPager, lp);
49
     }
50
     }
50
 
51
 
52
+    protected ViewPager createViewPager(Context context) {
53
+        return new ViewPager(context);
54
+    }
55
+
51
     private void addPages() {
56
     private void addPages() {
52
         contentViews = new ArrayList<>();
57
         contentViews = new ArrayList<>();
53
         for (PageParams tab : screenParams.topTabParams) {
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
     private void setupViewPager(TabLayout tabLayout) {
73
     private void setupViewPager(TabLayout tabLayout) {
61
         ContentViewPagerAdapter adapter = new ContentViewPagerAdapter(contentViews, screenParams.topTabParams);
74
         ContentViewPagerAdapter adapter = new ContentViewPagerAdapter(contentViews, screenParams.topTabParams);
62
         viewPager.setAdapter(adapter);
75
         viewPager.setAdapter(adapter);

+ 1
- 0
android/app/src/main/java/com/reactnativenavigation/views/CollapsingContentView.java View File

49
         }
49
         }
50
     }
50
     }
51
 
51
 
52
+    @Override
52
     public void collapse(CollapseAmount amount) {
53
     public void collapse(CollapseAmount amount) {
53
         viewCollapser.collapse(amount);
54
         viewCollapser.collapse(amount);
54
     }
55
     }

+ 4
- 1
android/app/src/main/java/com/reactnativenavigation/views/ContentView.java View File

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

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

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

+ 3
- 3
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapseAmount.java View File

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

+ 11
- 10
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapseCalculator.java View File

7
 import android.widget.ScrollView;
7
 import android.widget.ScrollView;
8
 
8
 
9
 import com.reactnativenavigation.NavigationApplication;
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
 public class CollapseCalculator {
14
 public class CollapseCalculator {
15
-    enum Direction {
15
+    public enum Direction {
16
         Up, Down, None
16
         Up, Down, None
17
     }
17
     }
18
 
18
 
35
     public CollapseCalculator(final CollapsingView collapsingView, CollapseBehaviour collapseBehaviour) {
35
     public CollapseCalculator(final CollapsingView collapsingView, CollapseBehaviour collapseBehaviour) {
36
         this.view = collapsingView;
36
         this.view = collapsingView;
37
         this.collapseBehaviour = collapseBehaviour;
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
             flingDetector =
43
             flingDetector =
44
                     new GestureDetector(NavigationApplication.instance, new GestureDetector.SimpleOnGestureListener() {
44
                     new GestureDetector(NavigationApplication.instance, new GestureDetector.SimpleOnGestureListener() {
45
                         @Override
45
                         @Override
95
     }
95
     }
96
 
96
 
97
     private CollapseAmount shouldCollapseOnTouchUp(MotionEvent event) {
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
             final float visibilityPercentage = view.getCurrentCollapseValue() / view.getFinalCollapseValue();
100
             final float visibilityPercentage = view.getCurrentCollapseValue() / view.getFinalCollapseValue();
100
             Direction direction = visibilityPercentage >= 0.5f ? Direction.Up : Direction.Down;
101
             Direction direction = visibilityPercentage >= 0.5f ? Direction.Up : Direction.Down;
101
             if (canCollapse(direction) && totalCollapse != 0) {
102
             if (canCollapse(direction) && totalCollapse != 0) {
106
     }
107
     }
107
 
108
 
108
     private boolean shouldCollapseAfterMoveEvent(Direction direction) {
109
     private boolean shouldCollapseAfterMoveEvent(Direction direction) {
109
-        if (collapseBehaviour == CollapseBehaviour.TitleBarHideOnScroll && !isScrolling()) {
110
+        if (collapseBehaviour instanceof TitleBarHideOnScrollBehaviour && !isScrolling()) {
110
             return false;
111
             return false;
111
         }
112
         }
112
         return canCollapse(direction);
113
         return canCollapse(direction);
155
     private boolean calculateCanExpend(float currentTopBarTranslation, float finalExpendedTranslation, float finalCollapsedTranslation) {
156
     private boolean calculateCanExpend(float currentTopBarTranslation, float finalExpendedTranslation, float finalCollapsedTranslation) {
156
         return currentTopBarTranslation >= finalCollapsedTranslation &&
157
         return currentTopBarTranslation >= finalCollapsedTranslation &&
157
                currentTopBarTranslation < finalExpendedTranslation &&
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
     private boolean isCollapsedAndScrollingDown(Direction direction) {
162
     private boolean isCollapsedAndScrollingDown(Direction direction) {

+ 8
- 3
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingTopBar.java View File

65
         return collapsingTopBarBackground;
65
         return collapsingTopBarBackground;
66
     }
66
     }
67
 
67
 
68
+    @Override
68
     public void collapse(CollapseAmount amount) {
69
     public void collapse(CollapseAmount amount) {
69
         viewCollapser.collapse(amount);
70
         viewCollapser.collapse(amount);
70
         if (titleBar instanceof CollapsingTitleBar) {
71
         if (titleBar instanceof CollapsingTitleBar) {
85
     }
86
     }
86
 
87
 
87
     public int getCollapsedHeight() {
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
     @Override
98
     @Override

+ 2
- 0
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingView.java View File

8
     float getCurrentCollapseValue();
8
     float getCurrentCollapseValue();
9
 
9
 
10
     View asView();
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 View File

4
 import com.reactnativenavigation.utils.ViewUtils;
4
 import com.reactnativenavigation.utils.ViewUtils;
5
 import com.reactnativenavigation.views.utils.ViewMeasurer;
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
     private int screenHeight;
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
         ViewUtils.runOnPreDraw(topBar, new Runnable() {
13
         ViewUtils.runOnPreDraw(topBar, new Runnable() {
13
             @Override
14
             @Override
14
             public void run() {
15
             public void run() {
15
-                titleBarHeight = topBar.getCollapsedHeight();
16
+                collapsedTopBarHeight = topBar.getCollapsedHeight();
17
+                getFinalCollapseValue = topBar.getFinalCollapseValue();
16
             }
18
             }
17
         });
19
         });
18
 
20
 
24
         });
26
         });
25
     }
27
     }
26
 
28
 
29
+    public float getFinalCollapseValue() {
30
+        return getFinalCollapseValue;
31
+    }
32
+
27
     @Override
33
     @Override
28
     public int getMeasuredHeight(int heightMeasureSpec) {
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 View File

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 View File

3
 import android.view.MotionEvent;
3
 import android.view.MotionEvent;
4
 import android.widget.ScrollView;
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
 public class ScrollListener {
10
 public class ScrollListener {
9
     private CollapseCalculator collapseCalculator;
11
     private CollapseCalculator collapseCalculator;
26
         CollapseAmount amount = collapseCalculator.calculate(event);
28
         CollapseAmount amount = collapseCalculator.calculate(event);
27
         if (amount.canCollapse()) {
29
         if (amount.canCollapse()) {
28
             scrollListener.onScroll(amount);
30
             scrollListener.onScroll(amount);
29
-            return CollapseBehaviour.CollapseTopBar.equals(collapseBehaviour);
31
+            return collapseBehaviour instanceof CollapseTopBarBehaviour;
30
         }
32
         }
31
         return false;
33
         return false;
32
     }
34
     }

+ 16
- 15
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/ViewCollapser.java View File

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.view.ViewPropertyAnimator;
5
 
6
 
6
 public class ViewCollapser {
7
 public class ViewCollapser {
7
     private static final int DURATION = 160;
8
     private static final int DURATION = 160;
8
     private CollapsingView view;
9
     private CollapsingView view;
9
-    private boolean animating;
10
+    private ViewPropertyAnimator animator;
10
 
11
 
11
     public ViewCollapser(CollapsingView view) {
12
     public ViewCollapser(CollapsingView view) {
12
         this.view = view;
13
         this.view = view;
22
         }
23
         }
23
     }
24
     }
24
 
25
 
25
-    public void collapse(float amount) {
26
-        view.asView().setTranslationY(amount);
27
-    }
28
-
29
     private void collapseView(boolean animate, float translation) {
26
     private void collapseView(boolean animate, float translation) {
30
         if (animate) {
27
         if (animate) {
31
             animate(translation);
28
             animate(translation);
32
         } else {
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
                 .translationY(translation)
43
                 .translationY(translation)
43
                 .setDuration(DURATION)
44
                 .setDuration(DURATION)
44
                 .setListener(new AnimatorListenerAdapter() {
45
                 .setListener(new AnimatorListenerAdapter() {
45
                     @Override
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
                     @Override
51
                     @Override
51
                     public void onAnimationEnd(Animator animation) {
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 View File

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 View File

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 View File

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 View File

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 View File

59
     }
59
     }
60
 
60
 
61
     public void destroy() {
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 View File

44
     tab.screen = tab.screenId;
44
     tab.screen = tab.screenId;
45
     addNavigatorButtons(tab);
45
     addNavigatorButtons(tab);
46
     adaptNavigationParams(tab);
46
     adaptNavigationParams(tab);
47
+    addNavigationStyleParams(tab);
48
+    tab = adaptNavigationStyleToScreenStyle(tab);
47
   });
49
   });
48
 }
50
 }
49
 
51