Преглед на файлове

Animate fab in and out when screen changes

Guy Carmeli преди 8 години
родител
ревизия
1142b437d8

+ 11
- 0
android/app/src/main/java/com/reactnativenavigation/events/ScreenChangedEvent.java Целия файл

@@ -1,7 +1,18 @@
1 1
 package com.reactnativenavigation.events;
2 2
 
3
+import com.reactnativenavigation.params.ScreenParams;
4
+
3 5
 public class ScreenChangedEvent implements Event {
4 6
     public static final String TYPE = "ScreenChangedEvent";
7
+    private ScreenParams screenParams;
8
+
9
+    public ScreenChangedEvent(ScreenParams screenParams) {
10
+        this.screenParams = screenParams;
11
+    }
12
+
13
+    public ScreenParams getScreenParams() {
14
+        return screenParams;
15
+    }
5 16
 
6 17
     @Override
7 18
     public String getType() {

+ 14
- 20
android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java Целия файл

@@ -8,8 +8,9 @@ import android.widget.RelativeLayout;
8 8
 
9 9
 import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
10 10
 import com.reactnativenavigation.NavigationApplication;
11
+import com.reactnativenavigation.events.EventBus;
12
+import com.reactnativenavigation.events.ScreenChangedEvent;
11 13
 import com.reactnativenavigation.params.ActivityParams;
12
-import com.reactnativenavigation.params.FabParams;
13 14
 import com.reactnativenavigation.params.ScreenParams;
14 15
 import com.reactnativenavigation.params.SideMenuParams;
15 16
 import com.reactnativenavigation.params.SnackbarParams;
@@ -52,7 +53,6 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
52 53
         addScreenStacks();
53 54
         createSnackbarContainer();
54 55
         showInitialScreenStack();
55
-        showFab();
56 56
     }
57 57
 
58 58
     private void createSideMenu() {
@@ -110,13 +110,7 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
110 110
 
111 111
     private void showInitialScreenStack() {
112 112
         showStackAndUpdateStyle(screenStacks[0]);
113
-    }
114
-
115
-    private void showFab() {
116
-        FabParams fabParams = getCurrentScreenStack().peek().getFabParams();
117
-        if (fabParams != null) {
118
-            snackbarAndFabContainer.showFab(fabParams);
119
-        }
113
+        EventBus.instance.post(new ScreenChangedEvent(screenStacks[0].peek().getScreenParams()));
120 114
     }
121 115
 
122 116
     @Override
@@ -207,31 +201,31 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
207 201
     }
208 202
 
209 203
     @Override
210
-    public void push(ScreenParams screenParams) {
211
-        ScreenStack screenStack = getScreenStack(screenParams.getNavigatorId());
212
-        screenStack.push(screenParams, createScreenLayoutParams(screenParams));
204
+    public void push(ScreenParams params) {
205
+        ScreenStack screenStack = getScreenStack(params.getNavigatorId());
206
+        screenStack.push(params, createScreenLayoutParams(params));
213 207
         if (isCurrentStack(screenStack)) {
214
-            bottomTabs.setStyleFromScreen(screenParams.styleParams);
208
+            bottomTabs.setStyleFromScreen(params.styleParams);
215 209
         }
216
-        snackbarAndFabContainer.onScreenChange();
210
+        EventBus.instance.post(new ScreenChangedEvent(params));
217 211
     }
218 212
 
219 213
     @Override
220
-    public void pop(ScreenParams screenParams) {
221
-        getCurrentScreenStack().pop(screenParams.animateScreenTransitions, new ScreenStack.OnScreenPop() {
214
+    public void pop(ScreenParams params) {
215
+        getCurrentScreenStack().pop(params.animateScreenTransitions, new ScreenStack.OnScreenPop() {
222 216
             @Override
223 217
             public void onScreenPopAnimationEnd() {
224 218
                 setBottomTabsStyleFromCurrentScreen();
225 219
             }
226 220
         });
227
-        snackbarAndFabContainer.onScreenChange();
221
+        EventBus.instance.post(new ScreenChangedEvent(getCurrentScreenStack().peek().getScreenParams()));
228 222
     }
229 223
 
230 224
     @Override
231 225
     public void popToRoot(ScreenParams params) {
232 226
         getCurrentScreenStack().popToRoot(params.animateScreenTransitions);
233 227
         setBottomTabsStyleFromCurrentScreen();
234
-        snackbarAndFabContainer.onScreenChange();
228
+        EventBus.instance.post(new ScreenChangedEvent(getCurrentScreenStack().peek().getScreenParams()));
235 229
     }
236 230
 
237 231
     @Override
@@ -246,7 +240,7 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
246 240
         screenStacks[currentStackIndex] = newStack;
247 241
 
248 242
         bottomTabs.setStyleFromScreen(params.styleParams);
249
-        snackbarAndFabContainer.onScreenChange();
243
+        EventBus.instance.post(new ScreenChangedEvent(params));
250 244
     }
251 245
 
252 246
     @Override
@@ -264,7 +258,7 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
264 258
     public boolean onTabSelected(int position, boolean wasSelected) {
265 259
         hideCurrentStack();
266 260
         showNewStack(position);
267
-        snackbarAndFabContainer.onScreenChange();
261
+        EventBus.instance.post(new ScreenChangedEvent(getCurrentScreenStack().peek().getScreenParams()));
268 262
         return true;
269 263
     }
270 264
 

+ 6
- 4
android/app/src/main/java/com/reactnativenavigation/layouts/SingleScreenLayout.java Целия файл

@@ -6,6 +6,8 @@ import android.view.View;
6 6
 import android.widget.RelativeLayout;
7 7
 
8 8
 import com.reactnativenavigation.NavigationApplication;
9
+import com.reactnativenavigation.events.EventBus;
10
+import com.reactnativenavigation.events.ScreenChangedEvent;
9 11
 import com.reactnativenavigation.params.ScreenParams;
10 12
 import com.reactnativenavigation.params.SideMenuParams;
11 13
 import com.reactnativenavigation.params.SnackbarParams;
@@ -109,26 +111,26 @@ public class SingleScreenLayout extends RelativeLayout implements Layout {
109 111
     public void push(ScreenParams params) {
110 112
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
111 113
         stack.push(params, lp);
112
-        snackbarAndFabContainer.onScreenChange();
114
+        EventBus.instance.post(new ScreenChangedEvent(params));
113 115
     }
114 116
 
115 117
     @Override
116 118
     public void pop(ScreenParams params) {
117 119
         stack.pop(params.animateScreenTransitions);
118
-        snackbarAndFabContainer.onScreenChange();
120
+        EventBus.instance.post(new ScreenChangedEvent(stack.peek().getScreenParams()));
119 121
     }
120 122
 
121 123
     @Override
122 124
     public void popToRoot(ScreenParams params) {
123 125
         stack.popToRoot(params.animateScreenTransitions);
124
-        snackbarAndFabContainer.onScreenChange();
126
+        EventBus.instance.post(new ScreenChangedEvent(stack.peek().getScreenParams()));
125 127
     }
126 128
 
127 129
     @Override
128 130
     public void newStack(ScreenParams params) {
129 131
         RelativeLayout parent = sideMenu == null ? this : sideMenu.getContentContainer();
130 132
         createStack(parent);
131
-        snackbarAndFabContainer.onScreenChange();
133
+        EventBus.instance.post(new ScreenChangedEvent(params));
132 134
     }
133 135
 
134 136
     @Override

+ 2
- 1
android/app/src/main/java/com/reactnativenavigation/screens/ContentViewPagerAdapter.java Целия файл

@@ -41,7 +41,8 @@ public class ContentViewPagerAdapter extends PagerAdapter {
41 41
     }
42 42
 
43 43
     private void sendScreenChangeBroadcast() {
44
-        EventBus.instance.post(new ScreenChangedEvent());
44
+        // TODO Send navigatorParams to native. -guyca
45
+        EventBus.instance.post(new ScreenChangedEvent(null));
45 46
     }
46 47
 
47 48
     private void sendTabSelectedEventToJs() {

+ 2
- 3
android/app/src/main/java/com/reactnativenavigation/screens/Screen.java Целия файл

@@ -9,7 +9,6 @@ import android.view.Window;
9 9
 import android.widget.RelativeLayout;
10 10
 
11 11
 import com.reactnativenavigation.animation.VisibilityAnimator;
12
-import com.reactnativenavigation.params.FabParams;
13 12
 import com.reactnativenavigation.params.ScreenParams;
14 13
 import com.reactnativenavigation.params.StyleParams;
15 14
 import com.reactnativenavigation.params.TitleBarButtonParams;
@@ -137,8 +136,8 @@ public abstract class Screen extends RelativeLayout {
137 136
         return screenParams.getNavigatorEventId();
138 137
     }
139 138
 
140
-    public FabParams getFabParams() {
141
-        return screenParams.fabParams;
139
+    public ScreenParams getScreenParams() {
140
+        return screenParams;
142 141
     }
143 142
 
144 143
     public void setTopBarVisible(boolean visible, boolean animate) {

+ 64
- 4
android/app/src/main/java/com/reactnativenavigation/views/FloatingActionButtonCoordinator.java Целия файл

@@ -31,15 +31,68 @@ public class FloatingActionButtonCoordinator {
31 31
     final int margin = (int) ViewUtils.convertDpToPixel(16);
32 32
     private final ArrayList<FloatingActionButton> actions;
33 33
 
34
-    public FloatingActionButtonCoordinator(CoordinatorLayout parent, FabParams params) {
34
+    public FloatingActionButtonCoordinator(CoordinatorLayout parent) {
35 35
         this.parent = parent;
36
-        this.params = params;
37 36
         actions = new ArrayList<>();
38 37
         crossFadeAnimationDuration = parent.getResources().getInteger(android.R.integer.config_shortAnimTime);
39 38
         actionSize = (int) ViewUtils.convertDpToPixel(40);
39
+    }
40
+
41
+    public void add(FabParams params) {
42
+        this.params = params;
40 43
         createCollapsedFab();
41 44
         createExpendedFab();
42 45
         setStyle();
46
+        show();
47
+    }
48
+
49
+    public void remove(final Runnable onComplete) {
50
+        if (parent.getChildCount() == 0) {
51
+            onComplete.run();
52
+            return;
53
+        }
54
+
55
+        removeFabFromScreen(expendedFab, new AnimatorListenerAdapter() {
56
+            @Override
57
+            public void onAnimationEnd(Animator animation) {
58
+                removeAllViews();
59
+                onComplete.run();
60
+            }
61
+        });
62
+        removeFabFromScreen(collapsedFab, null);
63
+        removeActionsFromScreen();
64
+    }
65
+
66
+    private void removeActionsFromScreen() {
67
+        for (FloatingActionButton action : actions) {
68
+            action.animate()
69
+                    .alpha(0)
70
+                    .scaleX(0)
71
+                    .scaleY(0)
72
+                    .setDuration(crossFadeAnimationDuration)
73
+                    .start();
74
+        }
75
+    }
76
+
77
+    private void removeFabFromScreen(FloatingActionButton fab, AnimatorListenerAdapter animationListener) {
78
+        fab.animate()
79
+                .alpha(0)
80
+                .scaleX(0)
81
+                .scaleY(0)
82
+                .setDuration(crossFadeAnimationDuration)
83
+                .setListener(animationListener)
84
+                .start();
85
+    }
86
+
87
+    private void removeAllViews() {
88
+        parent.removeView(collapsedFab);
89
+        parent.removeView(expendedFab);
90
+        collapsedFab = null;
91
+        expendedFab = null;
92
+        for (FloatingActionButton action : actions) {
93
+            parent.removeView(action);
94
+        }
95
+        actions.clear();
43 96
     }
44 97
 
45 98
     private void createCollapsedFab() {
@@ -127,8 +180,15 @@ public class FloatingActionButtonCoordinator {
127 180
         expendedFab.setBackgroundTintList(ColorStateList.valueOf(params.backgroundColor.getColor()));
128 181
     }
129 182
 
130
-    public void show() {
131
-
183
+    private void show() {
184
+        collapsedFab.setScaleX(0);
185
+        collapsedFab.setScaleY(0);
186
+        collapsedFab.animate()
187
+                .alpha(1)
188
+                .scaleX(1)
189
+                .scaleY(1)
190
+                .setDuration(crossFadeAnimationDuration)
191
+                .start();
132 192
     }
133 193
 
134 194
     private void showActions() {

+ 27
- 15
android/app/src/main/java/com/reactnativenavigation/views/SnackbarAndFabContainer.java Целия файл

@@ -1,22 +1,22 @@
1 1
 package com.reactnativenavigation.views;
2 2
 
3 3
 import android.content.Context;
4
-import android.support.annotation.NonNull;
5 4
 import android.support.design.widget.CoordinatorLayout;
6 5
 
7 6
 import com.reactnativenavigation.events.Event;
8 7
 import com.reactnativenavigation.events.EventBus;
9 8
 import com.reactnativenavigation.events.ScreenChangedEvent;
10 9
 import com.reactnativenavigation.events.Subscriber;
11
-import com.reactnativenavigation.params.FabParams;
10
+import com.reactnativenavigation.params.ScreenParams;
12 11
 import com.reactnativenavigation.params.SnackbarParams;
13 12
 
14 13
 public class SnackbarAndFabContainer extends CoordinatorLayout implements Snakbar.OnDismissListener, Subscriber{
15 14
     private Snakbar snakbar;
16
-    private FloatingActionButtonCoordinator actionButtonCoordinator;
15
+    private FloatingActionButtonCoordinator fabCoordinator;
17 16
 
18 17
     public SnackbarAndFabContainer(Context context) {
19 18
         super(context);
19
+        fabCoordinator = new FloatingActionButtonCoordinator(this);
20 20
         EventBus.instance.register(this);
21 21
     }
22 22
 
@@ -25,13 +25,6 @@ public class SnackbarAndFabContainer extends CoordinatorLayout implements Snakba
25 25
         snakbar.show();
26 26
     }
27 27
 
28
-    public void onScreenChange() {
29
-        if (snakbar != null) {
30
-            snakbar.dismiss();
31
-            snakbar = null;
32
-        }
33
-    }
34
-
35 28
     @Override
36 29
     public void onDismiss(Snakbar snakbar) {
37 30
         if (this.snakbar == snakbar) {
@@ -43,14 +36,33 @@ public class SnackbarAndFabContainer extends CoordinatorLayout implements Snakba
43 36
         EventBus.instance.unregister(this);
44 37
     }
45 38
 
46
-    public void showFab(@NonNull FabParams fabParams) {
47
-        actionButtonCoordinator = new FloatingActionButtonCoordinator(this, fabParams);
48
-    }
49
-
50 39
     @Override
51 40
     public void onEvent(Event event) {
52 41
         if (event.getType() == ScreenChangedEvent.TYPE) {
53
-            onScreenChange();
42
+            onScreenChange(((ScreenChangedEvent) event).getScreenParams());
43
+        }
44
+    }
45
+
46
+    private void onScreenChange(ScreenParams screenParams) {
47
+        dismissSnackbar();
48
+        updateFab(screenParams);
49
+    }
50
+
51
+    private void dismissSnackbar() {
52
+        if (snakbar != null) {
53
+            snakbar.dismiss();
54
+            snakbar = null;
54 55
         }
55 56
     }
57
+
58
+    private void updateFab(final ScreenParams screenParams) {
59
+        fabCoordinator.remove(new Runnable() {
60
+            @Override
61
+            public void run() {
62
+                if (screenParams.fabParams != null) {
63
+                    fabCoordinator.add(screenParams.fabParams);
64
+                }
65
+            }
66
+        });
67
+    }
56 68
 }