Explorar el Código

Merge branch 'sideMenu' into v2.0

Guy Carmeli hace 8 años
padre
commit
616a04bc62
Se han modificado 39 ficheros con 858 adiciones y 216 borrados
  1. 7
    1
      android/app/src/main/java/com/reactnativenavigation/bridge/NavigationReactModule.java
  2. 4
    1
      android/app/src/main/java/com/reactnativenavigation/controllers/Modal.java
  3. 7
    2
      android/app/src/main/java/com/reactnativenavigation/controllers/ModalController.java
  4. 8
    0
      android/app/src/main/java/com/reactnativenavigation/controllers/NavigationActivity.java
  5. 28
    0
      android/app/src/main/java/com/reactnativenavigation/controllers/NavigationCommandsHandler.java
  6. 77
    11
      android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java
  7. 4
    0
      android/app/src/main/java/com/reactnativenavigation/layouts/Layout.java
  8. 3
    2
      android/app/src/main/java/com/reactnativenavigation/layouts/LayoutFactory.java
  9. 2
    2
      android/app/src/main/java/com/reactnativenavigation/layouts/ScreenStackContainer.java
  10. 66
    18
      android/app/src/main/java/com/reactnativenavigation/layouts/SingleScreenLayout.java
  11. 1
    0
      android/app/src/main/java/com/reactnativenavigation/params/ActivityParams.java
  12. 1
    0
      android/app/src/main/java/com/reactnativenavigation/params/ScreenParams.java
  13. 9
    0
      android/app/src/main/java/com/reactnativenavigation/params/SideMenuParams.java
  14. 4
    0
      android/app/src/main/java/com/reactnativenavigation/params/parsers/ActivityParamsParser.java
  15. 2
    0
      android/app/src/main/java/com/reactnativenavigation/params/parsers/ScreenParamsParser.java
  16. 16
    0
      android/app/src/main/java/com/reactnativenavigation/params/parsers/SideMenuParamsParser.java
  17. 3
    3
      android/app/src/main/java/com/reactnativenavigation/params/parsers/TitleBarLeftButtonParamsParser.java
  18. 3
    4
      android/app/src/main/java/com/reactnativenavigation/screens/FragmentScreen.java
  19. 6
    6
      android/app/src/main/java/com/reactnativenavigation/screens/Screen.java
  20. 5
    5
      android/app/src/main/java/com/reactnativenavigation/screens/ScreenFactory.java
  21. 36
    9
      android/app/src/main/java/com/reactnativenavigation/screens/ScreenStack.java
  22. 3
    3
      android/app/src/main/java/com/reactnativenavigation/screens/SingleScreen.java
  23. 3
    3
      android/app/src/main/java/com/reactnativenavigation/screens/ViewPagerScreen.java
  24. 6
    2
      android/app/src/main/java/com/reactnativenavigation/views/ContentView.java
  25. 10
    4
      android/app/src/main/java/com/reactnativenavigation/views/LeftButton.java
  26. 7
    0
      android/app/src/main/java/com/reactnativenavigation/views/LeftButtonOnClickListener.java
  27. 74
    0
      android/app/src/main/java/com/reactnativenavigation/views/SideMenu.java
  28. 4
    4
      android/app/src/main/java/com/reactnativenavigation/views/TitleBar.java
  29. 0
    5
      android/app/src/main/java/com/reactnativenavigation/views/TitleBarBackButtonListener.java
  30. 4
    4
      android/app/src/main/java/com/reactnativenavigation/views/TopBar.java
  31. 86
    71
      example-redux/src/app.js
  32. 101
    0
      example-redux/src/screens/BottomTabsSideMenu.js
  33. 48
    15
      example-redux/src/screens/FirstTabScreen.js
  34. 31
    3
      example-redux/src/screens/ListScreen.js
  35. 44
    7
      example-redux/src/screens/SecondTabScreen.js
  36. 89
    0
      example-redux/src/screens/SideMenu.js
  37. 4
    0
      example-redux/src/screens/index.js
  38. 37
    30
      src/deprecated/platformSpecificDeprecated.android.js
  39. 15
    1
      src/platformSpecific.android.js

+ 7
- 1
android/app/src/main/java/com/reactnativenavigation/bridge/NavigationReactModule.java Ver fichero

80
     }
80
     }
81
 
81
 
82
     @ReactMethod
82
     @ReactMethod
83
-    public void toggleSideMenuVisible(final ReadableMap params) {
83
+    public void toggleSideMenuVisible(boolean animated) {
84
+        NavigationCommandsHandler.toggleSideMenuVisible(animated);
85
+    }
86
+
87
+    @ReactMethod
88
+    public void setSideMenuVisible(boolean animated, boolean visible) {
89
+        NavigationCommandsHandler.setSideMenuVisible(animated, visible);
84
     }
90
     }
85
 
91
 
86
     @ReactMethod
92
     @ReactMethod

+ 4
- 1
android/app/src/main/java/com/reactnativenavigation/controllers/Modal.java Ver fichero

39
     }
39
     }
40
 
40
 
41
     @Override
41
     @Override
42
-    public boolean onTitleBarBackPress() {
42
+    public boolean onTitleBarBackButtonClick() {
43
         if (!layout.onBackPressed()) {
43
         if (!layout.onBackPressed()) {
44
             onBackPressed();
44
             onBackPressed();
45
         }
45
         }
46
         return true;
46
         return true;
47
     }
47
     }
48
 
48
 
49
+    public void onSideMenuButtonClick() {
50
+    }
51
+
49
     public interface OnModalDismissedListener {
52
     public interface OnModalDismissedListener {
50
         void onModalDismissed(Modal modal);
53
         void onModalDismissed(Modal modal);
51
     }
54
     }

+ 7
- 2
android/app/src/main/java/com/reactnativenavigation/controllers/ModalController.java Ver fichero

98
     }
98
     }
99
 
99
 
100
     @Override
100
     @Override
101
-    public boolean onTitleBarBackPress() {
102
-        // Do nothing and let the layout handle the back press
101
+    public boolean onTitleBarBackButtonClick() {
102
+        // Do nothing and let the layout handle the back button click
103
         return false;
103
         return false;
104
     }
104
     }
105
+
106
+    @Override
107
+    public void onSideMenuButtonClick() {
108
+        // Do nothing and let the layout handle the click
109
+    }
105
 }
110
 }

+ 8
- 0
android/app/src/main/java/com/reactnativenavigation/controllers/NavigationActivity.java Ver fichero

195
         layout.setTitleBarLeftButton(screenInstanceId, navigatorEventId, titleBarLeftButton);
195
         layout.setTitleBarLeftButton(screenInstanceId, navigatorEventId, titleBarLeftButton);
196
         modalController.setTitleBarLeftButton(screenInstanceId, navigatorEventId, titleBarLeftButton);
196
         modalController.setTitleBarLeftButton(screenInstanceId, navigatorEventId, titleBarLeftButton);
197
     }
197
     }
198
+
199
+    public void toggleSideMenuVisible(boolean animated) {
200
+        layout.toggleSideMenuVisible(animated);
201
+    }
202
+
203
+    public void setSideMenuVisible(boolean animated, boolean visible) {
204
+        layout.setSideMenuVisible(animated, visible);
205
+    }
198
 }
206
 }

+ 28
- 0
android/app/src/main/java/com/reactnativenavigation/controllers/NavigationCommandsHandler.java Ver fichero

210
             }
210
             }
211
         });
211
         });
212
     }
212
     }
213
+
214
+    public static void toggleSideMenuVisible(final boolean animated) {
215
+        final NavigationActivity currentActivity = NavigationActivity.currentActivity;
216
+        if (currentActivity == null) {
217
+            return;
218
+        }
219
+
220
+        NavigationApplication.instance.runOnMainThread(new Runnable() {
221
+            @Override
222
+            public void run() {
223
+                currentActivity.toggleSideMenuVisible(animated);
224
+            }
225
+        });
226
+    }
227
+
228
+    public static void setSideMenuVisible(final boolean animated, final boolean visible) {
229
+        final NavigationActivity currentActivity = NavigationActivity.currentActivity;
230
+        if (currentActivity == null) {
231
+            return;
232
+        }
233
+
234
+        NavigationApplication.instance.runOnMainThread(new Runnable() {
235
+            @Override
236
+            public void run() {
237
+                currentActivity.setSideMenuVisible(animated, visible);
238
+            }
239
+        });
240
+    }
213
 }
241
 }

+ 77
- 11
android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java Ver fichero

1
 package com.reactnativenavigation.layouts;
1
 package com.reactnativenavigation.layouts;
2
 
2
 
3
 import android.support.annotation.NonNull;
3
 import android.support.annotation.NonNull;
4
+import android.support.annotation.Nullable;
4
 import android.support.v7.app.AppCompatActivity;
5
 import android.support.v7.app.AppCompatActivity;
5
 import android.view.View;
6
 import android.view.View;
6
 import android.widget.RelativeLayout;
7
 import android.widget.RelativeLayout;
8
 import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
9
 import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
9
 import com.reactnativenavigation.params.ActivityParams;
10
 import com.reactnativenavigation.params.ActivityParams;
10
 import com.reactnativenavigation.params.ScreenParams;
11
 import com.reactnativenavigation.params.ScreenParams;
12
+import com.reactnativenavigation.params.SideMenuParams;
11
 import com.reactnativenavigation.params.TitleBarButtonParams;
13
 import com.reactnativenavigation.params.TitleBarButtonParams;
12
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
14
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
13
 import com.reactnativenavigation.screens.ScreenStack;
15
 import com.reactnativenavigation.screens.ScreenStack;
14
 import com.reactnativenavigation.views.BottomTabs;
16
 import com.reactnativenavigation.views.BottomTabs;
17
+import com.reactnativenavigation.views.SideMenu;
15
 
18
 
16
 import java.util.List;
19
 import java.util.List;
17
 
20
 
24
     private ActivityParams params;
27
     private ActivityParams params;
25
     private BottomTabs bottomTabs;
28
     private BottomTabs bottomTabs;
26
     private ScreenStack[] screenStacks;
29
     private ScreenStack[] screenStacks;
30
+    private final SideMenuParams sideMenuParams;
31
+    private @Nullable SideMenu sideMenu;
27
     private int currentStackIndex = 0;
32
     private int currentStackIndex = 0;
28
 
33
 
29
     public BottomTabsLayout(AppCompatActivity activity, ActivityParams params) {
34
     public BottomTabsLayout(AppCompatActivity activity, ActivityParams params) {
30
         super(activity);
35
         super(activity);
31
         this.activity = activity;
36
         this.activity = activity;
32
         this.params = params;
37
         this.params = params;
38
+        this.sideMenuParams = params.sideMenuParams;
33
         screenStacks = new ScreenStack[params.tabParams.size()];
39
         screenStacks = new ScreenStack[params.tabParams.size()];
34
         createLayout();
40
         createLayout();
35
     }
41
     }
36
 
42
 
37
     private void createLayout() {
43
     private void createLayout() {
44
+        createSideMenu();
38
         createBottomTabs();
45
         createBottomTabs();
39
-        addBottomTabsToScreen();
46
+        addBottomTabs();
40
         addScreenStacks();
47
         addScreenStacks();
41
         showInitialScreenStack();
48
         showInitialScreenStack();
42
     }
49
     }
43
 
50
 
