Browse Source

Less intrusive collapse (#590)

* Less intrusive collapsing implementation

In order for a screen to implement collapsingTopBar, it had to define
a specific set of style properties such as drawUnderTabBar or
drawUnderNavBar. This commit aims to make implementing collapsingTopBar
less intrusive by inferring these properties from hideTitleBarOnScroll.

This commit introduces a few fixes and changes related to
the collapsingTopBar mechanism.

1. Screens are now drawn under bottomTabs if titleBarHideOnScroll
   is true.

2. TitleBarHideOnScroll can be passed in AppStyle.

3. ScrollView is detected properly after it gets detached due to large
   diff in render.

4. Take BottomTabs height into account when measuring collapsing
   screens.
Guy Carmeli 7 years ago
parent
commit
cc199a50a9

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

12
 
12
 
13
 class CollapsingTopBarParamsParser extends Parser {
13
 class CollapsingTopBarParamsParser extends Parser {
14
     private Bundle params;
14
     private Bundle params;
15
+    private boolean titleBarHideOnScroll;
16
+    private boolean drawBelowTopBar;
15
 
17
 
16
-    CollapsingTopBarParamsParser(Bundle params) {
18
+    CollapsingTopBarParamsParser(Bundle params, boolean titleBarHideOnScroll, boolean drawBelowTopBar) {
17
         this.params = params;
19
         this.params = params;
20
+        this.titleBarHideOnScroll = titleBarHideOnScroll;
21
+        this.drawBelowTopBar = drawBelowTopBar;
18
     }
22
     }
19
 
23
 
20
     public CollapsingTopBarParams parse() {
24
     public CollapsingTopBarParams parse() {
21
-        if (!hasBackgroundImage() && !shouldHideTitleBarOnScroll()) {
25
+        if (!hasBackgroundImage() && !titleBarHideOnScroll) {
22
             return null;
26
             return null;
23
         }
27
         }
24
 
28
 
35
         if (hasBackgroundImage()) {
39
         if (hasBackgroundImage()) {
36
             return new CollapseTopBarBehaviour();
40
             return new CollapseTopBarBehaviour();
37
         }
41
         }
38
-        if (shouldHideTitleBarOnScroll() && params.getBoolean("drawBelowTopBar", false)) {
42
+        if (titleBarHideOnScroll && drawBelowTopBar) {
39
             return new CollapseTitleBarBehaviour();
43
             return new CollapseTitleBarBehaviour();
40
         }
44
         }
41
         return new TitleBarHideOnScrollBehaviour();
45
         return new TitleBarHideOnScrollBehaviour();
44
     private boolean hasBackgroundImage() {
48
     private boolean hasBackgroundImage() {
45
         return params.containsKey("collapsingToolBarImage");
49
         return params.containsKey("collapsingToolBarImage");
46
     }
50
     }
47
-
48
-    private boolean shouldHideTitleBarOnScroll() {
49
-        return params.getBoolean("titleBarHideOnScroll", false);
50
-    }
51
 }
51
 }

+ 23
- 14
android/app/src/main/java/com/reactnativenavigation/params/parsers/StyleParamsParser.java View File

14
     }
14
     }
15
 
15
 
16
     public StyleParams parse() {
16
     public StyleParams parse() {
17
-        StyleParams result = new StyleParams();
18
         if (params == null) {
17
         if (params == null) {
19
-            result.titleBarDisabledButtonColor = getTitleBarDisabledButtonColor();
20
-            result.topBarElevationShadowEnabled = true;
21
-            return result;
18
+            return createDefaultStyleParams();
22
         }
19
         }
23
 
20
 
21
+        StyleParams result = new StyleParams();
24
         result.statusBarColor = getColor("statusBarColor", getDefaultStatusBarColor());
22
         result.statusBarColor = getColor("statusBarColor", getDefaultStatusBarColor());
25
         result.contextualMenuStatusBarColor = getColor("contextualMenuStatusBarColor", getDefaultContextualMenuStatusBarColor());
23
         result.contextualMenuStatusBarColor = getColor("contextualMenuStatusBarColor", getDefaultContextualMenuStatusBarColor());
26
         result.contextualMenuButtonsColor = getColor("contextualMenuButtonsColor", getDefaultContextualMenuButtonsColor());
24
         result.contextualMenuButtonsColor = getColor("contextualMenuButtonsColor", getDefaultContextualMenuButtonsColor());
27
         result.contextualMenuBackgroundColor = getColor("contextualMenuBackgroundColor", getDefaultContextualMenuBackgroundColor());
25
         result.contextualMenuBackgroundColor = getColor("contextualMenuBackgroundColor", getDefaultContextualMenuBackgroundColor());
28
 
26
 
29
         result.topBarColor = getColor("topBarColor", getDefaultTopBarColor());
27
         result.topBarColor = getColor("topBarColor", getDefaultTopBarColor());
30
-        result.collapsingTopBarParams = new CollapsingTopBarParamsParser(params).parse();
31
-        result.titleBarHidden = getBoolean("titleBarHidden", getDefaultTopBarHidden());
28
+        result.titleBarHideOnScroll = getBoolean("titleBarHideOnScroll", getDefaultTitleBarHideOnScroll());
32
         result.topBarTransparent = getBoolean("topBarTransparent", getDefaultTopBarHidden());
29
         result.topBarTransparent = getBoolean("topBarTransparent", getDefaultTopBarHidden());
30
+        result.drawScreenBelowTopBar = params.getBoolean("drawBelowTopBar", getDefaultScreenBelowTopBar());
31
+        if (result.topBarTransparent) {
32
+            result.drawScreenBelowTopBar = false;
33
+        }
34
+        result.collapsingTopBarParams = new CollapsingTopBarParamsParser(params, result.titleBarHideOnScroll, result.drawScreenBelowTopBar).parse();
35
+        result.titleBarHidden = getBoolean("titleBarHidden", getDefaultTopBarHidden());
33
         result.topBarElevationShadowEnabled = getBoolean("topBarElevationShadowEnabled", getDefaultTopBarElevationShadowEnabled());
36
         result.topBarElevationShadowEnabled = getBoolean("topBarElevationShadowEnabled", getDefaultTopBarElevationShadowEnabled());
34
         result.titleBarTitleColor = getColor("titleBarTitleColor", getDefaultTitleBarColor());
37
         result.titleBarTitleColor = getColor("titleBarTitleColor", getDefaultTitleBarColor());
35
         result.topBarTranslucent = getBoolean("topBarTranslucent", getDefaultTopBarTranslucent());
38
         result.topBarTranslucent = getBoolean("topBarTranslucent", getDefaultTopBarTranslucent());
36
-        result.titleBarHideOnScroll = getBoolean("titleBarHideOnScroll", getDefaultTitleBarHideOnScroll());
37
 
39
 
38
         result.titleBarSubtitleColor = getColor("titleBarSubtitleColor", getDefaultSubtitleBarColor());
40
         result.titleBarSubtitleColor = getColor("titleBarSubtitleColor", getDefaultSubtitleBarColor());
39
         result.titleBarButtonColor = getColor("titleBarButtonColor", getTitleBarButtonColor());
41
         result.titleBarButtonColor = getColor("titleBarButtonColor", getTitleBarButtonColor());
46
         result.selectedTopTabIndicatorHeight = getInt("selectedTopTabIndicatorHeight", getDefaultSelectedTopTabIndicatorHeight());
48
         result.selectedTopTabIndicatorHeight = getInt("selectedTopTabIndicatorHeight", getDefaultSelectedTopTabIndicatorHeight());
47
         result.selectedTopTabIndicatorColor = getColor("selectedTopTabIndicatorColor", getDefaultSelectedTopTabIndicatorColor());
49
         result.selectedTopTabIndicatorColor = getColor("selectedTopTabIndicatorColor", getDefaultSelectedTopTabIndicatorColor());
48
 
50
 
49
-        result.drawScreenBelowTopBar = params.getBoolean("drawBelowTopBar", getDefaultScreenBelowTopBar());
50
-        if (result.topBarTransparent) {
51
-            result.drawScreenBelowTopBar = false;
52
-        }
53
-
54
         result.screenBackgroundColor = getColor("screenBackgroundColor", getDefaultScreenBackgroundColor());
51
         result.screenBackgroundColor = getColor("screenBackgroundColor", getDefaultScreenBackgroundColor());
55
 
52
 
56
         result.bottomTabsHidden = getBoolean("bottomTabsHidden", getDefaultBottomTabsHidden());
53
         result.bottomTabsHidden = getBoolean("bottomTabsHidden", getDefaultBottomTabsHidden());
57
         result.drawScreenAboveBottomTabs = !result.bottomTabsHidden &&
54
         result.drawScreenAboveBottomTabs = !result.bottomTabsHidden &&
58
                                            params.getBoolean("drawScreenAboveBottomTabs", getDefaultDrawScreenAboveBottomTabs());
55
                                            params.getBoolean("drawScreenAboveBottomTabs", getDefaultDrawScreenAboveBottomTabs());
59
-        result.bottomTabsHiddenOnScroll =
60
-                getBoolean("bottomTabsHiddenOnScroll", getDefaultBottomTabsHiddenOnScroll());
56
+        result.drawScreenAboveBottomTabs = drawScreenUnderBottomTabsIfTitleBarIsHiddenOnScroll(result);
57
+        result.bottomTabsHiddenOnScroll = getBoolean("bottomTabsHiddenOnScroll", getDefaultBottomTabsHiddenOnScroll());
61
         result.bottomTabsColor = getColor("bottomTabsColor", getDefaultBottomTabsColor());
58
         result.bottomTabsColor = getColor("bottomTabsColor", getDefaultBottomTabsColor());
62
         result.bottomTabsButtonColor = getColor("bottomTabsButtonColor", getDefaultBottomTabsButtonColor());
59
         result.bottomTabsButtonColor = getColor("bottomTabsButtonColor", getDefaultBottomTabsButtonColor());
63
         result.selectedBottomTabsButtonColor =
60
         result.selectedBottomTabsButtonColor =
71
         return result;
68
         return result;
72
     }
69
     }
73
 
70
 
71
+    private StyleParams createDefaultStyleParams() {
72
+        StyleParams result = new StyleParams();
73
+        result.titleBarDisabledButtonColor = getTitleBarDisabledButtonColor();
74
+        result.topBarElevationShadowEnabled = true;
75
+        result.titleBarHideOnScroll = false;
76
+        return result;
77
+    }
78
+
79
+    private boolean drawScreenUnderBottomTabsIfTitleBarIsHiddenOnScroll(StyleParams result) {
80
+        return !result.titleBarHideOnScroll;
81
+    }
82
+
74
     private StyleParams.Color getDefaultContextualMenuStatusBarColor() {
83
     private StyleParams.Color getDefaultContextualMenuStatusBarColor() {
75
         return new StyleParams.Color(Color.parseColor("#7c7c7c"));
84
         return new StyleParams.Color(Color.parseColor("#7c7c7c"));
76
     }
85
     }

+ 7
- 3
android/app/src/main/java/com/reactnativenavigation/screens/CollapsingSingleScreen.java View File

38
     @Override
38
     @Override
39
     protected void createContent() {
39
     protected void createContent() {
40
         contentView = new CollapsingContentView(getContext(), screenParams.screenId, screenParams.navigationParams);
40
         contentView = new CollapsingContentView(getContext(), screenParams.screenId, screenParams.navigationParams);
41
-        if (screenParams.styleParams.drawScreenBelowTopBar) {
42
-            contentView.setViewMeasurer(new CollapsingViewMeasurer((CollapsingTopBar) topBar, this));
43
-        }
41
+        setViewMeasurer();
44
         setupCollapseDetection((CollapsingTopBar) topBar);
42
         setupCollapseDetection((CollapsingTopBar) topBar);
45
         addView(contentView, createLayoutParams());
43
         addView(contentView, createLayoutParams());
46
     }
44
     }
47
 
45
 
46
+    private void setViewMeasurer() {
47
+        if (screenParams.styleParams.drawScreenBelowTopBar || screenParams.styleParams.drawScreenAboveBottomTabs) {
48
+            contentView.setViewMeasurer(new CollapsingViewMeasurer((CollapsingTopBar) topBar, this, screenParams.styleParams));
49
+        }
50
+    }
51
+
48
     private void setupCollapseDetection(final CollapsingTopBar topBar) {
52
     private void setupCollapseDetection(final CollapsingTopBar topBar) {
49
         ((CollapsingContentView) contentView).setupCollapseDetection(getScrollListener(topBar), new OnScrollViewAddedListener() {
53
         ((CollapsingContentView) contentView).setupCollapseDetection(getScrollListener(topBar), new OnScrollViewAddedListener() {
50
             @Override
54
             @Override

+ 4
- 2
android/app/src/main/java/com/reactnativenavigation/screens/CollapsingViewPagerScreen.java View File

1
 package com.reactnativenavigation.screens;
1
 package com.reactnativenavigation.screens;
2
 
2
 
3
+import android.annotation.SuppressLint;
3
 import android.content.Context;
4
 import android.content.Context;
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;
19
 import com.reactnativenavigation.views.collapsingToolbar.CollapsingView;
20
 import com.reactnativenavigation.views.collapsingToolbar.CollapsingView;
20
 import com.reactnativenavigation.views.collapsingToolbar.CollapsingViewMeasurer;
21
 import com.reactnativenavigation.views.collapsingToolbar.CollapsingViewMeasurer;
21
 import com.reactnativenavigation.views.collapsingToolbar.CollapsingViewPager;
22
 import com.reactnativenavigation.views.collapsingToolbar.CollapsingViewPager;
23
+import com.reactnativenavigation.views.collapsingToolbar.CollapsingViewPagerContentViewMeasurer;
22
 import com.reactnativenavigation.views.collapsingToolbar.OnScrollListener;
24
 import com.reactnativenavigation.views.collapsingToolbar.OnScrollListener;
23
 import com.reactnativenavigation.views.collapsingToolbar.OnScrollViewAddedListener;
25
 import com.reactnativenavigation.views.collapsingToolbar.OnScrollViewAddedListener;
24
 import com.reactnativenavigation.views.collapsingToolbar.ScrollListener;
26
 import com.reactnativenavigation.views.collapsingToolbar.ScrollListener;
25
 import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseBehaviour;
27
 import com.reactnativenavigation.views.collapsingToolbar.behaviours.CollapseBehaviour;
26
 
28
 
29
+@SuppressLint("ViewConstructor")
27
 public class CollapsingViewPagerScreen extends ViewPagerScreen {
30
 public class CollapsingViewPagerScreen extends ViewPagerScreen {
28
-
29
     public CollapsingViewPagerScreen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener backButtonListener) {
31
     public CollapsingViewPagerScreen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener backButtonListener) {
30
         super(activity, screenParams, backButtonListener);
32
         super(activity, screenParams, backButtonListener);
31
     }
33
     }
49
     protected ContentView createContentView(PageParams tab) {
51
     protected ContentView createContentView(PageParams tab) {
50
         if (tab.hasCollapsingTopBar()) {
52
         if (tab.hasCollapsingTopBar()) {
51
             CollapsingContentView contentView = new CollapsingContentView(getContext(), tab.screenId, tab.navigationParams);
53
             CollapsingContentView contentView = new CollapsingContentView(getContext(), tab.screenId, tab.navigationParams);
52
-            contentView.setViewMeasurer(new CollapsingViewMeasurer((CollapsingTopBar) topBar, this));
54
+            contentView.setViewMeasurer(new CollapsingViewPagerContentViewMeasurer((CollapsingTopBar) topBar, this, screenParams.styleParams));
53
             setupCollapseDetection(contentView);
55
             setupCollapseDetection(contentView);
54
             return contentView;
56
             return contentView;
55
         } else {
57
         } else {

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

1
 package com.reactnativenavigation.views;
1
 package com.reactnativenavigation.views;
2
 
2
 
3
+import android.annotation.SuppressLint;
3
 import android.content.Context;
4
 import android.content.Context;
4
 import android.support.annotation.Nullable;
5
 import android.support.annotation.Nullable;
5
 import android.view.MotionEvent;
6
 import android.view.MotionEvent;
15
 import com.reactnativenavigation.views.collapsingToolbar.ViewCollapser;
16
 import com.reactnativenavigation.views.collapsingToolbar.ViewCollapser;
16
 import com.reactnativenavigation.views.utils.ScrollViewDetector;
17
 import com.reactnativenavigation.views.utils.ScrollViewDetector;
17
 
18
 
19
+@SuppressLint("ViewConstructor")
18
 public class CollapsingContentView extends ContentView implements CollapsingView {
20
 public class CollapsingContentView extends ContentView implements CollapsingView {
19
 
21
 
20
     private @Nullable ScrollViewDelegate scrollViewDelegate;
22
     private @Nullable ScrollViewDelegate scrollViewDelegate;
46
     public void onViewAdded(final View child) {
48
     public void onViewAdded(final View child) {
47
         super.onViewAdded(child);
49
         super.onViewAdded(child);
48
         if (scrollViewDetector != null) {
50
         if (scrollViewDetector != null) {
49
-            scrollViewDetector.detectScrollViewAdded(child);
51
+            scrollViewDetector.findScrollView(child);
50
         }
52
         }
51
     }
53
     }
52
 
54
 

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

1
 package com.reactnativenavigation.views.collapsingToolbar;
1
 package com.reactnativenavigation.views.collapsingToolbar;
2
 
2
 
3
+import com.reactnativenavigation.params.StyleParams;
3
 import com.reactnativenavigation.screens.Screen;
4
 import com.reactnativenavigation.screens.Screen;
4
 import com.reactnativenavigation.utils.ViewUtils;
5
 import com.reactnativenavigation.utils.ViewUtils;
5
 import com.reactnativenavigation.views.utils.ViewMeasurer;
6
 import com.reactnativenavigation.views.utils.ViewMeasurer;
6
 
7
 
7
 public class CollapsingViewMeasurer extends ViewMeasurer {
8
 public class CollapsingViewMeasurer extends ViewMeasurer {
8
-    private int collapsedTopBarHeight;
9
-    private float getFinalCollapseValue;
10
-    private int screenHeight;
9
+
10
+    int collapsedTopBarHeight;
11
+    private float finalCollapseValue;
12
+    int screenHeight;
13
+    int bottomTabsHeight = 0;
14
+    boolean bottomTabsHidden;
15
+
16
+    public CollapsingViewMeasurer(CollapsingTopBar topBar, Screen screen, StyleParams styleParams) {
17
+        this(topBar, screen);
18
+        bottomTabsHidden = styleParams.bottomTabsHidden;
19
+        bottomTabsHeight = (int) ViewUtils.convertDpToPixel(56);
20
+    }
11
 
21
 
12
     public CollapsingViewMeasurer(final CollapsingTopBar topBar, final Screen collapsingSingleScreen) {
22
     public CollapsingViewMeasurer(final CollapsingTopBar topBar, final Screen collapsingSingleScreen) {
13
         ViewUtils.runOnPreDraw(topBar, new Runnable() {
23
         ViewUtils.runOnPreDraw(topBar, new Runnable() {
14
             @Override
24
             @Override
15
             public void run() {
25
             public void run() {
16
                 collapsedTopBarHeight = topBar.getCollapsedHeight();
26
                 collapsedTopBarHeight = topBar.getCollapsedHeight();
17
-                getFinalCollapseValue = topBar.getFinalCollapseValue();
27
+                finalCollapseValue = topBar.getFinalCollapseValue();
18
             }
28
             }
19
         });
29
         });
20
 
30
 
27
     }
37
     }
28
 
38
 
29
     public float getFinalCollapseValue() {
39
     public float getFinalCollapseValue() {
30
-        return getFinalCollapseValue;
40
+        return finalCollapseValue;
31
     }
41
     }
32
 
42
 
33
     @Override
43
     @Override
34
     public int getMeasuredHeight(int heightMeasureSpec) {
44
     public int getMeasuredHeight(int heightMeasureSpec) {
35
-        return screenHeight - collapsedTopBarHeight;
45
+        return screenHeight - collapsedTopBarHeight + (bottomTabsHidden ? bottomTabsHeight : 0);
36
     }
46
     }
37
 }
47
 }

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

1
+package com.reactnativenavigation.views.collapsingToolbar;
2
+
3
+import com.reactnativenavigation.params.StyleParams;
4
+import com.reactnativenavigation.screens.Screen;
5
+
6
+public class CollapsingViewPagerContentViewMeasurer extends CollapsingViewMeasurer {
7
+
8
+    public CollapsingViewPagerContentViewMeasurer(CollapsingTopBar topBar, Screen screen, StyleParams styleParams) {
9
+        super(topBar, screen, styleParams);
10
+    }
11
+
12
+    @Override
13
+    public int getMeasuredHeight(int heightMeasureSpec) {
14
+        return screenHeight - collapsedTopBarHeight - (bottomTabsHidden ? 0 : bottomTabsHeight);
15
+    }
16
+}

+ 35
- 21
android/app/src/main/java/com/reactnativenavigation/views/utils/ScrollViewDetector.java View File

2
 
2
 
3
 import android.view.View;
3
 import android.view.View;
4
 import android.view.ViewGroup;
4
 import android.view.ViewGroup;
5
+import android.view.ViewTreeObserver;
5
 import android.widget.ScrollView;
6
 import android.widget.ScrollView;
6
 
7
 
7
 import com.reactnativenavigation.utils.ViewUtils;
8
 import com.reactnativenavigation.utils.ViewUtils;
10
 import com.reactnativenavigation.views.collapsingToolbar.ScrollViewDelegate;
11
 import com.reactnativenavigation.views.collapsingToolbar.ScrollViewDelegate;
11
 
12
 
12
 public class ScrollViewDetector {
13
 public class ScrollViewDetector {
14
+    private static final boolean SCROLLVIEW_FOUND = true;
15
+    private static final boolean SCROLLVIEW_NOT_FOUND = false;
13
     private OnScrollViewAddedListener scrollViewAddedListener;
16
     private OnScrollViewAddedListener scrollViewAddedListener;
14
     private ScrollViewDelegate scrollViewDelegate;
17
     private ScrollViewDelegate scrollViewDelegate;
15
-    private View.OnAttachStateChangeListener stateChangeListener;
18
+    private View.OnAttachStateChangeListener scrollViewStateChangeListener;
19
+    private ViewTreeObserver.OnGlobalLayoutListener scrollViewDetectorListener;
16
 
20
 
17
-    public ScrollViewDetector(final ContentView contentView,
18
-                              OnScrollViewAddedListener onScrollViewAddedListener,
19
-                              final ScrollViewDelegate scrollViewDelegate) {
21
+    public ScrollViewDetector(ContentView contentView, OnScrollViewAddedListener onScrollViewAddedListener,
22
+                              ScrollViewDelegate scrollViewDelegate) {
20
         this.scrollViewAddedListener = onScrollViewAddedListener;
23
         this.scrollViewAddedListener = onScrollViewAddedListener;
21
         this.scrollViewDelegate = scrollViewDelegate;
24
         this.scrollViewDelegate = scrollViewDelegate;
22
-        stateChangeListener = new View.OnAttachStateChangeListener() {
23
-            @Override
24
-            public void onViewAttachedToWindow(View v) {
25
-
26
-            }
25
+        scrollViewStateChangeListener = createScrollViewStateChangeListener(contentView, scrollViewDelegate);
26
+    }
27
 
27
 
28
+    private StateChangeListenerAdapter createScrollViewStateChangeListener(final ContentView contentView, final ScrollViewDelegate scrollViewDelegate) {
29
+        return new StateChangeListenerAdapter() {
28
             @Override
30
             @Override
29
-            public void onViewDetachedFromWindow(View v) {
31
+            public void onViewDetachedFromWindow(View scrollView) {
30
                 scrollViewDelegate.getScrollView().removeOnAttachStateChangeListener(this);
32
                 scrollViewDelegate.getScrollView().removeOnAttachStateChangeListener(this);
31
                 scrollViewDelegate.onScrollViewRemoved();
33
                 scrollViewDelegate.onScrollViewRemoved();
32
-                contentView.post(new Runnable() {
33
-                    @Override
34
-                    public void run() {
35
-                        detectScrollViewAdded(contentView);
34
+                detectScrollView(scrollViewDelegate, contentView);
35
+            }
36
+        };
37
+    }
38
+
39
+    private void detectScrollView(final ScrollViewDelegate scrollViewDelegate, final ContentView contentView) {
40
+        scrollViewDetectorListener = new ViewTreeObserver.OnGlobalLayoutListener() {
41
+            @Override
42
+            public void onGlobalLayout() {
43
+                if (!scrollViewDelegate.hasScrollView()) {
44
+                    if (findScrollView(contentView) && contentView.getViewTreeObserver().isAlive()) {
45
+                        contentView.getViewTreeObserver().removeOnGlobalLayoutListener(scrollViewDetectorListener);
36
                     }
46
                     }
37
-                });
47
+                }
38
             }
48
             }
39
         };
49
         };
50
+        contentView.getViewTreeObserver().addOnGlobalLayoutListener(scrollViewDetectorListener);
40
     }
51
     }
41
 
52
 
42
-    public void detectScrollViewAdded(View child) {
53
+    public boolean findScrollView(View child) {
43
         if (child instanceof ScrollView) {
54
         if (child instanceof ScrollView) {
44
-            onScrollViewAdded((ScrollView) child);
55
+            onScrollViewFound((ScrollView) child);
56
+            return SCROLLVIEW_FOUND;
45
         } else if (child instanceof ViewGroup) {
57
         } else if (child instanceof ViewGroup) {
46
             Object maybeScrollView = ViewUtils.findChildByClass((ViewGroup) child, ScrollView.class);
58
             Object maybeScrollView = ViewUtils.findChildByClass((ViewGroup) child, ScrollView.class);
47
             if (maybeScrollView instanceof ScrollView) {
59
             if (maybeScrollView instanceof ScrollView) {
48
-                onScrollViewAdded((ScrollView) maybeScrollView);
60
+                onScrollViewFound((ScrollView) maybeScrollView);
61
+                return SCROLLVIEW_FOUND;
49
             }
62
             }
50
         }
63
         }
64
+        return SCROLLVIEW_NOT_FOUND;
51
     }
65
     }
52
 
66
 
53
-    private void onScrollViewAdded(final ScrollView scrollView) {
67
+    private void onScrollViewFound(final ScrollView scrollView) {
54
         if (scrollViewDelegate != null && !scrollViewDelegate.hasScrollView()) {
68
         if (scrollViewDelegate != null && !scrollViewDelegate.hasScrollView()) {
55
             scrollViewDelegate.onScrollViewAdded(scrollView);
69
             scrollViewDelegate.onScrollViewAdded(scrollView);
56
             scrollViewAddedListener.onScrollViewAdded(scrollView);
70
             scrollViewAddedListener.onScrollViewAdded(scrollView);
57
-            scrollView.addOnAttachStateChangeListener(stateChangeListener);
71
+            scrollView.addOnAttachStateChangeListener(scrollViewStateChangeListener);
58
         }
72
         }
59
     }
73
     }
60
 
74
 
61
     public void destroy() {
75
     public void destroy() {
62
         if (scrollViewDelegate.getScrollView() != null) {
76
         if (scrollViewDelegate.getScrollView() != null) {
63
-            scrollViewDelegate.getScrollView().removeOnAttachStateChangeListener(stateChangeListener);
77
+            scrollViewDelegate.getScrollView().removeOnAttachStateChangeListener(scrollViewStateChangeListener);
64
         }
78
         }
65
     }
79
     }
66
 }
80
 }

+ 15
- 0
android/app/src/main/java/com/reactnativenavigation/views/utils/StateChangeListenerAdapter.java View File

1
+package com.reactnativenavigation.views.utils;
2
+
3
+import android.view.View;
4
+
5
+class StateChangeListenerAdapter implements View.OnAttachStateChangeListener {
6
+    @Override
7
+    public void onViewAttachedToWindow(View view) {
8
+
9
+    }
10
+
11
+    @Override
12
+    public void onViewDetachedFromWindow(View view) {
13
+
14
+    }
15
+}