Browse Source

Find proper ScrollView and detect scroll

Guy Carmeli 8 years ago
parent
commit
2683e395fd

+ 98
- 4
android/app/src/main/java/com/reactnativenavigation/activities/BottomTabActivity.java View File

@@ -5,7 +5,11 @@ import android.graphics.drawable.Drawable;
5 5
 import android.os.AsyncTask;
6 6
 import android.os.Bundle;
7 7
 import android.support.design.widget.CoordinatorLayout;
8
+import android.util.Log;
8 9
 import android.view.View;
10
+import android.view.ViewGroup;
11
+import android.view.ViewTreeObserver;
12
+import android.widget.ScrollView;
9 13
 
10 14
 import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
11 15
 import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
@@ -15,6 +19,8 @@ import com.reactnativenavigation.core.RctManager;
15 19
 import com.reactnativenavigation.core.objects.Drawer;
16 20
 import com.reactnativenavigation.core.objects.Screen;
17 21
 import com.reactnativenavigation.utils.StyleHelper;
22
+import com.reactnativenavigation.views.BottomNavigation;
23
+import com.reactnativenavigation.views.RctView;
18 24
 import com.reactnativenavigation.views.RnnToolBar;
19 25
 import com.reactnativenavigation.views.ScreenStack;
20 26
 
@@ -23,6 +29,7 @@ import java.util.HashMap;
23 29
 import java.util.Map;
24 30
 
25 31
 public class BottomTabActivity extends BaseReactActivity implements AHBottomNavigation.OnTabSelectedListener {
32
+    private static final String TAG = "BottomTabActivity";
26 33
     public static final String DRAWER_PARAMS = "drawerParams";
27 34
     public static final String EXTRA_SCREENS = "extraScreens";
28 35
 
@@ -36,11 +43,38 @@ public class BottomTabActivity extends BaseReactActivity implements AHBottomNavi
36 43
     private static int DEFAULT_TAB_SELECTED_COLOR = 0xFF0000FF;
37 44
     private static boolean DEFAULT_TAB_INACTIVE_TITLES = true;
38 45
 
39
-    private AHBottomNavigation mBottomNavigation;
46
+    private BottomNavigation mBottomNavigation;
40 47
     private CoordinatorLayout mContentFrame;
41 48
     private ArrayList<ScreenStack> mScreenStacks;
42 49
     private int mCurrentStackPosition = -1;
43 50
 
51
+    private ScrollView mScrollView;
52
+    private ViewTreeObserver.OnScrollChangedListener mScrollChangedListener;
53
+    private final View.OnAttachStateChangeListener mScrollViewStateChangeListener =
54
+            new View.OnAttachStateChangeListener() {
55
+                @Override
56
+                public void onViewAttachedToWindow(View v) {
57
+
58
+                }
59
+
60
+                @Override
61
+                public void onViewDetachedFromWindow(View detachedScrollView) {
62
+                    detachedScrollView.getViewTreeObserver().removeOnScrollChangedListener(mScrollChangedListener);
63
+                    detachedScrollView.removeOnAttachStateChangeListener(this);
64
+
65
+                    mContentFrame.post(new Runnable() {
66
+                        @Override
67
+                        public void run() {
68
+                            mScrollView = getScrollView(mContentFrame);
69
+                            if (mScrollView != null) {
70
+                                mScrollView.addOnAttachStateChangeListener(mScrollViewStateChangeListener);
71
+                                addScrollListener(mScrollView);
72
+                            }
73
+                        }
74
+                    });
75
+                }
76
+            };
77
+
44 78
     @Override
45 79
     protected void handleOnCreate() {
46 80
         super.handleOnCreate();
@@ -48,7 +82,7 @@ public class BottomTabActivity extends BaseReactActivity implements AHBottomNavi
48 82
 
49 83
         setContentView(R.layout.bottom_tab_activity);
50 84
         mToolbar = (RnnToolBar) findViewById(R.id.toolbar);
51
-        mBottomNavigation = (AHBottomNavigation) findViewById(R.id.bottom_tab_bar);
85
+        mBottomNavigation = (BottomNavigation) findViewById(R.id.bottom_tab_bar);
52 86
         mContentFrame = (CoordinatorLayout) findViewById(R.id.contentFrame);
53 87
 
54 88
         final ArrayList<Screen> screens = (ArrayList<Screen>) getIntent().getSerializableExtra(EXTRA_SCREENS);
@@ -65,6 +99,18 @@ public class BottomTabActivity extends BaseReactActivity implements AHBottomNavi
65 99
                 setupToolbar(screens);
66 100
             }
67 101
         });
