Browse Source

Fixes overlapping fab. (#620)

This commit also introduces a tempprary fix to an issue where fab is
displayed on wrong screen when switching between bottom tabs rapidly.
Guy Carmeli 8 years ago
parent
commit
0211af8bf6

+ 1
- 1
android/app/src/main/java/com/reactnativenavigation/bridge/NavigationReactModule.java View File

98
     }
98
     }
99
 
99
 
100
     private void setScreenFab(String screenInstanceId, String navigatorEventId, ReadableMap fab) {
100
     private void setScreenFab(String screenInstanceId, String navigatorEventId, ReadableMap fab) {
101
-        FabParams fabParams = new FabParamsParser().parse(BundleConverter.toBundle(fab), navigatorEventId);
101
+        FabParams fabParams = new FabParamsParser().parse(BundleConverter.toBundle(fab), navigatorEventId, screenInstanceId);
102
         NavigationCommandsHandler.setScreenFab(screenInstanceId, navigatorEventId, fabParams);
102
         NavigationCommandsHandler.setScreenFab(screenInstanceId, navigatorEventId, fabParams);
103
     }
103
     }
104
 
104
 

+ 7
- 1
android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java View File

21
 import com.reactnativenavigation.params.SnackbarParams;
21
 import com.reactnativenavigation.params.SnackbarParams;
22
 import com.reactnativenavigation.params.TitleBarButtonParams;
22
 import com.reactnativenavigation.params.TitleBarButtonParams;
23
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
23
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
24
+import com.reactnativenavigation.screens.Screen;
24
 import com.reactnativenavigation.screens.ScreenStack;
25
 import com.reactnativenavigation.screens.ScreenStack;
25
 import com.reactnativenavigation.views.BottomTabs;
26
 import com.reactnativenavigation.views.BottomTabs;
26
 import com.reactnativenavigation.views.SideMenu;
27
 import com.reactnativenavigation.views.SideMenu;
110
     }
111
     }
111
 
112
 
112
     private void createSnackbarContainer() {
113
     private void createSnackbarContainer() {
113
-        snackbarAndFabContainer = new SnackbarAndFabContainer(getContext());
114
+        snackbarAndFabContainer = new SnackbarAndFabContainer(getContext(), this);
114
         RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
115
         RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
115
         lp.addRule(ABOVE, bottomTabs.getId());
116
         lp.addRule(ABOVE, bottomTabs.getId());
116
         getScreenStackParent().addView(snackbarAndFabContainer, lp);
117
         getScreenStackParent().addView(snackbarAndFabContainer, lp);
229
         getCurrentScreenStack().peek().dismissContextualMenu();
230
         getCurrentScreenStack().peek().dismissContextualMenu();
230
     }
231
     }
231
 
232
 
233
+    @Override
234
+    public Screen getCurrentScreen() {
235
+        return getCurrentScreenStack().peek();
236
+    }
237
+
232
     public void selectBottomTabByTabIndex(Integer index) {
238
     public void selectBottomTabByTabIndex(Integer index) {
233
         bottomTabs.setCurrentItem(index);
239
         bottomTabs.setCurrentItem(index);
234
     }
240
     }

+ 3
- 0
android/app/src/main/java/com/reactnativenavigation/layouts/Layout.java View File

8
 import com.reactnativenavigation.params.SnackbarParams;
8
 import com.reactnativenavigation.params.SnackbarParams;
9
 import com.reactnativenavigation.params.TitleBarButtonParams;
9
 import com.reactnativenavigation.params.TitleBarButtonParams;
10
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
10
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
11
+import com.reactnativenavigation.screens.Screen;
11
 import com.reactnativenavigation.views.SideMenu.Side;
12
 import com.reactnativenavigation.views.SideMenu.Side;
12
 
13
 
13
 import java.util.List;
14
 import java.util.List;
42
     void showContextualMenu(String screenInstanceId, ContextualMenuParams params, Callback onButtonClicked);
43
     void showContextualMenu(String screenInstanceId, ContextualMenuParams params, Callback onButtonClicked);
43
 
44
 
44
     void dismissContextualMenu(String screenInstanceId);
45
     void dismissContextualMenu(String screenInstanceId);
46
+
47
+    Screen getCurrentScreen();
45
 }
48
 }

+ 7
- 1
android/app/src/main/java/com/reactnativenavigation/layouts/SingleScreenLayout.java View File