51
+    private void createSideMenu() {
52
+        if (sideMenuParams == null) {
53
+            return;
54
+        }
55
+        sideMenu = new SideMenu(getContext(), sideMenuParams);
56
+        RelativeLayout.LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
57
+        addView(sideMenu, lp);
58
+    }
59
+
44
     private void addScreenStacks() {
60
     private void addScreenStacks() {
45
         for (int i = 0; i < screenStacks.length; i++) {
61
         for (int i = 0; i < screenStacks.length; i++) {
46
             createAndAddScreens(i);
62
             createAndAddScreens(i);
48
     }
64
     }
49
 
65
 
50
     private void createAndAddScreens(int position) {
66
     private void createAndAddScreens(int position) {
51
-        ScreenStack newStack = new ScreenStack(activity, this, this);
52
         ScreenParams screenParams = params.tabParams.get(position);
67
         ScreenParams screenParams = params.tabParams.get(position);
68
+        ScreenStack newStack = new ScreenStack(activity, getScreenStackParent(), screenParams.navigatorId, this);
53
         newStack.pushInitialScreen(screenParams, createScreenLayoutParams(screenParams));
69
         newStack.pushInitialScreen(screenParams, createScreenLayoutParams(screenParams));
54
         screenStacks[position] = newStack;
70
         screenStacks[position] = newStack;
55
     }
71
     }
56
 
72
 
73
+    private RelativeLayout getScreenStackParent() {
74
+        return sideMenu == null ? this : sideMenu.getContentContainer();
75
+    }
76
+
57
     @NonNull
77
     @NonNull
58
     private LayoutParams createScreenLayoutParams(ScreenParams params) {
78
     private LayoutParams createScreenLayoutParams(ScreenParams params) {
59
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
79
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
68
         bottomTabs.addTabs(params.tabParams, this);
88
         bottomTabs.addTabs(params.tabParams, this);
69
     }
89
     }
70
 
90
 
71
-    private void addBottomTabsToScreen() {
91
+    private void addBottomTabs() {
72
         LayoutParams lp = new LayoutParams(MATCH_PARENT, WRAP_CONTENT);
92
         LayoutParams lp = new LayoutParams(MATCH_PARENT, WRAP_CONTENT);
73
         lp.addRule(ALIGN_PARENT_BOTTOM);
93
         lp.addRule(ALIGN_PARENT_BOTTOM);
74
-        addView(bottomTabs, lp);
94
+        getScreenStackParent().addView(bottomTabs, lp);
75
     }
95
     }
76
 
96
 
77
     private void showInitialScreenStack() {
97
     private void showInitialScreenStack() {
126
         }
146
         }
127
     }
147
     }
128
 
148
 
149
+    @Override
150
+    public void toggleSideMenuVisible(boolean animated) {
151
+        if (sideMenu != null) {
152
+            sideMenu.toggleVisible(animated);
153
+        }
154
+    }
155
+
156
+    @Override
157
+    public void setSideMenuVisible(boolean animated, boolean visible) {
158
+        if (sideMenu != null) {
159
+            sideMenu.setVisible(visible, animated);
160
+        }
161
+    }
162
+
129
     @Override
163
     @Override
130
     public void push(ScreenParams screenParams) {
164
     public void push(ScreenParams screenParams) {
131
-        getCurrentScreenStack().push(screenParams, createScreenLayoutParams(screenParams));
132
-        bottomTabs.setStyleFromScreen(screenParams.styleParams);
165
+        ScreenStack screenStack = getScreenStack(screenParams.navigatorId);
166
+        if (screenStack == null) {
167
+            return;
168
+        }
169
+
170
+        if (isCurrentStack(screenStack)) {
171
+            screenStack.push(screenParams, createScreenLayoutParams(screenParams));
172
+            bottomTabs.setStyleFromScreen(screenParams.styleParams);
173
+        } else {
174
+            screenStack.push(screenParams, createScreenLayoutParams(screenParams));
175
+        }
133
     }
176
     }
134
 
177
 
135
     @Override
178
     @Override
154
         currentScreenStack.destroy();
197
         currentScreenStack.destroy();
155
         removeView(currentScreenStack.peek());
198
         removeView(currentScreenStack.peek());
156
 
199
 
157
-        ScreenStack newStack = new ScreenStack(activity, this, this);
200
+        ScreenStack newStack = new ScreenStack(activity, getScreenStackParent(), params.navigatorId, this);
158
         LayoutParams lp = createScreenLayoutParams(params);
201
         LayoutParams lp = createScreenLayoutParams(params);
159
         newStack.pushInitialScreen(params, lp);
202
         newStack.pushInitialScreen(params, lp);
160
         screenStacks[currentStackIndex] = newStack;
203
         screenStacks[currentStackIndex] = newStack;
167
         for (ScreenStack screenStack : screenStacks) {
210
         for (ScreenStack screenStack : screenStacks) {
168
             screenStack.destroy();
211
             screenStack.destroy();
169
         }
212
         }
213
+
214
+        if (sideMenu != null) {
215
+            sideMenu.destroy();
216
+        }
170
     }
217
     }
171
 
218
 
172
     @Override
219
     @Override
181
     }
228
     }
182
 
229
 
183
     private void showStackAndUpdateStyle(ScreenStack newStack) {
230
     private void showStackAndUpdateStyle(ScreenStack newStack) {
184
-        newStack.showFirstScreen();
231
+        newStack.show();
185
         bottomTabs.setStyleFromScreen(newStack.getCurrentScreenStyleParams());
232
         bottomTabs.setStyleFromScreen(newStack.getCurrentScreenStyleParams());
186
     }
233
     }
187
 
234
 
188
     private void hideCurrentStack() {
235
     private void hideCurrentStack() {
189
         ScreenStack currentScreenStack = getCurrentScreenStack();
236
         ScreenStack currentScreenStack = getCurrentScreenStack();
190
-        currentScreenStack.hideScreen();
237
+        currentScreenStack.hide();
191
     }
238
     }
192
 
239
 
193
     private ScreenStack getCurrentScreenStack() {
240
     private ScreenStack getCurrentScreenStack() {
194
         return screenStacks[currentStackIndex];
241
         return screenStacks[currentStackIndex];
195
     }
242
     }
196
 
243
 
244
+    private @Nullable ScreenStack getScreenStack(String navigatorId) {
245
+        for (ScreenStack screenStack : screenStacks) {
246
+            if (screenStack.getNavigatorId().equals(navigatorId)) {
247
+                return screenStack;
248
+            }
249
+        }
250
+        return null;
251
+    }
252
+
253
+    private boolean isCurrentStack(ScreenStack screenStack) {
254
+        return getCurrentScreenStack() == screenStack;
255
+    }
256
+
197
     private void setBottomTabsStyleFromCurrentScreen() {
257
     private void setBottomTabsStyleFromCurrentScreen() {
198
         bottomTabs.setStyleFromScreen(getCurrentScreenStack().getCurrentScreenStyleParams());
258
         bottomTabs.setStyleFromScreen(getCurrentScreenStack().getCurrentScreenStyleParams());
199
     }
259
     }
200
 
260
 
201
     @Override
261
     @Override
202
-    public boolean onTitleBarBackPress() {
262
+    public boolean onTitleBarBackButtonClick() {
203
         if (getCurrentScreenStack().canPop()) {
263
         if (getCurrentScreenStack().canPop()) {
204
             getCurrentScreenStack().pop(true, new ScreenStack.OnScreenPop() {
264
             getCurrentScreenStack().pop(true, new ScreenStack.OnScreenPop() {
205
                 @Override
265
                 @Override
209
             });
269
             });
210
             return true;
270
             return true;
211
         }
271
         }
212
-
213
         return false;
272
         return false;
214
     }
273
     }
274
+
275
+    @Override
276
+    public void onSideMenuButtonClick() {
277
+        if (sideMenu != null) {
278
+            sideMenu.openDrawer();
279
+        }
280
+    }
215
 }
281
 }

+ 4
- 0
android/app/src/main/java/com/reactnativenavigation/layouts/Layout.java Ver fichero

19
     void setTitleBarRightButtons(String screenInstanceId, String navigatorEventId, List<TitleBarButtonParams> titleBarButtons);
19
     void setTitleBarRightButtons(String screenInstanceId, String navigatorEventId, List<TitleBarButtonParams> titleBarButtons);
20
 
20
 
21
     void setTitleBarLeftButton(String screenInstanceId, String navigatorEventId, TitleBarLeftButtonParams titleBarLeftButtonParams);
21
     void setTitleBarLeftButton(String screenInstanceId, String navigatorEventId, TitleBarLeftButtonParams titleBarLeftButtonParams);
22
+
23
+    void toggleSideMenuVisible(boolean animated);
24
+
25
+    void setSideMenuVisible(boolean animated, boolean visible);
22
 }
26
 }

+ 3
- 2
android/app/src/main/java/com/reactnativenavigation/layouts/LayoutFactory.java Ver fichero

1
 package com.reactnativenavigation.layouts;
1
 package com.reactnativenavigation.layouts;
2
 
2
 
3
 import android.support.v7.app.AppCompatActivity;
3
 import android.support.v7.app.AppCompatActivity;
4
+import android.util.Log;
4
 
5
 
5
 import com.reactnativenavigation.params.ActivityParams;
6
 import com.reactnativenavigation.params.ActivityParams;
6
 
7
 
16
     }
17
     }
17
 
18
 
18
     private static Layout createSingleScreenLayout(AppCompatActivity activity, ActivityParams params) {
19
     private static Layout createSingleScreenLayout(AppCompatActivity activity, ActivityParams params) {
19
-        return new SingleScreenLayout(activity, params.screenParams);
20
+        return new SingleScreenLayout(activity, params.sideMenuParams, params.screenParams);
20
     }
21
     }
21
 
22
 
22
     private static Layout createBottomTabsScreenLayout(AppCompatActivity activity, ActivityParams params) {
23
     private static Layout createBottomTabsScreenLayout(AppCompatActivity activity, ActivityParams params) {
27
     }
28
     }
28
 
29
 
