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,7 +98,7 @@ public class NavigationReactModule extends ReactContextBaseJavaModule {
98 98
     }
99 99
 
100 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 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,6 +21,7 @@ import com.reactnativenavigation.params.SideMenuParams;
21 21
 import com.reactnativenavigation.params.SnackbarParams;
22 22
 import com.reactnativenavigation.params.TitleBarButtonParams;
23 23
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
24
+import com.reactnativenavigation.screens.Screen;
24 25
 import com.reactnativenavigation.screens.ScreenStack;
25 26
 import com.reactnativenavigation.views.BottomTabs;
26 27
 import com.reactnativenavigation.views.SideMenu;
@@ -110,7 +111,7 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
110 111
     }
111 112
 
112 113
     private void createSnackbarContainer() {
113
-        snackbarAndFabContainer = new SnackbarAndFabContainer(getContext());
114
+        snackbarAndFabContainer = new SnackbarAndFabContainer(getContext(), this);
114 115
         RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
115 116
         lp.addRule(ABOVE, bottomTabs.getId());
116 117
         getScreenStackParent().addView(snackbarAndFabContainer, lp);
@@ -229,6 +230,11 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
229 230
         getCurrentScreenStack().peek().dismissContextualMenu();
230 231
     }
231 232
 
233
+    @Override
234
+    public Screen getCurrentScreen() {
235
+        return getCurrentScreenStack().peek();
236
+    }
237
+
232 238
     public void selectBottomTabByTabIndex(Integer index) {
233 239
         bottomTabs.setCurrentItem(index);
234 240
     }

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

@@ -8,6 +8,7 @@ import com.reactnativenavigation.params.FabParams;
8 8
 import com.reactnativenavigation.params.SnackbarParams;
9 9
 import com.reactnativenavigation.params.TitleBarButtonParams;
10 10
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
11
+import com.reactnativenavigation.screens.Screen;
11 12
 import com.reactnativenavigation.views.SideMenu.Side;
12 13
 
13 14
 import java.util.List;