102
+
103
+        mContentFrame.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
104
+            @Override
105
+            public void onChildViewAdded(View parent, View child) {
106
+                Log.i(TAG, "onChildViewAdded: " + child.getClass());
107
+            }
108
+
109
+            @Override
110
+            public void onChildViewRemoved(View parent, View child) {
111
+                Log.d(TAG, "onChildViewRemoved: " + child.getClass());
112
+            }
113
+        });
68 114
     }
69 115
 
70 116
     private void setupPages(ArrayList<Screen> screens) {
@@ -80,8 +126,44 @@ public class BottomTabActivity extends BaseReactActivity implements AHBottomNavi
80 126
 
81 127
     private void setupBottomTabs(Screen initialScreen) {
82 128
         if (initialScreen.bottomTabsHiddenOnScroll) {
129
+            mScrollView = getScrollView(mContentFrame);
130
+            if (mScrollView != null) {
131
+                attachStateChangeListener(mScrollView);
132
+                addScrollListener(mScrollView);
133
+            }
134
+        }
135
+    }
136
+
137
+    private void attachStateChangeListener(ScrollView scrollView) {
138
+        scrollView.addOnAttachStateChangeListener(mScrollViewStateChangeListener);
139
+    }
140
+
141
+    private void addScrollListener(final ScrollView scrollView) {
142
+        mScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() {
143
+            @Override
144
+            public void onScrollChanged() {
145
+                if (scrollView.getViewTreeObserver().isAlive()) {
146
+                    Log.i(TAG, "onScrollChanged: " + scrollView.getScrollY());
147
+                }
148
+            }
149
+        };
150
+        scrollView.getViewTreeObserver().addOnScrollChangedListener(mScrollChangedListener);
151
+    }
152
+
153
+    private ScrollView getScrollView(ViewGroup parent) {
154
+        for (int i = 0; i < parent.getChildCount(); i++) {
155
+            View child = parent.getChildAt(i);
156
+
157
+            if (child instanceof ScrollView) {
158
+                return (ScrollView) child;
159
+            }
83 160
 
161
+            if (child instanceof ViewGroup) {
162
+                return getScrollView((ViewGroup) child);
163
+            }
84 164
         }
165
+
166
+        return null;
85 167
     }
86 168
 
87 169
     @Override
@@ -300,9 +382,21 @@ public class BottomTabActivity extends BaseReactActivity implements AHBottomNavi
300 382
 
301 383
     private void setTabsWithIcons(ArrayList<Screen> screens, Map<Screen, Drawable> icons) {
302 384
         mScreenStacks = new ArrayList<>();
303
-        for (Screen screen : screens) {
385
+        for (int i = 0; i < screens.size(); i++) {
386
+            final Screen screen = screens.get(i);
304 387
             ScreenStack stack = new ScreenStack(this);
305
-            stack.push(screen);
388
+
389
+            if (i == 0) {
390
+                stack.push(screen, new RctView.OnDisplayedListener() {
391
+                    @Override
392
+                    public void onDisplayed() {
393
+                        setupBottomTabs(screen);
394
+                    }
395
+                });
396
+            } else {
397
+                stack.push(screen);
398
+            }
399
+
306 400
             mScreenStacks.add(stack);
307 401
             AHBottomNavigationItem item = new AHBottomNavigationItem(screen.label, icons.get(screen), Color.GRAY);
308 402
             mBottomNavigation.addItem(item);

+ 3
- 2
android/app/src/main/java/com/reactnativenavigation/core/objects/Screen.java View File

@@ -5,6 +5,7 @@ import android.graphics.drawable.Drawable;
5 5
 import android.support.annotation.ColorInt;
6 6
 import android.support.annotation.NonNull;
7 7
 import android.support.annotation.Nullable;
8
+import android.util.Log;
8 9
 
9 10
 import com.facebook.react.bridge.ReadableArray;
10 11
 import com.facebook.react.bridge.ReadableMap;
@@ -56,7 +57,7 @@ public class Screen extends JsonObject implements Serializable {
56 57
     public final String icon;
57 58
     public ArrayList<Button> buttons;
58 59
     public final boolean backButtonHidden;
59
-    public final boolean bottomTabsHiddenOnScroll;
60
+    public boolean bottomTabsHiddenOnScroll;
60 61
     public HashMap<String, Object> passedProps = new HashMap<>();
61 62
 
62 63
     // Navigation styling
@@ -89,7 +90,6 @@ public class Screen extends JsonObject implements Serializable {
89 90
         }
90 91
         buttons = getButtons(screen);
91 92
         backButtonHidden = getBoolean(screen, KEY_BACK_BUTTON_HIDDEN);
92
-        bottomTabsHiddenOnScroll = getBoolean(screen, KEY_BOTTOM_TABS_HIDDEN_ON_SCROLL);
93 93
         setToolbarStyle(screen);
94 94
     }
95 95
 
@@ -138,6 +138,7 @@ public class Screen extends JsonObject implements Serializable {
138 138
             tabSelectedTextColor = getColor(style, KEY_TAB_SELECTED_TEXT_COLOR);
139 139
             tabIndicatorColor = getColor(style, KEY_TAB_INDICATOR_COLOR);
140 140
             bottomTabsHidden = getBoolean(style, KEY_BOTTOM_TABS_HIDDEN);
141
+            bottomTabsHiddenOnScroll = getBoolean(style, KEY_BOTTOM_TABS_HIDDEN_ON_SCROLL);
141 142
         }
142 143
     }
143 144
 }

+ 21
- 3
android/app/src/main/java/com/reactnativenavigation/utils/ReflectionUtils.java View File

@@ -9,9 +9,11 @@ import java.lang.reflect.Method;
9 9
 public class ReflectionUtils {
10 10
 
11 11
     public static boolean setField(Object obj, String name, Object value) {
12
-        Field field;
13 12
         try {
14
-            field = obj.getClass().getDeclaredField(name);
13
+            Field field = getField(obj.getClass(), name);
14
+            if (field == null) {
15
+                return false;
16
+            }
15 17
             field.setAccessible(true);
16 18
             field.set(obj, value);
17 19
             return true;
@@ -21,9 +23,25 @@ public class ReflectionUtils {
21 23
         return false;
22 24
     }
23 25
 
26
+    private static Field getField(Class clazz, String name) {
27
+        try {
28
+            return clazz.getDeclaredField(name);
29
+        } catch (NoSuchFieldException nsfe) {
30
+            return getField(clazz.getSuperclass(), name);
31
+        } catch (Exception e) {
32
+            return null;
33
+        }
34
+    }
35
+
36
+    /**
37
+     * Returns the value of the field
38
+     */
24 39
     public static Object getDeclaredField(Object obj, String fieldName) {
25 40
         try {
26
-            Field f = obj.getClass().getDeclaredField(fieldName);
41
+            Field f = getField(obj.getClass(), fieldName);
42
+            if (f == null) {
43
+                return null;
44
+            }
27 45
             f.setAccessible(true);
28 46
             return f.get(obj);
29 47
         } catch (Exception e) {

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

@@ -1,7 +1,6 @@
1 1
 package com.reactnativenavigation.views;
2 2
 
3 3
 import android.os.Bundle;
4
-import android.view.ViewTreeObserver;
5 4
 import android.widget.FrameLayout;
6 5
 
7 6
 import com.facebook.react.ReactInstanceManager;
@@ -34,7 +33,7 @@ public class RctView extends FrameLayout {
34 33
         super(ctx);
35 34
         setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
36 35
 
37
-        mReactRootView = new ReactRootView(ctx);
36
+        mReactRootView = new RnnReactRootView(ctx, onDisplayedListener);
38 37
         mReactRootView.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
39 38
 
40 39
         String componentName = screen.screenId;
@@ -48,16 +47,6 @@ public class RctView extends FrameLayout {
48 47
 
49 48
         mReactRootView.startReactApplication(rctInstanceManager, componentName, passProps);
50 49
 
51
-        if (onDisplayedListener != null) {
52
-            mReactRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
53
-                @Override
54
-                public void onGlobalLayout() {
55
-                    onDisplayedListener.onDisplayed();
56
-                    mReactRootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
57
-                }
58
-            });
59
-        }
60
-
61 50
         addView(mReactRootView);
62 51
     }
63 52
 

+ 34
- 0
android/app/src/main/java/com/reactnativenavigation/views/RnnReactRootView.java View File

@@ -0,0 +1,34 @@
1
+package com.reactnativenavigation.views;
2
+
3
+import android.content.Context;
4
+import android.view.ViewTreeObserver;
5
+
6
+import com.facebook.react.ReactRootView;
7
+
8
+/**
9
+ * Created by guyc on 11/07/16.
10
+ */
11
+public class RnnReactRootView extends ReactRootView implements ViewTreeObserver.OnGlobalLayoutListener {
12
+    private final RctView.OnDisplayedListener mOnDisplayedListener;
13
+
14
+    public RnnReactRootView(Context context, RctView.OnDisplayedListener onDisplayedListener) {
15
+        super(context);
16
+        mOnDisplayedListener = onDisplayedListener;
17
+
18
+        if (onDisplayedListener != null) {
19
+            detectOnDisplay();
20
+        }
21
+    }
22
+
23
+    private void detectOnDisplay() {
24
+        getViewTreeObserver().addOnGlobalLayoutListener(this);
25
+    }
26
+
27
+    @Override
28
+    public void onGlobalLayout() {
29
+        if (getChildCount() >= 1) {
30
+            getViewTreeObserver().removeOnGlobalLayoutListener(this);
31
+            mOnDisplayedListener.onDisplayed();
32
+        }
33
+    }
34
+}