29
     private static void removeAllButTheFirst5Tabs(ActivityParams params) {
30
     private static void removeAllButTheFirst5Tabs(ActivityParams params) {
30
-        android.util.Log.e("LOG", "LayoutFactory:createBottomTabsScreenLayout() does not support more than 5 tabs, currently");
31
+        Log.e("Navigation", "LayoutFactory:createBottomTabsScreenLayout() does not support more than 5 tabs, currently");
31
         while (params.tabParams.size() > 5) {
32
         while (params.tabParams.size() > 5) {
32
             params.tabParams.remove(params.tabParams.size() - 1);
33
             params.tabParams.remove(params.tabParams.size() - 1);
33
         }
34
         }

+ 2
- 2
android/app/src/main/java/com/reactnativenavigation/layouts/ScreenStackContainer.java Ver fichero

1
 package com.reactnativenavigation.layouts;
1
 package com.reactnativenavigation.layouts;
2
 
2
 
3
 import com.reactnativenavigation.params.ScreenParams;
3
 import com.reactnativenavigation.params.ScreenParams;
4
-import com.reactnativenavigation.views.TitleBarBackButtonListener;
4
+import com.reactnativenavigation.views.LeftButtonOnClickListener;
5
 
5
 
6
-public interface ScreenStackContainer extends TitleBarBackButtonListener {
6
+public interface ScreenStackContainer extends LeftButtonOnClickListener {
7
     void push(ScreenParams screenParams);
7
     void push(ScreenParams screenParams);
8
 
8
 
9
     void pop(ScreenParams screenParams);
9
     void pop(ScreenParams screenParams);

+ 66
- 18
android/app/src/main/java/com/reactnativenavigation/layouts/SingleScreenLayout.java Ver fichero

1
 package com.reactnativenavigation.layouts;
1
 package com.reactnativenavigation.layouts;
2
 
2
 
3
+import android.support.annotation.Nullable;
3
 import android.support.v7.app.AppCompatActivity;
4
 import android.support.v7.app.AppCompatActivity;
4
 import android.view.View;
5
 import android.view.View;
5
 import android.widget.RelativeLayout;
6
 import android.widget.RelativeLayout;
6
 
7
 
7
 import com.reactnativenavigation.params.ScreenParams;
8
 import com.reactnativenavigation.params.ScreenParams;
9
+import com.reactnativenavigation.params.SideMenuParams;
8
 import com.reactnativenavigation.params.TitleBarButtonParams;
10
 import com.reactnativenavigation.params.TitleBarButtonParams;
9
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
11
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
10
-import com.reactnativenavigation.screens.ScreenAnimator;
11
 import com.reactnativenavigation.screens.ScreenStack;
12
 import com.reactnativenavigation.screens.ScreenStack;
12
-import com.reactnativenavigation.views.TitleBarBackButtonListener;
13
+import com.reactnativenavigation.views.LeftButtonOnClickListener;
14
+import com.reactnativenavigation.views.SideMenu;
13
 
15
 
14
 import java.util.List;
16
 import java.util.List;
15
 
17
 
18
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
19
+
16
 public class SingleScreenLayout extends RelativeLayout implements Layout {
20
 public class SingleScreenLayout extends RelativeLayout implements Layout {
17
 
21
 
18
     private final AppCompatActivity activity;
22
     private final AppCompatActivity activity;
19
     private final ScreenParams screenParams;
23
     private final ScreenParams screenParams;
24
+    private final SideMenuParams sideMenuParams;
20
     private ScreenStack stack;
25
     private ScreenStack stack;
21
-    private ScreenAnimator screenAnimator;
22
-    private TitleBarBackButtonListener titleBarBackButtonListener;
26
+    private LeftButtonOnClickListener leftButtonOnClickListener;
27
+    private @Nullable SideMenu sideMenu;
23
 
28
 
24
-    public SingleScreenLayout(AppCompatActivity activity, ScreenParams screenParams, TitleBarBackButtonListener titleBarBackButtonListener) {
25
-        this(activity, screenParams);
26
-        this.titleBarBackButtonListener = titleBarBackButtonListener;
29
+    public SingleScreenLayout(AppCompatActivity activity, ScreenParams screenParams,
30
+                              LeftButtonOnClickListener leftButtonOnClickListener) {
31
+        this(activity, null, screenParams);
32
+        this.leftButtonOnClickListener = leftButtonOnClickListener;
27
     }
33
     }
28
 
34
 
29
-    public SingleScreenLayout(AppCompatActivity activity, ScreenParams screenParams) {
35
+    public SingleScreenLayout(AppCompatActivity activity, @Nullable SideMenuParams sideMenuParams, ScreenParams screenParams) {
30
         super(activity);
36
         super(activity);
31
         this.activity = activity;
37
         this.activity = activity;
32
         this.screenParams = screenParams;
38
         this.screenParams = screenParams;
33
-        createStack();
39
+        this.sideMenuParams = sideMenuParams;
40
+        createLayout();
41
+    }
42
+
43
+    private void createLayout() {
44
+        if (sideMenuParams == null) {
45
+            createStack(this);
46
+        } else {
47
+            sideMenu = createSideMenu();
48
+            createStack(sideMenu.getContentContainer());
49
+        }
34
     }
50
     }
35
 
51
 
36
-    private void createStack() {
52
+    private SideMenu createSideMenu() {
53
+        SideMenu sideMenu = new SideMenu(getContext(), sideMenuParams);
54
+        RelativeLayout.LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
55
+        addView(sideMenu, lp);
56
+        return sideMenu;
57
+    }
58
+
59
+    private void createStack(RelativeLayout parent) {
37
         if (stack != null) {
60
         if (stack != null) {
38
             stack.destroy();
61
             stack.destroy();
39
         }
62
         }
40
-        stack = new ScreenStack(activity, this, this);
41
-        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
63
+        stack = new ScreenStack(activity, parent, screenParams.navigatorId, this);
64
+        LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
42
         stack.pushInitialScreen(screenParams, lp);
65
         stack.pushInitialScreen(screenParams, lp);
43
-        stack.showFirstScreen();
66
+        stack.show();
44
     }
67
     }
45
 
68
 
46
     @Override
69
     @Override
56
     @Override
79
     @Override
57
     public void destroy() {
80
     public void destroy() {
58
         stack.destroy();
81
         stack.destroy();
82
+        if (sideMenu != null) {
83
+            sideMenu.destroy();
84
+        }
59
     }
85
     }
60
 
86
 
61
     @Override
87
     @Override
62
     public void push(ScreenParams params) {
88
     public void push(ScreenParams params) {
63
-        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
89
+        LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
64
         stack.push(params, lp);
90
         stack.push(params, lp);
65
     }
91
     }
66
 
92
 
76
 
102
 
77
     @Override
103
     @Override
78
     public void newStack(ScreenParams params) {
104
     public void newStack(ScreenParams params) {
79
-        createStack();
105
+        RelativeLayout parent = sideMenu == null ? this : sideMenu.getContentContainer();
106
+        createStack(parent);
80
     }
107
     }
81
 
108
 
82
     @Override
109
     @Override
106
     }
133
     }
107
 
134
 
108
     @Override
135
     @Override
109
-    public boolean onTitleBarBackPress() {
110
-        if (titleBarBackButtonListener != null) {
111
-            return titleBarBackButtonListener.onTitleBarBackPress();
136
+    public void toggleSideMenuVisible(boolean animated) {
137
+        if (sideMenu != null) {
138
+            sideMenu.toggleVisible(animated);
139
+        }
140
+    }
141
+
142
+    @Override
143
+    public void setSideMenuVisible(boolean animated, boolean visible) {
144
+        if (sideMenu != null) {
145
+            sideMenu.setVisible(visible, animated);
146
+        }
147
+    }
148
+
149
+    @Override
150
+    public boolean onTitleBarBackButtonClick() {
151
+        if (leftButtonOnClickListener != null) {
152
+            return leftButtonOnClickListener.onTitleBarBackButtonClick();
112
         }
153
         }
113
 
154
 
114
         return onBackPressed();
155
         return onBackPressed();
115
     }
156
     }
157
+
158
+    @Override
159
+    public void onSideMenuButtonClick() {
160
+        if (sideMenu != null) {
161
+            sideMenu.openDrawer();
162
+        }
163
+    }
116
 }
164
 }

+ 1
- 0
android/app/src/main/java/com/reactnativenavigation/params/ActivityParams.java Ver fichero

10
     public Type type;
10
     public Type type;
11
     public ScreenParams screenParams;
11
     public ScreenParams screenParams;
12
     public List<ScreenParams> tabParams;
12
     public List<ScreenParams> tabParams;
13
+    public SideMenuParams sideMenuParams;
13
 }
14
 }

+ 1
- 0
android/app/src/main/java/com/reactnativenavigation/params/ScreenParams.java Ver fichero

21
 
21
 
22
     public String screenInstanceId;
22
     public String screenInstanceId;
23
     public String navigatorEventId;
23
     public String navigatorEventId;
24
+    public String navigatorId;
24
     public Bundle navigationParams;
25
     public Bundle navigationParams;
25
 
26
 
26
     public boolean hasTopTabs() {
27
     public boolean hasTopTabs() {

+ 9
- 0
android/app/src/main/java/com/reactnativenavigation/params/SideMenuParams.java Ver fichero

1
+package com.reactnativenavigation.params;
2
+
3
+import android.os.Bundle;
4
+
5
+public class SideMenuParams {
6
+    public String screenId;
7
+    public Bundle navigationParams;
8
+    public boolean disableOpenGesture;
9
+}

+ 4
- 0
android/app/src/main/java/com/reactnativenavigation/params/parsers/ActivityParamsParser.java Ver fichero

21
             result.tabParams = ScreenParamsParser.parseTabs(params.getBundle("tabs"));
21
             result.tabParams = ScreenParamsParser.parseTabs(params.getBundle("tabs"));
22
         }
22
         }
23
 
23
 
24
+        if (hasKey(params, "sideMenu")) {
25
+            result.sideMenuParams = SideMenuParamsParser.parse(params.getBundle("sideMenu"));
26
+        }
27
+
24
         return result;
28
         return result;
25
     }
29
     }
26
 }
30
 }

+ 2
- 0
android/app/src/main/java/com/reactnativenavigation/params/parsers/ScreenParamsParser.java Ver fichero

17
     private static final String KEY_SCREEN_ID = "screenId";
17
     private static final String KEY_SCREEN_ID = "screenId";
18
     private static final String KEY_SCREEN_INSTANCE_ID = "screenInstanceID";
18
     private static final String KEY_SCREEN_INSTANCE_ID = "screenInstanceID";
19
     private static final String KEY_NAVIGATOR_EVENT_ID = "navigatorEventID";
19
     private static final String KEY_NAVIGATOR_EVENT_ID = "navigatorEventID";
20
+    private static final String KEY_NAVIGATOR_ID = "navigatorID";
20
     private static final String KEY_NAVIGATION_PARAMS = "navigationParams";
21
     private static final String KEY_NAVIGATION_PARAMS = "navigationParams";
21
     private static final String KEY_RIGHT_BUTTONS = "rightButtons";
22
     private static final String KEY_RIGHT_BUTTONS = "rightButtons";
22
     private static final String KEY_LEFT_BUTTON = "leftButton";
23
     private static final String KEY_LEFT_BUTTON = "leftButton";
34
         assertKeyExists(params, KEY_NAVIGATION_PARAMS);
35
         assertKeyExists(params, KEY_NAVIGATION_PARAMS);
35
         result.navigationParams = params.getBundle(KEY_NAVIGATION_PARAMS);
36
         result.navigationParams = params.getBundle(KEY_NAVIGATION_PARAMS);
36
         result.navigatorEventId = result.navigationParams.getString(KEY_NAVIGATOR_EVENT_ID);
37
         result.navigatorEventId = result.navigationParams.getString(KEY_NAVIGATOR_EVENT_ID);
38
+        result.navigatorId = result.navigationParams.getString(KEY_NAVIGATOR_ID);
37
         result.screenInstanceId = result.navigationParams.getString(KEY_SCREEN_INSTANCE_ID);
39
         result.screenInstanceId = result.navigationParams.getString(KEY_SCREEN_INSTANCE_ID);
38
 
40
 
39
         result.styleParams = new StyleParamsParser(params.getBundle(STYLE_PARAMS)).parse();
41
         result.styleParams = new StyleParamsParser(params.getBundle(STYLE_PARAMS)).parse();

+ 16
- 0
android/app/src/main/java/com/reactnativenavigation/params/parsers/SideMenuParamsParser.java Ver fichero

1
+package com.reactnativenavigation.params.parsers;
2
+
3
+import android.os.Bundle;
4
+
5
+import com.reactnativenavigation.params.SideMenuParams;
6
+
7
+public class SideMenuParamsParser extends Parser {
8
+
9
+    public static SideMenuParams parse(Bundle sideMenu) {
10
+        SideMenuParams result = new SideMenuParams();
11
+        result.screenId = sideMenu.getString("screenId");
12
+        result.navigationParams = sideMenu.getBundle("navigationParams");
13
+        result.disableOpenGesture = sideMenu.getBoolean("disableOpenGesture", false);
14
+        return result;
15
+    }
16
+}

+ 3
- 3
android/app/src/main/java/com/reactnativenavigation/params/parsers/TitleBarLeftButtonParamsParser.java Ver fichero