@@ -42,4 +43,6 @@ public interface Layout extends ScreenStackContainer {
42 43
     void showContextualMenu(String screenInstanceId, ContextualMenuParams params, Callback onButtonClicked);
43 44
 
44 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,6 +16,7 @@ import com.reactnativenavigation.params.SideMenuParams;
16 16
 import com.reactnativenavigation.params.SnackbarParams;
17 17
 import com.reactnativenavigation.params.TitleBarButtonParams;
18 18
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
19
+import com.reactnativenavigation.screens.Screen;
19 20
 import com.reactnativenavigation.screens.ScreenStack;
20 21
 import com.reactnativenavigation.views.LeftButtonOnClickListener;
21 22
 import com.reactnativenavigation.views.SideMenu;
@@ -92,7 +93,7 @@ public class SingleScreenLayout extends RelativeLayout implements Layout {
92 93
     }
93 94
 
94 95
     private void createFabAndSnackbarContainer() {
95
-        snackbarAndFabContainer = new SnackbarAndFabContainer(getContext());
96
+        snackbarAndFabContainer = new SnackbarAndFabContainer(getContext(), this);
96 97
         RelativeLayout.LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
97 98
         lp.addRule(ALIGN_PARENT_BOTTOM);
98 99
         snackbarAndFabContainer.setLayoutParams(lp);
@@ -231,6 +232,11 @@ public class SingleScreenLayout extends RelativeLayout implements Layout {
231 232
         stack.dismissContextualMenu(screenInstanceId);
232 233
     }
233 234
 
235
+    @Override
236
+    public Screen getCurrentScreen() {
237
+        return stack.peek();
238
+    }
239
+
234 240
     @Override
235 241
     public boolean onTitleBarBackButtonClick() {
236 242
         if (leftButtonOnClickListener != null) {

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

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

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

@@ -35,10 +35,10 @@ public class ButtonParser extends Parser {
35 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 39
         FabParams fabParams = null;
40 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 43
         return fabParams;
44 44
     }

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

@@ -8,11 +8,12 @@ import com.reactnativenavigation.params.StyleParams;
8 8
 import com.reactnativenavigation.react.ImageLoader;
9 9
 
10 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 12
         FabParams fabParams = new FabParams();
13 13
         fabParams.collapsedId = params.getString("collapsedId");
14 14
         fabParams.expendedId = params.getString("expendedId");
15 15
         fabParams.navigatorEventId = navigatorEventId;
16
+        fabParams.screenInstanceId = screenInstanceId;
16 17
         fabParams.backgroundColor = getColor(params, "backgroundColor", new StyleParams.Color());
17 18
 
18 19
         if (hasKey(params, "collapsedIcon")) {

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

@@ -43,7 +43,7 @@ public class ScreenParamsParser extends Parser {
43 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 48
         result.tabLabel = getTabLabel(params);
49 49
         result.tabIcon = getTabIcon(params);

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

@@ -31,7 +31,7 @@ public class TopTabParamsParser extends Parser {
31 31
         result.navigationParams = new NavigationParams(params.getBundle(NAVIGATION_PARAMS));
32 32
         result.leftButton = ButtonParser.parseLeftButton(params);
33 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 35
         result.styleParams = new StyleParamsParser(params.getBundle("styleParams")).parse();
36 36
         return result;
37 37
     }

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

@@ -9,11 +9,13 @@ import android.support.annotation.Nullable;
9 9
 import android.util.DisplayMetrics;
10 10
 import android.view.View;
11 11
 import android.view.ViewGroup;
12
+import android.view.ViewParent;
12 13
 import android.view.ViewTreeObserver;
13 14
 import android.view.WindowManager;
14 15
 
15 16
 import com.reactnativenavigation.NavigationApplication;
16 17
 import com.reactnativenavigation.params.AppStyle;
18
+import com.reactnativenavigation.screens.Screen;
17 19
 
18 20
 import java.util.concurrent.atomic.AtomicInteger;
19 21
 
@@ -115,5 +117,22 @@ public class ViewUtils {
115 117
     public interface PerformOnViewTask {
116 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,6 +87,9 @@ public class FloatingActionButtonAnimator {
87 87
     }
88 88
 
89 89
     void removeFabFromScreen(FloatingActionButton fab, final AnimatorListenerAdapter animationListener) {
90
+        if (fab == null) {
91
+            return;
92
+        }
90 93
         state = State.Removing;
91 94
         fab.animate()
92 95
                 .alpha(0)

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

@@ -10,6 +10,7 @@ import android.support.annotation.NonNull;
10 10
 import android.support.annotation.Nullable;
11 11
 import android.support.design.widget.CoordinatorLayout;
12 12
 import android.support.design.widget.FloatingActionButton;
13
+import android.util.Log;
13 14
 import android.view.Gravity;
14 15
 import android.view.View;
15 16
 
@@ -23,7 +24,7 @@ import java.util.ArrayList;
23 24
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
24 25
 
25 26
 public class FloatingActionButtonCoordinator {
26
-
27
+    private static final String TAG = "FloatingActionButtonCoo";
27 28
     private static final int INITIAL_EXPENDED_FAB_ROTATION = -90;
28 29
     private CoordinatorLayout parent;
29 30
     private FabParams params;
@@ -42,7 +43,18 @@ public class FloatingActionButtonCoordinator {
42 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 58
         this.params = params;
47 59
         if (!params.isValid()) {
48 60
             return;
@@ -55,7 +67,8 @@ public class FloatingActionButtonCoordinator {
55 67
     }
56 68
 
57 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 72
             if (onComplete != null) {
60 73
                 onComplete.run();
61 74
             }

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

@@ -8,15 +8,18 @@ import com.reactnativenavigation.events.EventBus;
8 8
 import com.reactnativenavigation.events.FabSetEvent;
9 9
 import com.reactnativenavigation.events.ScreenChangedEvent;
10 10
 import com.reactnativenavigation.events.Subscriber;
11
+import com.reactnativenavigation.layouts.Layout;
11 12
 import com.reactnativenavigation.params.FabParams;
12 13
 import com.reactnativenavigation.params.SnackbarParams;
13 14
 
14 15
 public class SnackbarAndFabContainer extends CoordinatorLayout implements Snakbar.OnDismissListener, Subscriber{
15 16
     private Snakbar snakbar;
16 17
     private FloatingActionButtonCoordinator fabCoordinator;
18
+    private Layout layout;
17 19
 
18
-    public SnackbarAndFabContainer(Context context) {
20
+    public SnackbarAndFabContainer(Context context, Layout layout) {
19 21
         super(context);
22
+        this.layout = layout;
20 23
         fabCoordinator = new FloatingActionButtonCoordinator(this);
21 24
         EventBus.instance.register(this);
22 25
     }
@@ -64,7 +67,9 @@ public class SnackbarAndFabContainer extends CoordinatorLayout implements Snakba
64 67
             @Override
65 68
             public void run() {
66 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
         });