Browse Source

Collapse when scrolling header

Guy Carmeli 8 years ago
parent
commit
2b7f9b4bb0

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

41
                                          LeftButtonOnClickListener leftButtonOnClickListener,
41
                                          LeftButtonOnClickListener leftButtonOnClickListener,
42
                                          String navigatorEventId, boolean overrideBackPressInJs) {
42
                                          String navigatorEventId, boolean overrideBackPressInJs) {
43
         titleBar = createTitleBar();
43
         titleBar = createTitleBar();
44
-        titleBarAndContextualMenuContainer.addView(titleBar, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
44
+        addTitleBar();
45
         addButtons(rightButtons, leftButton, leftButtonOnClickListener, navigatorEventId, overrideBackPressInJs);
45
         addButtons(rightButtons, leftButton, leftButtonOnClickListener, navigatorEventId, overrideBackPressInJs);
46
     }
46
     }
47
 
47
 
49
         return new TitleBar(getContext());
49
         return new TitleBar(getContext());
50
     }
50
     }
51
 
51
 
52
+    protected void addTitleBar() {
53
+        titleBarAndContextualMenuContainer.addView(titleBar, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
54
+    }
55
+
52
     private void addButtons(List<TitleBarButtonParams> rightButtons, TitleBarLeftButtonParams leftButton, LeftButtonOnClickListener leftButtonOnClickListener, String navigatorEventId, boolean overrideBackPressInJs) {
56
     private void addButtons(List<TitleBarButtonParams> rightButtons, TitleBarLeftButtonParams leftButton, LeftButtonOnClickListener leftButtonOnClickListener, String navigatorEventId, boolean overrideBackPressInJs) {
53
         titleBar.setRightButtons(rightButtons, navigatorEventId);
57
         titleBar.setRightButtons(rightButtons, navigatorEventId);
54
         titleBar.setLeftButton(leftButton, leftButtonOnClickListener, navigatorEventId, overrideBackPressInJs);
58
         titleBar.setLeftButton(leftButton, leftButtonOnClickListener, navigatorEventId, overrideBackPressInJs);

+ 25
- 7
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingTitleBar.java View File

4
 import android.view.MotionEvent;
4
 import android.view.MotionEvent;
5
 import android.view.View;
5
 import android.view.View;
6
 
6
 
7
+import com.reactnativenavigation.params.CollapsingTopBarParams;
7
 import com.reactnativenavigation.params.StyleParams;
8
 import com.reactnativenavigation.params.StyleParams;
8
 import com.reactnativenavigation.views.TitleBar;
9
 import com.reactnativenavigation.views.TitleBar;
9
 
10
 
11
     private CollapsingTextView title;
12
     private CollapsingTextView title;
12
     private int collapsedHeight;
13
     private int collapsedHeight;
13
     private final ScrollListener scrollListener;
14
     private final ScrollListener scrollListener;
15
+    private final CollapsingTopBarParams params;
14
 
16
 
15
-    public CollapsingTitleBar(Context context, int collapsedHeight, ScrollListener scrollListener) {
17
+    public CollapsingTitleBar(Context context, int collapsedHeight, ScrollListener scrollListener, CollapsingTopBarParams params) {
16
         super(context);
18
         super(context);
17
         this.collapsedHeight = collapsedHeight;
19
         this.collapsedHeight = collapsedHeight;
18
         this.scrollListener = scrollListener;
20
         this.scrollListener = scrollListener;
21
+        this.params = params;
19
         addCollapsingTitle();
22
         addCollapsingTitle();
20
         setOnTouchListener(this);
23
         setOnTouchListener(this);
21
     }
24
     }
22
 
25
 
23
     private void addCollapsingTitle() {
26
     private void addCollapsingTitle() {
24
-        title = new CollapsingTextView(getContext(), collapsedHeight);
25
-        addView(title);
27
+        if (params.hasBackgroundImage()) {
28
+            title = new CollapsingTextView(getContext(), collapsedHeight);
29
+            addView(title);
30
+        }
26
     }
31
     }
27
 
32
 
28
     @Override
33
     @Override
29
     public void setTitle(CharSequence title) {
34
     public void setTitle(CharSequence title) {
30
-        this.title.setText((String) title);
35
+        if (params.hasBackgroundImage()) {
36
+            this.title.setText((String) title);
37
+        } else {
38
+            super.setTitle(title);
39
+        }
31
     }
40
     }
32
 
41
 
33
     @Override
42
     @Override
34
     protected void setTitleTextColor(StyleParams params) {
43
     protected void setTitleTextColor(StyleParams params) {
35
-        title.setTextColor(params);
44
+        if (this.params.hasBackgroundImage()) {
45
+            title.setTextColor(params);
46
+        } else {
47
+            super.setTitleTextColor(params);
48
+        }
36
     }
49
     }
37
 
50
 
38
     @Override
51
     @Override
39
     protected void setSubtitleTextColor(StyleParams params) {
52
     protected void setSubtitleTextColor(StyleParams params) {
53
+        if (this.params.hasReactView()) {
54
+            super.setSubtitleTextColor(params);
55
+        }
40
     }
56
     }
41
 
57
 
42
     public void collapse(float collapse) {
58
     public void collapse(float collapse) {
43
-        title.setTranslationY(0);
59
+        if (params.hasBackgroundImage()) {
60
+            title.setTranslationY(0);
61
+            title.collapseBy(collapse);
62
+        }
44
         setTranslationY(-collapse);
63
         setTranslationY(-collapse);
45
-        title.collapseBy(collapse);
46
     }
64
     }
47
 
65
 
48
     @Override
66
     @Override

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

4
 import android.content.res.TypedArray;
4
 import android.content.res.TypedArray;
5
 import android.os.Bundle;
5
 import android.os.Bundle;
6
 import android.view.View;
6
 import android.view.View;
7
+import android.view.ViewGroup;
7
 import android.widget.ScrollView;
8
 import android.widget.ScrollView;
8
 
9
 
9
 import com.reactnativenavigation.params.CollapsingTopBarParams;
10
 import com.reactnativenavigation.params.CollapsingTopBarParams;
12
 import com.reactnativenavigation.views.TitleBar;
13
 import com.reactnativenavigation.views.TitleBar;
13
 import com.reactnativenavigation.views.TopBar;
14
 import com.reactnativenavigation.views.TopBar;
14
 
15
 
16
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
17
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
18
+
15
 public class CollapsingTopBar extends TopBar implements CollapsingView {
19
 public class CollapsingTopBar extends TopBar implements CollapsingView {
16
     private CollapsingTopBarBackground collapsingTopBarBackground;
20
     private CollapsingTopBarBackground collapsingTopBarBackground;
17
     private CollapsingTopBarReactView header;
21
     private CollapsingTopBarReactView header;
27
         this.params = params;
31
         this.params = params;
28
         topBarHeight = calculateTopBarHeight();
32
         topBarHeight = calculateTopBarHeight();
29
         createBackgroundImage(params);
33
         createBackgroundImage(params);
30
-        createReactView(params);
31
         calculateFinalCollapsedTranslation(params);
34
         calculateFinalCollapsedTranslation(params);
32
         viewCollapser = new ViewCollapser(this);
35
         viewCollapser = new ViewCollapser(this);
33
     }
36
     }
36
         ViewUtils.runOnPreDraw(this, new Runnable() {
39
         ViewUtils.runOnPreDraw(this, new Runnable() {
37
             @Override
40
             @Override
38
             public void run() {
41
             public void run() {
39
-                if (params.hasBackgroundImage()) {
42
+                if (params.hasBackgroundImage() || params.hasReactView()) {
40
                     finalCollapsedTranslation = getCollapsedHeight() - getHeight();
43
                     finalCollapsedTranslation = getCollapsedHeight() - getHeight();
41
                 } else {
44
                 } else {
42
                     finalCollapsedTranslation = -titleBar.getHeight();
45
                     finalCollapsedTranslation = -titleBar.getHeight();
70
         if (params.hasReactView()) {
73
         if (params.hasReactView()) {
71
             header = new CollapsingTopBarReactView(getContext(),
74
             header = new CollapsingTopBarReactView(getContext(),
72
                     params.reactViewId,
75
                     params.reactViewId,
73
-                    new NavigationParams(Bundle.EMPTY));
76
+                    new NavigationParams(Bundle.EMPTY),
77
+                    scrollListener);
74
             LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, (int) ViewUtils.convertDpToPixel(params.reactViewHeight));
78
             LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, (int) ViewUtils.convertDpToPixel(params.reactViewHeight));
75
             titleBarAndContextualMenuContainer.addView(header, lp);
79
             titleBarAndContextualMenuContainer.addView(header, lp);
76
         }
80
         }
78
 
82
 
79
     @Override
83
     @Override
80
     protected TitleBar createTitleBar() {
84
     protected TitleBar createTitleBar() {
81
-        if (params.hasBackgroundImage()) {
85
+        if (params.hasBackgroundImage() || params.hasReactView()) {
86
+            createReactView(params);
82
             return new CollapsingTitleBar(getContext(),
87
             return new CollapsingTitleBar(getContext(),
83
                     getCollapsedHeight(),
88
                     getCollapsedHeight(),
84
-                    scrollListener);
89
+                    scrollListener,
90
+                    params);
85
         } else {
91
         } else {
86
             return super.createTitleBar();
92
             return super.createTitleBar();
87
         }
93
         }
88
     }
94
     }
89
 
95
 
96
+    @Override
97
+    protected void addTitleBar() {
98
+        if (params.hasReactView()) {
99
+            titleBarAndContextualMenuContainer.addView(titleBar, new ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
100
+        } else {
101
+            super.addTitleBar();
102
+        }
103
+    }
104
+
90
     @Override
105
     @Override
91
     public void collapse(CollapseAmount amount) {
106
     public void collapse(CollapseAmount amount) {
92
         viewCollapser.collapse(amount);
107
         viewCollapser.collapse(amount);

+ 86
- 1
android/app/src/main/java/com/reactnativenavigation/views/collapsingToolbar/CollapsingTopBarReactView.java View File

1
 package com.reactnativenavigation.views.collapsingToolbar;
1
 package com.reactnativenavigation.views.collapsingToolbar;
2
 
2
 
3
 import android.content.Context;
3
 import android.content.Context;
4
+import android.support.v4.view.MotionEventCompat;
5
+import android.view.MotionEvent;
6
+import android.view.ViewConfiguration;
4
 
7
 
8
+import com.facebook.react.bridge.ReactContext;
9
+import com.facebook.react.uimanager.JSTouchDispatcher;
10
+import com.facebook.react.uimanager.UIManagerModule;
11
+import com.facebook.react.uimanager.events.EventDispatcher;
12
+import com.reactnativenavigation.NavigationApplication;
5
 import com.reactnativenavigation.params.NavigationParams;
13
 import com.reactnativenavigation.params.NavigationParams;
6
 import com.reactnativenavigation.views.ContentView;
14
 import com.reactnativenavigation.views.ContentView;
7
 
15
 
8
 public class CollapsingTopBarReactView extends ContentView {
16
 public class CollapsingTopBarReactView extends ContentView {
9
-    public CollapsingTopBarReactView(Context context, String screenId, NavigationParams navigationParams) {
17
+    private ScrollListener listener;
18
+    private boolean mIsScrolling;
19
+    private int mTouchSlop;
20
+    private int touchDown = -1;
21
+    private final JSTouchDispatcher mJSTouchDispatcher = new JSTouchDispatcher(this);
22
+
23
+    public CollapsingTopBarReactView(Context context, String screenId, NavigationParams navigationParams, ScrollListener scrollListener) {
10
         super(context, screenId, navigationParams);
24
         super(context, screenId, navigationParams);
25
+        listener = scrollListener;
26
+        ViewConfiguration vc = ViewConfiguration.get(context);
27
+        mTouchSlop = vc.getScaledTouchSlop();
28
+    }
29
+
30
+    @Override
31
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
32
+        final int action = MotionEventCompat.getActionMasked(ev);
33
+        switch (action) {
34
+            case MotionEvent.ACTION_CANCEL:
35
+                releaseScroll(ev);
36
+                break;
37
+            case MotionEvent.ACTION_UP:
38
+                releaseScroll(ev);
39
+                break;
40
+            case MotionEvent.ACTION_DOWN:
41
+                onTouchDown(ev);
42
+                break;
43
+            case MotionEvent.ACTION_MOVE: {
44
+                if (mIsScrolling) {
45
+                    return true;
46
+                }
47
+                if (calculateDistanceY(ev) > mTouchSlop) {
48
+                    mIsScrolling = true;
49
+                    return true;
50
+                }
51
+                break;
52
+            }
53
+            default:
54
+                break;
55
+        }
56
+        return false;
57
+    }
58
+
59
+    private void onTouchDown(MotionEvent ev) {
60
+        if (touchDown == -1) {
61
+            touchDown = (int) ev.getRawY();
62
+        }
63
+        dispatchTouchEventToJs(ev);
64
+    }
65
+
66
+    private int calculateDistanceY(MotionEvent ev) {
67
+        return (int) Math.abs(ev.getRawY() - touchDown);
68
+    }
69
+
70
+    @Override
71
+    public boolean onTouchEvent(MotionEvent ev) {
72
+        listener.onTouch(ev);
73
+        int action = ev.getActionMasked();
74
+        switch (action) {
75
+            case MotionEvent.ACTION_UP:
76
+                releaseScroll(ev);
77
+                break;
78
+            case MotionEvent.ACTION_MOVE:
79
+                break;
80
+            default:
81
+                break;
82
+        }
83
+        return super.onTouchEvent(ev);
84
+    }
85
+
86
+    private void releaseScroll(MotionEvent ev) {
87
+        mIsScrolling = false;
88
+        touchDown = -1;
89
+        dispatchTouchEventToJs(ev);
90
+    }
91
+
92
+    private void dispatchTouchEventToJs(MotionEvent event) {
93
+        ReactContext reactContext = NavigationApplication.instance.getReactGateway().getReactInstanceManager().getCurrentReactContext();
94
+        EventDispatcher eventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
95
+        mJSTouchDispatcher.handleTouchEvent(event, eventDispatcher);
11
     }
96
     }
12
 }
97
 }