8
 public class TitleBarLeftButtonParamsParser extends TitleBarButtonParamsParser {
8
 public class TitleBarLeftButtonParamsParser extends TitleBarButtonParamsParser {
9
 
9
 
10
     public TitleBarLeftButtonParams parseSingleButton(Bundle params) {
10
     public TitleBarLeftButtonParams parseSingleButton(Bundle params) {
11
-        TitleBarLeftButtonParams backButtonParams = new TitleBarLeftButtonParams(super.parseSingleButton(params));
12
-        backButtonParams.iconState = getIconStateFromId(backButtonParams.eventId);
13
-        return backButtonParams;
11
+        TitleBarLeftButtonParams leftButtonParams = new TitleBarLeftButtonParams(super.parseSingleButton(params));
12
+        leftButtonParams.iconState = getIconStateFromId(leftButtonParams.eventId);
13
+        return leftButtonParams;
14
     }
14
     }
15
 
15
 
16
     private MaterialMenuDrawable.IconState getIconStateFromId(String id) {
16
     private MaterialMenuDrawable.IconState getIconStateFromId(String id) {

+ 3
- 4
android/app/src/main/java/com/reactnativenavigation/screens/FragmentScreen.java Ver fichero

11
 import com.reactnativenavigation.R;
11
 import com.reactnativenavigation.R;
12
 import com.reactnativenavigation.params.ScreenParams;
12
 import com.reactnativenavigation.params.ScreenParams;
13
 import com.reactnativenavigation.views.ContentView;
13
 import com.reactnativenavigation.views.ContentView;
14
-import com.reactnativenavigation.views.TitleBarBackButtonListener;
14
+import com.reactnativenavigation.views.LeftButtonOnClickListener;
15
 
15
 
16
 import java.lang.reflect.InvocationTargetException;
16
 import java.lang.reflect.InvocationTargetException;
17
 import java.lang.reflect.Method;
17
 import java.lang.reflect.Method;
25
     private static final String CONTRACT_GET_SUPPORT_FRAGMENT = "getSupportFragment";
25
     private static final String CONTRACT_GET_SUPPORT_FRAGMENT = "getSupportFragment";
26
     private FrameLayout content;
26
     private FrameLayout content;
27
 
27
 
28
-    public FragmentScreen(AppCompatActivity activity, ScreenParams screenParams, TitleBarBackButtonListener titleBarBackButtonListener) {
29
-        super(activity, screenParams, titleBarBackButtonListener);
28
+    public FragmentScreen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener leftButtonOnClickListener) {
29
+        super(activity, screenParams, leftButtonOnClickListener);
30
     }
30
     }
31
 
31
 
32
     @Override
32
     @Override
40
     private void addContent() {
40
     private void addContent() {
41
         ContentView contentView = new ContentView(getContext(),
41
         ContentView contentView = new ContentView(getContext(),
42
                 screenParams.screenId,
42
                 screenParams.screenId,
43
-                screenParams.navigatorEventId,
44
                 screenParams.navigationParams);
43
                 screenParams.navigationParams);
45
         addView(contentView, 0, 0);
44
         addView(contentView, 0, 0);
46
         LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
45
         LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);

+ 6
- 6
android/app/src/main/java/com/reactnativenavigation/screens/Screen.java Ver fichero

14
 import com.reactnativenavigation.params.TitleBarButtonParams;
14
 import com.reactnativenavigation.params.TitleBarButtonParams;
15
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
15
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
16
 import com.reactnativenavigation.utils.ViewUtils;
16
 import com.reactnativenavigation.utils.ViewUtils;
17
-import com.reactnativenavigation.views.TitleBarBackButtonListener;
17
+import com.reactnativenavigation.views.LeftButtonOnClickListener;
18
 import com.reactnativenavigation.views.TopBar;
18
 import com.reactnativenavigation.views.TopBar;
19
 
19
 
20
 import java.util.List;
20
 import java.util.List;
27
     protected final AppCompatActivity activity;
27
     protected final AppCompatActivity activity;
28
     protected final ScreenParams screenParams;
28
     protected final ScreenParams screenParams;
29
     protected TopBar topBar;
29
     protected TopBar topBar;
30
-    private final TitleBarBackButtonListener titleBarBackButtonListener;
30
+    private final LeftButtonOnClickListener leftButtonOnClickListener;
31
     private VisibilityAnimator topBarVisibilityAnimator;
31
     private VisibilityAnimator topBarVisibilityAnimator;
32
     private ScreenAnimator screenAnimator;
32
     private ScreenAnimator screenAnimator;
33
 
33
 
34
-    public Screen(AppCompatActivity activity, ScreenParams screenParams, TitleBarBackButtonListener titleBarBackButtonListener) {
34
+    public Screen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener leftButtonOnClickListener) {
35
         super(activity);
35
         super(activity);
36
         this.activity = activity;
36
         this.activity = activity;
37
         this.screenParams = screenParams;
37
         this.screenParams = screenParams;
38
-        this.titleBarBackButtonListener = titleBarBackButtonListener;
38
+        this.leftButtonOnClickListener = leftButtonOnClickListener;
39
 
39
 
40
         screenAnimator = new ScreenAnimator(this);
40
         screenAnimator = new ScreenAnimator(this);
41
         createViews();
41
         createViews();
61
             screenParams.leftButton.setColorFromScreenStyle(screenParams.styleParams.titleBarButtonColor);
61
             screenParams.leftButton.setColorFromScreenStyle(screenParams.styleParams.titleBarButtonColor);
62
         }
62
         }
63
         topBar.addTitleBarAndSetButtons(screenParams.rightButtons, screenParams.leftButton,
63
         topBar.addTitleBarAndSetButtons(screenParams.rightButtons, screenParams.leftButton,
64
-                titleBarBackButtonListener, screenParams.navigatorEventId);
64
+                leftButtonOnClickListener, screenParams.navigatorEventId);
65
     }
65
     }
66
 
66
 
67
     private void createTopBar() {
67
     private void createTopBar() {
138
         topBar.setTitleBarRightButtons(navigatorEventId, titleBarButtons);
138
         topBar.setTitleBarRightButtons(navigatorEventId, titleBarButtons);
139
     }
139
     }
140
 
140
 
141
-    public void setTitleBarLeftButton(String navigatorEventId, TitleBarBackButtonListener backButtonListener,
141
+    public void setTitleBarLeftButton(String navigatorEventId, LeftButtonOnClickListener backButtonListener,
142
                                       TitleBarLeftButtonParams titleBarLeftButtonParams) {
142
                                       TitleBarLeftButtonParams titleBarLeftButtonParams) {
143
         topBar.setTitleBarRightButton(navigatorEventId, backButtonListener, titleBarLeftButtonParams);
143
         topBar.setTitleBarRightButton(navigatorEventId, backButtonListener, titleBarLeftButtonParams);
144
     }
144
     }

+ 5
- 5
android/app/src/main/java/com/reactnativenavigation/screens/ScreenFactory.java Ver fichero

3
 import android.support.v7.app.AppCompatActivity;
3
 import android.support.v7.app.AppCompatActivity;
4
 
4
 
5
 import com.reactnativenavigation.params.ScreenParams;
5
 import com.reactnativenavigation.params.ScreenParams;
6
-import com.reactnativenavigation.views.TitleBarBackButtonListener;
6
+import com.reactnativenavigation.views.LeftButtonOnClickListener;
7
 
7
 
8
 public class ScreenFactory {
8
 public class ScreenFactory {
9
     public static Screen create(AppCompatActivity activity,
9
     public static Screen create(AppCompatActivity activity,
10
                                 ScreenParams screenParams,
10
                                 ScreenParams screenParams,
11
-                                TitleBarBackButtonListener titleBarBackButtonListener) {
11
+                                LeftButtonOnClickListener leftButtonOnClickListener) {
12
         if (screenParams.isFragmentScreen()) {
12
         if (screenParams.isFragmentScreen()) {
13
-            return new FragmentScreen(activity, screenParams, titleBarBackButtonListener);
13
+            return new FragmentScreen(activity, screenParams, leftButtonOnClickListener);
14
         } else if (screenParams.hasTopTabs()) {
14
         } else if (screenParams.hasTopTabs()) {
15
-            return new ViewPagerScreen(activity, screenParams, titleBarBackButtonListener);
15
+            return new ViewPagerScreen(activity, screenParams, leftButtonOnClickListener);
16
         } else {
16
         } else {
17
-            return new SingleScreen(activity, screenParams, titleBarBackButtonListener);
17
+            return new SingleScreen(activity, screenParams, leftButtonOnClickListener);
18
         }
18
         }
19
     }
19
     }
20
 }
20
 }

+ 36
- 9
android/app/src/main/java/com/reactnativenavigation/screens/ScreenStack.java Ver fichero

11
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
11
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
12
 import com.reactnativenavigation.utils.KeyboardVisibilityDetector;
12
 import com.reactnativenavigation.utils.KeyboardVisibilityDetector;
13
 import com.reactnativenavigation.utils.Task;
13
 import com.reactnativenavigation.utils.Task;
14
-import com.reactnativenavigation.views.TitleBarBackButtonListener;
14
+import com.reactnativenavigation.views.LeftButtonOnClickListener;
15
 
15
 
16
 import java.util.List;
16
 import java.util.List;
17
 import java.util.Stack;
17
 import java.util.Stack;
24
 
24
 
25
     private final AppCompatActivity activity;
25
     private final AppCompatActivity activity;
26
     private RelativeLayout parent;
26
     private RelativeLayout parent;
27
-    private TitleBarBackButtonListener titleBarBackButtonListener;
27
+    private LeftButtonOnClickListener leftButtonOnClickListener;
28
     private Stack<Screen> stack = new Stack<>();
28
     private Stack<Screen> stack = new Stack<>();
29
     private final KeyboardVisibilityDetector keyboardVisibilityDetector;
29
     private final KeyboardVisibilityDetector keyboardVisibilityDetector;
30
+    private boolean isStackVisible = false;
31
+    private final String navigatorId;
32
+
33
+    public String getNavigatorId() {
34
+        return navigatorId;
35
+    }
30
 
36
 
31
     public ScreenStack(AppCompatActivity activity,
37
     public ScreenStack(AppCompatActivity activity,
32
                        RelativeLayout parent,
38
                        RelativeLayout parent,
33
-                       TitleBarBackButtonListener titleBarBackButtonListener) {
39
+                       String navigatorId,
40
+                       LeftButtonOnClickListener leftButtonOnClickListener) {
34
         this.activity = activity;
41
         this.activity = activity;
35
         this.parent = parent;
42
         this.parent = parent;
36
-        this.titleBarBackButtonListener = titleBarBackButtonListener;
43
+        this.navigatorId = navigatorId;
44
+        this.leftButtonOnClickListener = leftButtonOnClickListener;
37
         keyboardVisibilityDetector = new KeyboardVisibilityDetector(parent);
45
         keyboardVisibilityDetector = new KeyboardVisibilityDetector(parent);
38
     }
46
     }
39
 
47
 
40
     public void pushInitialScreen(ScreenParams initialScreenParams, RelativeLayout.LayoutParams params) {
48
     public void pushInitialScreen(ScreenParams initialScreenParams, RelativeLayout.LayoutParams params) {
41
-        Screen initialScreen = ScreenFactory.create(activity, initialScreenParams, titleBarBackButtonListener);
49
+        Screen initialScreen = ScreenFactory.create(activity, initialScreenParams, leftButtonOnClickListener);
42
         initialScreen.setVisibility(View.INVISIBLE);
50
         initialScreen.setVisibility(View.INVISIBLE);
43
         addScreen(initialScreen, params);
51
         addScreen(initialScreen, params);
44
     }
52
     }
45
 
53
 
46
     public void push(final ScreenParams params, RelativeLayout.LayoutParams layoutParams) {
54
     public void push(final ScreenParams params, RelativeLayout.LayoutParams layoutParams) {
47
-        Screen nextScreen = ScreenFactory.create(activity, params, titleBarBackButtonListener);
55
+        Screen nextScreen = ScreenFactory.create(activity, params, leftButtonOnClickListener);
48
         final Screen previousScreen = stack.peek();
56
         final Screen previousScreen = stack.peek();
57
+        if (isStackVisible) {
58
+            pushScreenToVisibleStack(params, layoutParams, nextScreen, previousScreen);
59
+        } else {
60
+            pushScreenToInvisibleStack(layoutParams, nextScreen, previousScreen);
61
+        }
62
+    }
63
+
64
+    private void pushScreenToVisibleStack(ScreenParams params, RelativeLayout.LayoutParams layoutParams,
65
+                                          Screen nextScreen, final Screen previousScreen) {
49
         addScreen(nextScreen, layoutParams);
66
         addScreen(nextScreen, layoutParams);
50
         nextScreen.show(params.animateScreenTransitions, new Runnable() {
67
         nextScreen.show(params.animateScreenTransitions, new Runnable() {
51
             @Override
68
             @Override
55
         });
72
         });
56
     }
73
     }
57
 
74
 
75
+    private void pushScreenToInvisibleStack(RelativeLayout.LayoutParams layoutParams, Screen nextScreen,
76
+                                            Screen previousScreen) {
77
+        nextScreen.setVisibility(View.INVISIBLE);
78
+        addScreen(nextScreen, layoutParams);
79
+        removePreviousWithoutUnmount(previousScreen);
80
+    }
81
+
58
     private void addScreen(Screen screen, RelativeLayout.LayoutParams layoutParams) {
82
     private void addScreen(Screen screen, RelativeLayout.LayoutParams layoutParams) {
59
         parent.addView(screen, layoutParams);
83
         parent.addView(screen, layoutParams);
60
         stack.push(screen);
84
         stack.push(screen);
109
     }
133
     }
110
 
134
 
111
     private void readdPrevious(Screen previous) {
135
     private void readdPrevious(Screen previous) {
136
+        previous.setVisibility(View.VISIBLE);
112
         parent.addView(previous, 0);
137
         parent.addView(previous, 0);
113
         previous.preventMountAfterReattachedToWindow();
138
         previous.preventMountAfterReattachedToWindow();
114
     }
139
     }
166
         performOnScreen(screenInstanceId, new Task<Screen>() {
191
         performOnScreen(screenInstanceId, new Task<Screen>() {
167
             @Override
192
             @Override
168
             public void run(Screen param) {
193
             public void run(Screen param) {
169
-                param.setTitleBarLeftButton(navigatorEventId, titleBarBackButtonListener, titleBarLeftButtonParams);
194
+                param.setTitleBarLeftButton(navigatorEventId, leftButtonOnClickListener, titleBarLeftButtonParams);
170
             }
195
             }
171
         });
196
         });
172
     }