16
 import com.reactnativenavigation.params.SnackbarParams;
16
 import com.reactnativenavigation.params.SnackbarParams;
17
 import com.reactnativenavigation.params.TitleBarButtonParams;
17
 import com.reactnativenavigation.params.TitleBarButtonParams;
18
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
18
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
19
+import com.reactnativenavigation.screens.Screen;
19
 import com.reactnativenavigation.screens.ScreenStack;
20
 import com.reactnativenavigation.screens.ScreenStack;
20
 import com.reactnativenavigation.views.LeftButtonOnClickListener;
21
 import com.reactnativenavigation.views.LeftButtonOnClickListener;
21
 import com.reactnativenavigation.views.SideMenu;
22
 import com.reactnativenavigation.views.SideMenu;
92
     }
93
     }
93
 
94
 
94
     private void createFabAndSnackbarContainer() {
95
     private void createFabAndSnackbarContainer() {
95
-        snackbarAndFabContainer = new SnackbarAndFabContainer(getContext());
96
+        snackbarAndFabContainer = new SnackbarAndFabContainer(getContext(), this);
96
         RelativeLayout.LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
97
         RelativeLayout.LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
97
         lp.addRule(ALIGN_PARENT_BOTTOM);
98
         lp.addRule(ALIGN_PARENT_BOTTOM);
98
         snackbarAndFabContainer.setLayoutParams(lp);
99
         snackbarAndFabContainer.setLayoutParams(lp);
231
         stack.dismissContextualMenu(screenInstanceId);
232
         stack.dismissContextualMenu(screenInstanceId);
232
     }
233
     }
233
 
234
 
235
+    @Override
236
+    public Screen getCurrentScreen() {
237
+        return stack.peek();
238
+    }
239
+
234
     @Override
240
     @Override