197
     }
188
         }
213
         }
189
     }
214
     }
190
 
215
 
191
-    public void showFirstScreen() {
216
+    public void show() {
217
+        isStackVisible = true;
192
         stack.peek().setVisibility(View.VISIBLE);
218
         stack.peek().setVisibility(View.VISIBLE);
193
     }
219
     }
194
 
220
 
195
-    public void hideScreen() {
221
+    public void hide() {
222
+        isStackVisible = false;
196
         stack.peek().setVisibility(View.INVISIBLE);
223
         stack.peek().setVisibility(View.INVISIBLE);
197
     }
224
     }
198
 }
225
 }

+ 3
- 3
android/app/src/main/java/com/reactnativenavigation/screens/SingleScreen.java Ver fichero

4
 
4
 
5
 import com.reactnativenavigation.params.ScreenParams;
5
 import com.reactnativenavigation.params.ScreenParams;
6
 import com.reactnativenavigation.views.ContentView;
6
 import com.reactnativenavigation.views.ContentView;
7
-import com.reactnativenavigation.views.TitleBarBackButtonListener;
7
+import com.reactnativenavigation.views.LeftButtonOnClickListener;
8
 
8
 
9
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
9
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
10
 
10
 
13
     private ContentView contentView;
13
     private ContentView contentView;
14
 
14
 
15
     public SingleScreen(AppCompatActivity activity, ScreenParams screenParams,
15
     public SingleScreen(AppCompatActivity activity, ScreenParams screenParams,
16
-                        TitleBarBackButtonListener titleBarBarBackButtonListener) {
16
+                        LeftButtonOnClickListener titleBarBarBackButtonListener) {
17
         super(activity, screenParams, titleBarBarBackButtonListener);
17
         super(activity, screenParams, titleBarBarBackButtonListener);
18
     }
18
     }
19
 
19
 
20
     @Override
20
     @Override
21
     protected void createContent() {
21
     protected void createContent() {
22
-        contentView = new ContentView(getContext(), screenParams.screenId, screenParams.navigatorEventId, screenParams.navigationParams);
22
+        contentView = new ContentView(getContext(), screenParams.screenId, screenParams.navigationParams);
23
         LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
23
         LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
24
         if (screenParams.styleParams.drawScreenBelowTopBar) {
24
         if (screenParams.styleParams.drawScreenBelowTopBar) {
25
             params.addRule(BELOW, topBar.getId());
25
             params.addRule(BELOW, topBar.getId());

+ 3
- 3
android/app/src/main/java/com/reactnativenavigation/screens/ViewPagerScreen.java Ver fichero

7
 import com.reactnativenavigation.params.ScreenParams;
7
 import com.reactnativenavigation.params.ScreenParams;
8
 import com.reactnativenavigation.params.TopTabParams;
8
 import com.reactnativenavigation.params.TopTabParams;
9
 import com.reactnativenavigation.views.ContentView;
9
 import com.reactnativenavigation.views.ContentView;
10
-import com.reactnativenavigation.views.TitleBarBackButtonListener;
10
+import com.reactnativenavigation.views.LeftButtonOnClickListener;
11
 
11
 
12
 import java.util.ArrayList;
12
 import java.util.ArrayList;
13
 import java.util.List;
13
 import java.util.List;
20
     private List<ContentView> contentViews;
20
     private List<ContentView> contentViews;
21
     private ViewPager viewPager;
21
     private ViewPager viewPager;
22
 
22
 
23
-    public ViewPagerScreen(AppCompatActivity activity, ScreenParams screenParams, TitleBarBackButtonListener backButtonListener) {
23
+    public ViewPagerScreen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener backButtonListener) {
24
         super(activity, screenParams, backButtonListener);
24
         super(activity, screenParams, backButtonListener);
25
     }
25
     }
26
 
26
 
45
     private void addPages() {
45
     private void addPages() {
46
         contentViews = new ArrayList<>();
46
         contentViews = new ArrayList<>();
47
         for (TopTabParams tab : screenParams.topTabParams) {
47
         for (TopTabParams tab : screenParams.topTabParams) {
48
-            ContentView contentView = new ContentView(getContext(), tab.screenId, screenParams.navigatorEventId, tab.navigationParams);
48
+            ContentView contentView = new ContentView(getContext(), tab.screenId, tab.navigationParams, screenParams.navigatorEventId);
49
             addContent(contentView);
49
             addContent(contentView);
50
             contentViews.add(contentView);
50
             contentViews.add(contentView);
51
         }
51
         }

+ 6
- 2
android/app/src/main/java/com/reactnativenavigation/views/ContentView.java Ver fichero

10
 public class ContentView extends ReactRootView {
10
 public class ContentView extends ReactRootView {
11
 
11
 
12
     private final String screenId;
12
     private final String screenId;
13
-    private final String navigatorEventId;
13
+    private String navigatorEventId;
14
     private final Bundle navigationParams;
14
     private final Bundle navigationParams;
15
 
15
 
16
-    public ContentView(Context context, String screenId, String navigatorEventId, Bundle navigationParams) {
16
+    public ContentView(Context context, String screenId, Bundle navigationParams) {
17
+        this(context, screenId, navigationParams, null);
18
+    }
19
+
20
+    public ContentView(Context context, String screenId, Bundle navigationParams, String navigatorEventId) {
17
         super(context);
21
         super(context);
18
         this.screenId = screenId;
22
         this.screenId = screenId;
19
         this.navigatorEventId = navigatorEventId;
23
         this.navigatorEventId = navigatorEventId;

+ 10
- 4
android/app/src/main/java/com/reactnativenavigation/views/LeftButton.java Ver fichero

19
     }
19
     }
20
 
20
 
21
     private TitleBarLeftButtonParams params;
21
     private TitleBarLeftButtonParams params;
22
-    private final TitleBarBackButtonListener titleBarBackButtonListener;
22
+    private final LeftButtonOnClickListener onClickListener;
23
     private final String navigatorEventId;
23
     private final String navigatorEventId;
24
 
24
 
25
     public LeftButton(Context context,
25
     public LeftButton(Context context,
26
                       TitleBarLeftButtonParams params,
26
                       TitleBarLeftButtonParams params,
27
-                      TitleBarBackButtonListener titleBarBackButtonListener,
27
+                      LeftButtonOnClickListener onClickListener,
28
                       String navigatorEventId) {
28
                       String navigatorEventId) {
29
         super(context, getColor(params), Stroke.THIN);
29
         super(context, getColor(params), Stroke.THIN);
30
         this.params = params;
30
         this.params = params;
31
-        this.titleBarBackButtonListener = titleBarBackButtonListener;
31
+        this.onClickListener = onClickListener;
32
         this.navigatorEventId = navigatorEventId;
32
         this.navigatorEventId = navigatorEventId;
33
         setInitialState();
33
         setInitialState();
34
     }
34
     }
44
     @Override
44
     @Override
45
     public void onClick(View v) {
45
     public void onClick(View v) {
46
         if (isBackButton()) {
46
         if (isBackButton()) {
47
-            titleBarBackButtonListener.onTitleBarBackPress();
47
+            onClickListener.onTitleBarBackButtonClick();
48
+        } else if (isSideMenuButton()) {
49
+            onClickListener.onSideMenuButtonClick();
48
         } else {
50
         } else {
49
             sendClickEvent();
51
             sendClickEvent();
50
         }
52
         }
62
         return getIconState() == IconState.ARROW;
64
         return getIconState() == IconState.ARROW;
63
     }
65
     }
64
 
66
 
67
+    private boolean isSideMenuButton() {
68
+        return getIconState() == IconState.BURGER;
69
+    }
70
+
65
     private void sendClickEvent() {
71
     private void sendClickEvent() {
66
         NavigationApplication.instance.sendNavigatorEvent(params.eventId, navigatorEventId);
72
         NavigationApplication.instance.sendNavigatorEvent(params.eventId, navigatorEventId);
67
     }
73
     }

+ 7
- 0
android/app/src/main/java/com/reactnativenavigation/views/LeftButtonOnClickListener.java Ver fichero

1
+package com.reactnativenavigation.views;
2
+
3
+public interface LeftButtonOnClickListener {
4
+    boolean onTitleBarBackButtonClick();
5
+
6
+    void onSideMenuButtonClick();
7
+}

+ 74
- 0
android/app/src/main/java/com/reactnativenavigation/views/SideMenu.java Ver fichero

1
+package com.reactnativenavigation.views;
2
+
3
+import android.content.Context;
4
+import android.support.v4.widget.DrawerLayout;
5
+import android.view.Gravity;
6
+import android.widget.RelativeLayout;
7
+
8
+import com.reactnativenavigation.params.SideMenuParams;
9
+import com.reactnativenavigation.utils.ViewUtils;
10
+
11
+public class SideMenu extends DrawerLayout {
12
+
13
+    private ContentView sideMenuView;
14
+    private RelativeLayout contentContainer;
15
+
16
+    public RelativeLayout getContentContainer() {
17
+        return contentContainer;
18
+    }
19
+
20
+    public void destroy() {
21
+        sideMenuView.ensureUnmountOnDetachedFromWindow();
22
+        removeView(sideMenuView);
23
+    }
24
+
25
+    public void setVisible(boolean visible, boolean animated) {
26
+        if (!isShown() && visible) {
27
+            openDrawer(animated);
28
+        }
29
+
30
+        if (isShown() && !visible) {
31
+            closeDrawer(animated);
32
+        }
33
+    }
34
+
35
+    public void openDrawer() {
36
+        openDrawer(Gravity.LEFT);
37
+    }
38
+
39
+    public void openDrawer(boolean animated) {
40
+        openDrawer(Gravity.LEFT, animated);
41
+    }
42
+
43
+    public void closeDrawer(boolean animated) {
44
+        closeDrawer(Gravity.LEFT, animated);
45
+    }
46
+
47
+    public void toggleVisible(boolean animated) {
48
+        if (isShown()) {
49
+            closeDrawer(animated);
50
+        } else {
51
+            openDrawer(animated);
52
+        }
53
+    }
54
+
55
+    public SideMenu(Context context, SideMenuParams sideMenuParams) {
56
+        super(context);
57
+        createContentContainer();
58
+        createSideMenu(sideMenuParams);
59
+    }
60
+
61
+    private void createContentContainer() {
62
+        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
63
+        contentContainer = new RelativeLayout(getContext());
64
+        contentContainer.setId(ViewUtils.generateViewId());
65
+        addView(contentContainer, lp);
66
+    }
67
+
68
+    private void createSideMenu(SideMenuParams sideMenuParams) {
69
+        sideMenuView = new ContentView(getContext(), sideMenuParams.screenId, sideMenuParams.navigationParams);
70
+        LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
71
+        lp.gravity = Gravity.START;
72
+        addView(sideMenuView, lp);
73
+    }
74
+}

+ 4
- 4
android/app/src/main/java/com/reactnativenavigation/views/TitleBar.java Ver fichero

46
     }
46
     }
47
 
47
 
48
     public void setLeftButton(TitleBarLeftButtonParams leftButtonParams,
48
     public void setLeftButton(TitleBarLeftButtonParams leftButtonParams,
49
-                               TitleBarBackButtonListener titleBarBackButtonListener, String navigatorEventId) {
49
+                              LeftButtonOnClickListener leftButtonOnClickListener, String navigatorEventId) {
50
         if (shouldSetLeftButton(leftButtonParams)) {
50
         if (shouldSetLeftButton(leftButtonParams)) {
51
-            createAndSetLeftButton(leftButtonParams, titleBarBackButtonListener, navigatorEventId);
51
+            createAndSetLeftButton(leftButtonParams, leftButtonOnClickListener, navigatorEventId);
52
         } else if (hasLeftButton()) {
52
         } else if (hasLeftButton()) {
53
             updateLeftButton(leftButtonParams);
53
             updateLeftButton(leftButtonParams);
54
         }
54
         }
101
         return leftButton == null && leftButtonParams != null;
101
         return leftButton == null && leftButtonParams != null;
102
     }
102
     }
103
 
103
 
104
-    private void createAndSetLeftButton(TitleBarLeftButtonParams leftButtonParams, TitleBarBackButtonListener titleBarBackButtonListener, String navigatorEventId) {
105
-        leftButton = new LeftButton(getContext(), leftButtonParams, titleBarBackButtonListener, navigatorEventId);
104
+    private void createAndSetLeftButton(TitleBarLeftButtonParams leftButtonParams, LeftButtonOnClickListener leftButtonOnClickListener, String navigatorEventId) {
105
+        leftButton = new LeftButton(getContext(), leftButtonParams, leftButtonOnClickListener, navigatorEventId);
106
         setNavigationOnClickListener(leftButton);
106
         setNavigationOnClickListener(leftButton);
107
         setNavigationIcon(leftButton);
107
         setNavigationIcon(leftButton);
108
     }
108
     }

+ 0
- 5
android/app/src/main/java/com/reactnativenavigation/views/TitleBarBackButtonListener.java Ver fichero

1
-package com.reactnativenavigation.views;
2
-
3
-public interface TitleBarBackButtonListener {
4
-    boolean onTitleBarBackPress();
5
-}

+ 4
- 4
android/app/src/main/java/com/reactnativenavigation/views/TopBar.java Ver fichero

24
 
24
 
25
     public void addTitleBarAndSetButtons(List<TitleBarButtonParams> rightButtons,
25
     public void addTitleBarAndSetButtons(List<TitleBarButtonParams> rightButtons,
26
                                          TitleBarLeftButtonParams leftButton,
26
                                          TitleBarLeftButtonParams leftButton,
27
-                                         TitleBarBackButtonListener titleBarBackButtonListener,
27
+                                         LeftButtonOnClickListener leftButtonOnClickListener,
28
                                          String navigatorEventId) {
28
                                          String navigatorEventId) {
29
         titleBar = new TitleBar(getContext());
29
         titleBar = new TitleBar(getContext());
30
         addView(titleBar);
30
         addView(titleBar);
31
         titleBar.setRightButtons(rightButtons, navigatorEventId);
31
         titleBar.setRightButtons(rightButtons, navigatorEventId);
32
-        titleBar.setLeftButton(leftButton, titleBarBackButtonListener, navigatorEventId);
32
+        titleBar.setLeftButton(leftButton, leftButtonOnClickListener, navigatorEventId);
33
     }
33
     }
34
 
34
 
35
     public void setTitle(String title) {
35
     public void setTitle(String title) {
56
     }
56
     }
57
 
57
 
58
     public void setTitleBarRightButton(String navigatorEventId,
58
     public void setTitleBarRightButton(String navigatorEventId,
59
-                                       TitleBarBackButtonListener titleBarBackButtonListener,
59
+                                       LeftButtonOnClickListener leftButtonOnClickListener,
60
                                        TitleBarLeftButtonParams titleBarLeftButtonParams) {
60
                                        TitleBarLeftButtonParams titleBarLeftButtonParams) {
61
-        titleBar.setLeftButton(titleBarLeftButtonParams, titleBarBackButtonListener, navigatorEventId);
61
+        titleBar.setLeftButton(titleBarLeftButtonParams, leftButtonOnClickListener, navigatorEventId);
62
     }
62
     }
63
 
63
 
64
     private void setTopTabsStyle(StyleParams style) {
64
     private void setTopTabsStyle(StyleParams style) {

+ 86
- 71
example-redux/src/app.js Ver fichero

35
   startApp(root) {
35
   startApp(root) {
36
     switch (root) {
36
     switch (root) {
37
       case 'login':
37
       case 'login':
38
-        //Navigation.startSingleScreenApp({
39
-        //  screen: {
40
-        //    screen: 'example.LoginScreen',
41
-        //    title: 'Login',
42
-        //    navigatorStyle: {}
43
-        //  },
44
-        //  passProps: {
45
-        //    str: 'This is a prop passed in \'startSingleScreenApp()\'!',
46
-        //    obj: {
47
-        //      str: 'This is a prop passed in an object!',
48
-        //      arr: [
49
-        //        {
50
-        //          str: 'This is a prop in an object in an array in an object!'
51
-        //        }
52
-        //      ],
53
-        //      arr2: [
54
-        //        [
55
-        //          'array of strings',
56
-        //          'with two strings'
57
-        //        ],
58
-        //        [
59
-        //          1, 2, 3
60
-        //        ]
61
-        //      ]
62
-        //    },
63
-        //    num: 1234,
64
-        //    fn: function() {
65
-        //      return 'Hello from a function!';
66
-        //    }
67
-        //  }
68
-        //});
69
         Navigation.startSingleScreenApp({
38
         Navigation.startSingleScreenApp({
70
-          screen: {
71
-            screen: 'example.FirstTabScreen',
72
-            title: 'Login',
73
-            topTabs: [
74
-              {
75
-                screenId: 'example.ListScreen',
76
-                title: 'Tab1',
77
-                passProps: {
78
-                  str: 'This is a prop passed to Tab1'
79
-                }
80
-              },
81
-              {
82
-                screenId: 'example.PushedScreen',
83
-                title: 'Tab2',
84
-                passProps: {
85
-                  str: 'This is a prop passed to Tab2'
86
-                }
87
-
88
-              },
89
-              {
90
-                screenId: 'example.PushedScreen',
91
-                title: 'Tab3',
92
-                passProps: {
93
-                  str: 'This is a prop passed to Tab3'
94
-                }
95
-              },
96
-              {
97
-                screenId: 'example.FirstTabScreen',
98
-                title: 'Tab4',
99
-                passProps: {
100
-                  str: 'This is a prop passed to Tab4',
101
-                  fn: () => 'Hello from a function passed as passProps!'
102
-                }
103
-              }
104
-            ],
105
-            navigatorStyle: {}
106
-          }
39
+         screen: {
40
+           screen: 'example.LoginScreen',
41
+           title: 'Login',
42
+           navigatorStyle: {}
43
+         },
44
+         passProps: {
45
+           str: 'This is a prop passed in \'startSingleScreenApp()\'!',
46
+           obj: {
47
+             str: 'This is a prop passed in an object!',
48
+             arr: [
49
+               {
50
+                 str: 'This is a prop in an object in an array in an object!'
51
+               }
52
+             ],
53
+             arr2: [
54
+               [
55
+                 'array of strings',
56
+                 'with two strings'
57
+               ],
58
+               [
59
+                 1, 2, 3
60
+               ]
61
+             ]
62
+           },
63
+           num: 1234,
64
+           fn: function() {
65
+             return 'Hello from a function!';
66
+           }
67
+         }
107
         });
68
         });
69
+        // Navigation.startSingleScreenApp({
70
+        //   screen: {
71
+        //     screen: 'example.FirstTabScreen',
72
+        //     title: 'Login',
73
+        //     topTabs: [
74
+        //       {
75
+        //         screenId: 'example.ListScreen',
76
+        //         title: 'Tab1',
77
+        //         passProps: {
78
+        //           str: 'This is a prop passed to Tab1'
79
+        //         }
80
+        //       },
81
+        //       {
82
+        //         screenId: 'example.PushedScreen',
83
+        //         title: 'Tab2',
84
+        //         passProps: {
85
+        //           str: 'This is a prop passed to Tab2'
86
+        //         }
87
+        //
88
+        //       },
89
+        //       {
90
+        //         screenId: 'example.PushedScreen',
91
+        //         title: 'Tab3',
92
+        //         passProps: {
93
+        //           str: 'This is a prop passed to Tab3'
94
+        //         }
95
+        //       },
96
+        //       {
97
+        //         screenId: 'example.FirstTabScreen',
98
+        //         title: 'Tab4',
99
+        //         passProps: {
100
+        //           str: 'This is a prop passed to Tab4',
101
+        //           fn: () => 'Hello from a function passed as passProps!'
102
+        //         }
103
+        //       }
104
+        //     ],
105
+        //     navigatorStyle: {}
106
+        //   },
107
+        //   drawer: { // optional, add this if you want a side menu drawer in your app
108
+        //     left: { // optional, define if you want a drawer from the left
109
+        //       screen: 'example.SideMenu' // unique ID registered with Navigation.registerScreen
110
+        //     },
111
+        //     disableOpenGesture: false // optional, can the drawer be opened with a swipe instead of button
112
+        //   }
113
+        // });
108
         return;
114
         return;
109
       case 'after-login':
115
       case 'after-login':
110
         Navigation.startTabBasedApp({
116
         Navigation.startTabBasedApp({
115
               icon: require('../img/one.png'),
121
               icon: require('../img/one.png'),
116
               selectedIcon: require('../img/one_selected.png'),
122
               selectedIcon: require('../img/one_selected.png'),
117
               title: 'Screen One',
123
               title: 'Screen One',
118
-              navigatorStyle: {},
124
+              navigatorStyle: {}
119
             },
125
             },
120
             {
126
             {
121
               label: 'Two',
127
               label: 'Two',
123
               icon: require('../img/two.png'),
129
               icon: require('../img/two.png'),
124
               selectedIcon: require('../img/two_selected.png'),
130
               selectedIcon: require('../img/two_selected.png'),
125
               title: 'Screen Two',
131
               title: 'Screen Two',
126
-              navigatorStyle: {},
132
+              navigatorStyle: {}
127
             }
133
             }
128
           ],
134
           ],
129
           passProps: {
135
           passProps: {
139
             num: 1234
145
             num: 1234
140
           },
146
           },
141
           animationType: 'slide-down',
147
           animationType: 'slide-down',
142
-          title: 'Redux Example'
148
+          title: 'Redux Example',
149
+          drawer: { // optional, add this if you want a side menu drawer in your app
150
+            left: { // optional, define if you want a drawer from the left
151
+              screen: 'example.BottomTabsSideMenu' // unique ID registered with Navigation.registerScreen
152
+            },
153
+            disableOpenGesture: false, // optional, can the drawer be opened with a swipe instead of button
154
+            passProps: {
155
+              title: 'Hello from SideMenu'
156
+            }
157
+          }
143
         });
158
         });
144
         return;
159
         return;
145
       default:
160
       default:

+ 101
- 0
example-redux/src/screens/BottomTabsSideMenu.js Ver fichero

1
+import React, {Component, PropTypes} from 'react';
2
+import {
3
+  Text,
4
+  View,
5
+  ScrollView,
6
+  TouchableOpacity,
7
+  StyleSheet,
8
+  Alert
9
+} from 'react-native';
10
+import {connect} from 'react-redux';
11
+import * as counterActions from '../reducers/counter/actions';
12
+import _ from 'lodash';
13
+
14
+class SideMenu extends Component {
15
+
16
+  constructor(props) {
17
+    super(props);
18
+    // if you want to listen on navigator events, set this up
19
+    this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
20
+  }
21
+
22
+  onNavigatorEvent(event) {
23
+      console.log('SideMenu', 'Unhandled event ' + event.id);
24
+  }
25
+
26
+  render() {
27
+    return (
28
+      <View style={styles.sideMenu}>
29
+        <Text style={styles.title}>{this.props.title}</Text>
30
+
31
+        <TouchableOpacity onPress={ this.onShowModalPress.bind(this) }>
32
+          <Text style={styles.button}>Show modal</Text>
33
+        </TouchableOpacity>
34
+
35
+        <TouchableOpacity onPress={ this.onPushScreenToFirstTab.bind(this) }>
36
+          <Text style={styles.button}>Push screen to first tab</Text>
37
+        </TouchableOpacity>
38
+
39
+        <TouchableOpacity onPress={ this.onPushScreenToSecondTab.bind(this) }>
40
+          <Text style={styles.button}>Push screen to second tab</Text>
41
+        </TouchableOpacity>
42
+      </View>
43
+    );
44
+  }
45
+
46
+  onShowModalPress() {
47
+    this.props.navigator.showModal({
48
+      title: "Modal Screen from SideMenu",
49
+      screen: "example.PushedScreen",
50
+      passProps: {
51
+        str: 'This is a prop passed in \'navigator.showModal()\'!',
52
+        obj: {
53
+          str: 'This is a prop passed in an object!',
54
+          arr: [
55
+            {
56
+              str: 'This is a prop in an object in an array in an object!'
57
+            }
58
+          ]
59
+        },
60
+        num: 1234
61
+      }
62
+    });
63
+  }
64
+
65
+  onPushScreenToFirstTab() {
66
+    this.props.navigator.handleDeepLink({
67
+      link: 'tab1/pushScreen/example.PushedScreen'
68
+    });
69
+  }
70
+
71
+  onPushScreenToSecondTab() {
72
+    console.log('SideMenu', 'onPushScreenToSecondTab ' + 'tab2/pushScreen/example.PushedScreen');
73
+    this.props.navigator.handleDeepLink({
74
+      link: 'tab2/pushScreen/example.PushedScreen'
75
+    });
76
+  }
77
+}
78
+
79
+const styles = StyleSheet.create({
80
+  sideMenu: {
81
+    flex: 1,
82
+    width: 260,
83
+    backgroundColor: '#efefef',
84
+    padding: 20
85
+  },
86
+  title: {
87
+    textAlign: 'center',
88
+    marginBottom: 15
89
+  },
90
+  button: {
91
+    textAlign: 'center',
92
+    fontSize: 18,
93
+    borderBottomWidth: 1,
94
+    borderColor: 'grey',
95
+    marginBottom: 10,
96
+    marginTop:10,
97
+    color: 'black'
98
+  }
99
+});
100
+
101
+export default connect()(SideMenu);

+ 48
- 15
example-redux/src/screens/FirstTabScreen.js Ver fichero

46
   }
46
   }
47
 
47
 
48
   onNavigatorEvent(event) {
48
   onNavigatorEvent(event) {
49
-    switch (event.id) {
50
-      case 'edit':
51
-        Alert.alert('NavBar', 'Edit button pressed');
52
-        break;
53
-
54
-      case 'add':
55
-        Alert.alert('NavBar', 'Add button pressed');
56
-        break;
57
-
58
-      case 'selectedTabChanged':
59
-        this.onTabSelected(event.position);
60
-        break;
49
+    if (event.type == 'DeepLink') {
50
+      this.handleDeepLink(event);
51
+    } else {
52
+      switch (event.id) {
53
+        case 'edit':
54
+          Alert.alert('NavBar', 'Edit button pressed');
55
+          break;
56
+
57
+        case 'add':
58
+          Alert.alert('NavBar', 'Add button pressed');
59
+          break;
60
+
61
+        case 'selectedTabChanged':
62
+          this.onTabSelected(event.position);
63
+          break;
64
+
65
+        default:
66
+          console.log('Unhandled event ' + event.id);
67
+          break;
68
+      }
69
+    }
70
+  }
61
 
71
 
62
-      default:
63
-        console.log('Unhandled event ' + event.id);
64
-        break;
72
+  handleDeepLink(event) {
73
+    const parts = event.link.split('/');
74
+    if (parts[0] == 'tab1' && parts[1] == 'pushScreen') {
75
+      this.props.navigator.toggleDrawer({
76
+        side: 'left',
77
+        animated: true,
78
+        to: 'closed'
79
+      });
80
+
81
+      this.props.navigator.push({
82
+        title: "Pushed from SideMenu",
83
+        screen: parts[2],
84
+        passProps: {
85
+          str: 'This is a prop passed in \'navigator.push()\'!',
86
+          obj: {
87
+            str: 'This is a prop passed in an object!',
88
+            arr: [
89
+              {
90
+                str: 'This is a prop in an object in an array in an object!'
91
+              }
92
+            ]
93
+          },
94
+          num: 1234
95
+        }
96
+      });
65
     }
97
     }
98
+    return;
66
   }
99
   }
67
 
100
 
68
   onTabSelected(position) {
101
   onTabSelected(position) {

+ 31
- 3
example-redux/src/screens/ListScreen.js Ver fichero

30
 
30
 
31
   constructor(props) {
31
   constructor(props) {
32
     super(props);
32
     super(props);
33
-
33
+    this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
34
+    
34
     var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
35
     var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
35
     this.state = {
36
     this.state = {
36
       dataSource: ds.cloneWithRows(this._genRows({}))
37
       dataSource: ds.cloneWithRows(this._genRows({}))
37
     }
38
     }
38
   }
39
   }
39
 
40
 
40
-  componentWillMount() {
41
-    this._pressData = {};
41
+  onNavigatorEvent(event) {
42
+    if (event.type == 'DeepLink') {
43
+      const parts = event.link.split('/');
44
+      if (parts[0] == 'tab1' && parts[1] == 'pushScreen') {
45
+        this.props.navigator.toggleDrawer({
46
+          side: 'left',
47
+          animated: true,
48
+          to: 'closed'
49
+        });
50
+
51
+        this.props.navigator.push({
52
+          title: "Pushed from SideMenu",
53
+          screen: parts[2],
54
+          passProps: {
55
+            str: 'This is a prop passed in \'navigator.push()\'!',
56
+            obj: {
57
+              str: 'This is a prop passed in an object!',
58
+              arr: [
59
+                {
60
+                  str: 'This is a prop in an object in an array in an object!'
61
+                }
62
+              ]
63
+            },
64
+            num: 1234
65
+          }
66
+        });
67
+      }
68
+    }
69
+      console.log('ListScreen', 'Unhandled event ' + event.id);
42
   }
70
   }
43
 
71
 
44
   render() {
72
   render() {

+ 44
- 7
example-redux/src/screens/SecondTabScreen.js Ver fichero

22
   constructor(props) {
22
   constructor(props) {
23
     super(props);
23
     super(props);
24
     this.buttonsCounter = 0;
24
     this.buttonsCounter = 0;
25
+    this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
25
   }
26
   }
26
 
27
 
27
   render() {
28
   render() {
80
   }
81
   }
81
 
82
 
82
   onNavigatorEvent(event) {
83
   onNavigatorEvent(event) {
83
-    switch (event.id) {
84
-      case 'left':
85
-        Alert.alert('NavBar', 'Left button pressed');
86
-        break;
87
-      case 'right':
88
-        Alert.alert('NavBar', 'Right button pressed');
89
-        break;
84
+    if (event.type == 'DeepLink') {
85
+      this.handleDeepLink(event);
86
+    } else {
87
+      switch (event.id) {
88
+        case 'left':
89
+          Alert.alert('NavBar', 'Left button pressed');
90
+          break;
91
+        case 'right':
92
+          Alert.alert('NavBar', 'Right button pressed');
93
+          break;
94
+      }
90
     }
95
     }
96
+    console.log('ListScreen', 'Unhandled event ' + event.id);
91
   }
97
   }
98
+
99
+  handleDeepLink(event) {
100
+    const parts = event.link.split('/');
101
+    if (parts[0] == 'tab2' && parts[1] == 'pushScreen') {
102
+      this.props.navigator.toggleDrawer({
103
+        side: 'left',
104
+        animated: true,
105
+        to: 'closed'
106
+      });
107
+
108
+      this.props.navigator.push({
109
+        title: "Pushed from SideMenu",
110
+        screen: parts[2],
111
+        passProps: {
112
+          str: 'This is a prop passed in \'navigator.push()\'!',
113
+          obj: {
114
+            str: 'This is a prop passed in an object!',
115
+            arr: [
116
+              {
117
+                str: 'This is a prop in an object in an array in an object!'
118
+              }
119
+            ]
120
+          },
121
+          num: 1234
122
+        }
123
+      });
124
+    }
125
+    return;
126
+
127
+  }
128
+
92
 }
129
 }
93
 
130
 
94
 const styles = StyleSheet.create({
131
 const styles = StyleSheet.create({

+ 89
- 0
example-redux/src/screens/SideMenu.js Ver fichero

1
+import React, {Component, PropTypes} from 'react';
2
+import {
3
+  Text,
4
+  View,
5
+  ScrollView,
6
+  TouchableOpacity,
7
+  StyleSheet,
8
+  Alert
9
+} from 'react-native';
10
+import {connect} from 'react-redux';
11
+import * as counterActions from '../reducers/counter/actions';
12
+import _ from 'lodash';
13
+
14
+class SideMenu extends Component {
15
+
16
+  constructor(props) {
17
+    super(props);
18
+    // if you want to listen on navigator events, set this up
19
+    this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
20
+  }
21
+
22
+  onNavigatorEvent(event) {
23
+      console.log('SideMenu', 'Unhandled event ' + event.id);
24
+  }
25
+
26
+  render() {
27
+    return (
28
+      <View style={styles.sideMenu}>
29
+        <Text style={styles.title}>Hello from SideMenu</Text>
30
+
31
+        <TouchableOpacity onPress={ this.onShowModalPress.bind(this) }>
32
+          <Text style={styles.button}>Show modal</Text>
33
+        </TouchableOpacity>
34
+
35
+        <TouchableOpacity onPress={ this.onPushScreen.bind(this) }>
36
+          <Text style={styles.button}>Push screen</Text>
37
+        </TouchableOpacity>
38
+      </View>
39
+    );
40
+  }
41
+
42
+  onShowModalPress() {
43
+    this.props.navigator.showModal({
44
+      title: "Modal Screen from SideMenu",
45
+      screen: "example.PushedScreen",
46
+      passProps: {
47
+        str: 'This is a prop passed in \'navigator.showModal()\'!',
48
+        obj: {
49
+          str: 'This is a prop passed in an object!',
50
+          arr: [
51
+            {
52
+              str: 'This is a prop in an object in an array in an object!'
53
+            }
54
+          ]
55
+        },
56
+        num: 1234
57
+      }
58
+    });
59
+  }
60
+
61
+  onPushScreen() {
62
+    this.props.navigator.handleDeepLink({
63
+      link: 'tab1/pushScreen/example.PushedScreen'
64
+    });
65
+  }
66
+}
67
+
68
+const styles = StyleSheet.create({
69
+  sideMenu: {
70
+    flex: 1,
71
+    backgroundColor: '#efefef',
72
+    padding: 20
73
+  },
74
+  title: {
75
+    textAlign: 'center',
76
+    marginBottom: 15
77
+  },
78
+  button: {
79
+    textAlign: 'center',
80
+    fontSize: 18,
81
+    borderBottomWidth: 1,
82
+    borderColor: 'grey',
83
+    marginBottom: 10,
84
+    marginTop:10,
85
+    color: 'black'
86
+  }
87
+});
88
+
89
+export default connect()(SideMenu);

+ 4
- 0
example-redux/src/screens/index.js Ver fichero

5
 import SecondTabScreen from './SecondTabScreen';
5
 import SecondTabScreen from './SecondTabScreen';
6
 import PushedScreen from './PushedScreen';
6
 import PushedScreen from './PushedScreen';
7
 import ListScreen from './ListScreen';
7
 import ListScreen from './ListScreen';
8
+import SideMenu from './SideMenu';
9
+import BottomTabsSideMenu from './BottomTabsSideMenu';
8
 
10
 
9
 // register all screens of the app (including internal ones)
11
 // register all screens of the app (including internal ones)
10
 export function registerScreens(store, Provider) {
12
 export function registerScreens(store, Provider) {
13
   Navigation.registerComponent('example.SecondTabScreen', () => SecondTabScreen, store, Provider);
15
   Navigation.registerComponent('example.SecondTabScreen', () => SecondTabScreen, store, Provider);
14
   Navigation.registerComponent('example.PushedScreen', () => PushedScreen, store, Provider);
16
   Navigation.registerComponent('example.PushedScreen', () => PushedScreen, store, Provider);
15
   Navigation.registerComponent('example.ListScreen', () => ListScreen, store, Provider);
17
   Navigation.registerComponent('example.ListScreen', () => ListScreen, store, Provider);
18
+  Navigation.registerComponent('example.SideMenu', () => SideMenu, store, Provider);
19
+  Navigation.registerComponent('example.BottomTabsSideMenu', () => BottomTabsSideMenu, store, Provider);
16
 }
20
 }

+ 37
- 30
src/deprecated/platformSpecificDeprecated.android.js Ver fichero

15
     return;
15
     return;
16
   }
16
   }
17
   addNavigatorParams(screen);
17
   addNavigatorParams(screen);
18
-  addNavigatorButtons(screen);
18
+  addNavigatorButtons(screen, params.drawer);
19
   addNavigationStyleParams(screen);
19
   addNavigationStyleParams(screen);
20
   screen.passProps = params.passProps;
20
   screen.passProps = params.passProps;
21
 
21
 
22
-  //const drawer = setupDrawer(params.drawer);
23
-
24
   /*
22
   /*
25
    * adapt to new API
23
    * adapt to new API
26
    */
24
    */
29
   params.screen = adaptNavigationStyleToScreenStyle(screen);
27
   params.screen = adaptNavigationStyleToScreenStyle(screen);
30
   params.screen = adaptNavigationParams(screen);
28
   params.screen = adaptNavigationParams(screen);
31
   params.appStyle = convertStyleParams(params.appStyle);
29
   params.appStyle = convertStyleParams(params.appStyle);
30
+  params.sideMenu = convertDrawerParamsToSideMenuParams(params.drawer);
32
 
31
 
33
   newPlatformSpecific.startApp(params);
32
   newPlatformSpecific.startApp(params);
34
 }
33
 }
134
   }
133
   }
135
 }
134
 }
136
 
135
 
136
+function convertDrawerParamsToSideMenuParams(drawerParams) {
137
+  const drawer = Object.assign({}, drawerParams);
138
+  if (!drawer.left || !drawer.left.screen) {
139
+    return null;
140
+  }
141
+
142
+  let result = {};
143
+  result.disableOpenGesture = drawer.disableOpenGesture !== undefined;
144
+  result.screenId = drawer.left.screen;
145
+  addNavigatorParams(result);
146
+  result = adaptNavigationParams(result);
147
+  result.passProps = drawer.passProps;
148
+  return result;
149
+}
150
+
137
 function adaptNavigationParams(screen) {
151
 function adaptNavigationParams(screen) {
138
   screen.navigationParams = {
152
   screen.navigationParams = {
139
     screenInstanceID: screen.screenInstanceID,
153
     screenInstanceID: screen.screenInstanceID,
153
 
167
 
154
   params.tabs.forEach(function(tab, idx) {
168
   params.tabs.forEach(function(tab, idx) {
155
     addNavigatorParams(tab, null, idx);
169
     addNavigatorParams(tab, null, idx);
156
-    addNavigatorButtons(tab);
170
+    addNavigatorButtons(tab, params.drawer);
157
     addNavigationStyleParams(tab);
171
     addNavigationStyleParams(tab);
158
     addTabIcon(tab);
172
     addTabIcon(tab);
159
     tab.passProps = params.passProps;
173
     tab.passProps = params.passProps;
169
   params.tabs = newTabs;
183
   params.tabs = newTabs;
170
 
184
 
171
   params.appStyle = convertStyleParams(params.appStyle);
185
   params.appStyle = convertStyleParams(params.appStyle);
172
-  // TODO: add drawer params
186
+  params.sideMenu = convertDrawerParamsToSideMenuParams(params.drawer);
173
 
187
 
174
   newPlatformSpecific.startApp(params);
188
   newPlatformSpecific.startApp(params);
175
 }
189
 }
229
 }
243
 }
230
 
244
 
231
 function navigatorToggleDrawer(navigator, params) {
245
 function navigatorToggleDrawer(navigator, params) {
232
-  //RctActivity.toggleDrawer({
233
-  //  side: params.side,
234
-  //  animated: !(params.animated === false),
235
-  //  to: params.to || ''
236
-  //});
246
+  const animated = !(params.animated === false);
247
+  if (params.to) {
248
+    const visible = params.to === 'open';
249
+    newPlatformSpecific.setSideMenuVisible(animated, visible);
250
+  } else {
251
+    newPlatformSpecific.toggleSideMenuVisible(animated);
252
+  }
237
 }
253
 }
238
 
254
 
239
 function navigatorToggleNavBar(navigator, params) {
255
 function navigatorToggleNavBar(navigator, params) {
284
   screen.navigatorEventID = screen.screenInstanceID + '_events';
300
   screen.navigatorEventID = screen.screenInstanceID + '_events';
285
 }
301
 }
286
 
302
 
287
-function addNavigatorButtons(screen) {
303
+function addNavigatorButtons(screen, sideMenuParams) {
288
   const Screen = Navigation.getRegisteredScreen(screen.screen);
304
   const Screen = Navigation.getRegisteredScreen(screen.screen);
289
   Object.assign(screen, Screen.navigatorButtons);
305
   Object.assign(screen, Screen.navigatorButtons);
290
 
306
 
302
     });
318
     });
303
   }
319
   }
304
 
320
 
305
-  const leftButton = getLeftButton(screen);
321
+  let leftButton = getLeftButton(screen);
322
+  if (sideMenuParams && !leftButton) {
323
+    leftButton = createSideMenuButton();
324
+  }
306
   if (leftButton) {
325
   if (leftButton) {
307
     if (leftButton.icon) {
326
     if (leftButton.icon) {
308
       const icon = resolveAssetSource(leftButton.icon);
327
       const icon = resolveAssetSource(leftButton.icon);
320
   }
339
   }
321
 }
340
 }
322
 
341
 
342
+function createSideMenuButton() {
343
+  return {
344
+    id: "sideMenu"
345
+  };
346
+}
347
+
323
 function addTitleBarBackButtonIfNeeded(screen) {
348
 function addTitleBarBackButtonIfNeeded(screen) {
324
   const leftButton = getLeftButton(screen);
349
   const leftButton = getLeftButton(screen);
325
   if (!leftButton) {
350
   if (!leftButton) {
350
   screen.navigatorStyle = Object.assign({}, screen.navigatorStyle, Screen.navigatorStyle);
375
   screen.navigatorStyle = Object.assign({}, screen.navigatorStyle, Screen.navigatorStyle);
351
 }
376
 }
352
 
377
 
353
-function setupDrawer(drawerParams) {
354
-  const drawer = Object.assign({}, drawerParams);
355
-  [drawer.left, drawer.right].forEach(side => {
356
-    if (!side) {
357
-      return;
358
-    }
359
-    const icon = resolveAssetSource(side.icon);
360
-    if (icon) {
361
-      side.icon = icon.uri;
362
-    }
363
-  });
364
-  if (drawer.disableOpenGesture === undefined) {
365
-    drawer.disableOpenGesture = false;
366
-  }
367
-
368
-  return drawer;
369
-}
370
-
371
 export default {
378
 export default {
372
   startTabBasedApp,
379
   startTabBasedApp,
373
   startSingleScreenApp,
380
   startSingleScreenApp,

+ 15
- 1
src/platformSpecific.android.js Ver fichero

78
       savePassProps(tab);
78
       savePassProps(tab);
79
     });
79
     });
80
   }
80
   }
81
+
82
+  if (params.sideMenu) {
83
+    PropRegistry.save(params.sideMenu.navigationParams.screenInstanceID, params.sideMenu.passProps);
84
+  }
85
+}
86
+
87
+function toggleSideMenuVisible(animated) {
88
+  NativeReactModule.toggleSideMenuVisible(animated);
89
+}
90
+
91
+function setSideMenuVisible(animated, visible) {
92
+  NativeReactModule.setSideMenuVisible(animated, visible);
81
 }
93
 }
82
 
94
 
83
 module.exports = {
95
 module.exports = {
92
   setScreenTitleBarButtons,
104
   setScreenTitleBarButtons,
93
   showModal,
105
   showModal,
94
   dismissTopModal,
106
   dismissTopModal,
95
-  dismissAllModals
107
+  dismissAllModals,
108
+  toggleSideMenuVisible,
109
+  setSideMenuVisible
96
 };
110
 };