235
     public boolean onTitleBarBackButtonClick() {
241
     public boolean onTitleBarBackButtonClick() {
236
         if (leftButtonOnClickListener != null) {
242
         if (leftButtonOnClickListener != null) {

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

12
     public String expendedId;
12
     public String expendedId;
13
     public String navigatorEventId;
13
     public String navigatorEventId;
14
     public List<FabActionParams> actions;
14
     public List<FabActionParams> actions;
15
+    public String screenInstanceId;
15
 
16
 
16
     public boolean hasExpendedState() {
17
     public boolean hasExpendedState() {
17
         return actions != null && actions.size() > 0;
18
         return actions != null && actions.size() > 0;

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

35
         return leftButton;
35
         return leftButton;
36
     }
36
     }
37
 
37
 
38
-    public static FabParams parseFab(Bundle params, String navigatorEventId) {
38
+    public static FabParams parseFab(Bundle params, String navigatorEventId, String screenInstanceId) {
39
         FabParams fabParams = null;
39
         FabParams fabParams = null;
40
         if (hasKey(params, KEY_FAB)) {
40
         if (hasKey(params, KEY_FAB)) {
41
-            fabParams = new FabParamsParser().parse(params.getBundle(KEY_FAB), navigatorEventId);
41
+            fabParams = new FabParamsParser().parse(params.getBundle(KEY_FAB), navigatorEventId, screenInstanceId);
42
         }
42
         }
43
         return fabParams;
43
         return fabParams;
44
     }
44
     }

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

8
 import com.reactnativenavigation.react.ImageLoader;
8
 import com.reactnativenavigation.react.ImageLoader;
9
 
9
 
10
 public class FabParamsParser extends Parser {
10
 public class FabParamsParser extends Parser {
11
-    public FabParams parse(Bundle params, final String navigatorEventId) {
11
+    public FabParams parse(Bundle params, final String navigatorEventId, String screenInstanceId) {
12
         FabParams fabParams = new FabParams();
12
         FabParams fabParams = new FabParams();
13
         fabParams.collapsedId = params.getString("collapsedId");
13
         fabParams.collapsedId = params.getString("collapsedId");
14
         fabParams.expendedId = params.getString("expendedId");
14
         fabParams.expendedId = params.getString("expendedId");
15
         fabParams.navigatorEventId = navigatorEventId;
15
         fabParams.navigatorEventId = navigatorEventId;
16
+        fabParams.screenInstanceId = screenInstanceId;
16
         fabParams.backgroundColor = getColor(params, "backgroundColor", new StyleParams.Color());
17
         fabParams.backgroundColor = getColor(params, "backgroundColor", new StyleParams.Color());
17
 
18
 
18
         if (hasKey(params, "collapsedIcon")) {
19
         if (hasKey(params, "collapsedIcon")) {

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

43
             result.fragmentCreatorPassProps = params.getBundle(FRAGMENT_CREATOR_PASS_PROPS);
43
             result.fragmentCreatorPassProps = params.getBundle(FRAGMENT_CREATOR_PASS_PROPS);
44
         }
44
         }
45
 
45
 
46
-        result.fabParams = ButtonParser.parseFab(params, result.navigationParams.navigatorEventId);
46
+        result.fabParams = ButtonParser.parseFab(params, result.navigationParams.navigatorEventId, result.navigationParams.screenInstanceId);
47
 
47
 
48
         result.tabLabel = getTabLabel(params);
48
         result.tabLabel = getTabLabel(params);
49
         result.tabIcon = getTabIcon(params);
49
         result.tabIcon = getTabIcon(params);

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

31
         result.navigationParams = new NavigationParams(params.getBundle(NAVIGATION_PARAMS));
31
         result.navigationParams = new NavigationParams(params.getBundle(NAVIGATION_PARAMS));
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, result.navigationParams.screenInstanceId);
35
         result.styleParams = new StyleParamsParser(params.getBundle("styleParams")).parse();
35
         result.styleParams = new StyleParamsParser(params.getBundle("styleParams")).parse();
36
         return result;
36
         return result;
37
     }
37
     }

+ 19
- 0
android/app/src/main/java/com/reactnativenavigation/utils/ViewUtils.java View File

9
 import android.util.DisplayMetrics;
9
 import android.util.DisplayMetrics;
10
 import android.view.View;
10
 import android.view.View;
11
 import android.view.ViewGroup;
11
 import android.view.ViewGroup;
12
+import android.view.ViewParent;
12
 import android.view.ViewTreeObserver;
13
 import android.view.ViewTreeObserver;
13
 import android.view.WindowManager;
14
 import android.view.WindowManager;
14
 
15
 
15
 import com.reactnativenavigation.NavigationApplication;
16
 import com.reactnativenavigation.NavigationApplication;
16
 import com.reactnativenavigation.params.AppStyle;
17
 import com.reactnativenavigation.params.AppStyle;
18
+import com.reactnativenavigation.screens.Screen;
17
 
19
 
18
 import java.util.concurrent.atomic.AtomicInteger;
20
 import java.util.concurrent.atomic.AtomicInteger;
19
 
21
 
115
     public interface PerformOnViewTask {
117
     public interface PerformOnViewTask {
116
         void runOnView(View view);
118
         void runOnView(View view);
117
     }
119
     }
120
+
121
+    public static void performOnParentScreen(View child, Task<Screen> task) {
122
+        Screen parentScreen = findParentScreen(child.getParent());
123
+        if (parentScreen != null) {
124
+            task.run(parentScreen);
125
+        }
126
+    }
127
+
128
+    private static Screen findParentScreen(ViewParent parent) {
129
+        if (parent == null) {
130
+            return null;
131
+        }
132
+        if (parent instanceof Screen) {
133
+            return (Screen) parent;
134
+        }
135
+        return findParentScreen(parent.getParent());
136
+    }
118
 }
137
 }
119
 
138
 

+ 3
- 0
android/app/src/main/java/com/reactnativenavigation/views/FloatingActionButtonAnimator.java View File

87
     }
87
     }
88
 
88
 
89
     void removeFabFromScreen(FloatingActionButton fab, final AnimatorListenerAdapter animationListener) {
89
     void removeFabFromScreen(FloatingActionButton fab, final AnimatorListenerAdapter animationListener) {
90
+        if (fab == null) {
91
+            return;
92
+        }
90
         state = State.Removing;
93
         state = State.Removing;
91
         fab.animate()
94
         fab.animate()
92
                 .alpha(0)
95
                 .alpha(0)

+ 16
- 3
android/app/src/main/java/com/reactnativenavigation/views/FloatingActionButtonCoordinator.java View File

10
 import android.support.annotation.Nullable;
10
 import android.support.annotation.Nullable;
11
 import android.support.design.widget.CoordinatorLayout;
11
 import android.support.design.widget.CoordinatorLayout;
12
 import android.support.design.widget.FloatingActionButton;
12
 import android.support.design.widget.FloatingActionButton;
13
+import android.util.Log;
13
 import android.view.Gravity;
14
 import android.view.Gravity;
14
 import android.view.View;
15
 import android.view.View;
15
 
16
 
23
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
24
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
24
 
25
 
25
 public class FloatingActionButtonCoordinator {
26
 public class FloatingActionButtonCoordinator {
26
-
27
+    private static final String TAG = "FloatingActionButtonCoo";
27
     private static final int INITIAL_EXPENDED_FAB_ROTATION = -90;
28
     private static final int INITIAL_EXPENDED_FAB_ROTATION = -90;
28
     private CoordinatorLayout parent;
29
     private CoordinatorLayout parent;
29
     private FabParams params;
30
     private FabParams params;
42
         actionSize = (int) ViewUtils.convertDpToPixel(40);
43
         actionSize = (int) ViewUtils.convertDpToPixel(40);
43
     }
44
     }
44
 
45
 
45
-    public void add(FabParams params) {
46
+    public void add(final FabParams params) {
47
+        Log.i(TAG, "add() called with: params = [" + params + "]");
48
+        if (parent.getChildCount() > 0) {
49
+            remove(new Runnable() {
50
+                @Override
51
+                public void run() {
52
+                    add(params);
53
+                }
54
+            });
55
+            return;
56
+        }
57
+
46
         this.params = params;
58
         this.params = params;
47
         if (!params.isValid()) {
59
         if (!params.isValid()) {
48
             return;
60
             return;
55
     }
67
     }
56
 
68
 
57
     public void remove(@Nullable final Runnable onComplete) {
69
     public void remove(@Nullable final Runnable onComplete) {
58
-        if (parent.getChildCount() == 0 || fabAnimator.isAnimating()) {
70
+        Log.w(TAG, "remove: ");
71
+        if (parent.getChildCount() == 0) {
59
             if (onComplete != null) {
72
             if (onComplete != null) {
60
                 onComplete.run();
73
                 onComplete.run();
61
             }
74
             }

+ 7
- 2
android/app/src/main/java/com/reactnativenavigation/views/SnackbarAndFabContainer.java View File

8
 import com.reactnativenavigation.events.FabSetEvent;
8
 import com.reactnativenavigation.events.FabSetEvent;
9
 import com.reactnativenavigation.events.ScreenChangedEvent;
9
 import com.reactnativenavigation.events.ScreenChangedEvent;
10
 import com.reactnativenavigation.events.Subscriber;
10
 import com.reactnativenavigation.events.Subscriber;
11
+import com.reactnativenavigation.layouts.Layout;
11
 import com.reactnativenavigation.params.FabParams;
12
 import com.reactnativenavigation.params.FabParams;
12
 import com.reactnativenavigation.params.SnackbarParams;
13
 import com.reactnativenavigation.params.SnackbarParams;
13
 
14
 
14
 public class SnackbarAndFabContainer extends CoordinatorLayout implements Snakbar.OnDismissListener, Subscriber{
15
 public class SnackbarAndFabContainer extends CoordinatorLayout implements Snakbar.OnDismissListener, Subscriber{
15
     private Snakbar snakbar;
16
     private Snakbar snakbar;
16
     private FloatingActionButtonCoordinator fabCoordinator;
17
     private FloatingActionButtonCoordinator fabCoordinator;
18
+    private Layout layout;
17
 
19
 
18
-    public SnackbarAndFabContainer(Context context) {
20
+    public SnackbarAndFabContainer(Context context, Layout layout) {
19
         super(context);
21
         super(context);
22
+        this.layout = layout;
20
         fabCoordinator = new FloatingActionButtonCoordinator(this);
23
         fabCoordinator = new FloatingActionButtonCoordinator(this);
21
         EventBus.instance.register(this);
24
         EventBus.instance.register(this);
22
     }
25
     }
64
             @Override
67
             @Override
65
             public void run() {
68
             public void run() {
66
                 if (fabParams != null) {
69
                 if (fabParams != null) {
67
-                    fabCoordinator.add(fabParams);
70
+                    if (layout.getCurrentScreen().getScreenInstanceId().equals(fabParams.screenInstanceId)) {
71
+                        fabCoordinator.add(fabParams);
72
+                    }
68
                 }
73
                 }
69
             }
74
             }
70
         });
75
         });