Browse Source

[Android] Add ability to start app with deep stack (#2761)

For example, the following code will start a single screen app with two
screens pushed into the stack.

```js
Navigation.startSingleScreenApp({
    components: [
    {
      screen: 'example.Types',
      title: 'Navigation Types',
      overrideBackPress: true
    },
    {
      screen: 'example.Types.CustomButtonScreen',
      title: 'Custom Buttons'
    }
  ]
});
```
Guy Carmeli 6 years ago
parent
commit
e0a6ff2dad
No account linked to committer's email address

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

106
         ScreenParams screenParams = params.tabParams.get(position);
106
         ScreenParams screenParams = params.tabParams.get(position);
107
         ScreenStack newStack = new ScreenStack(getActivity(), getScreenStackParent(), screenParams.getNavigatorId(), this);
107
         ScreenStack newStack = new ScreenStack(getActivity(), getScreenStackParent(), screenParams.getNavigatorId(), this);
108
         newStack.pushInitialScreen(screenParams, createScreenLayoutParams(screenParams));
108
         newStack.pushInitialScreen(screenParams, createScreenLayoutParams(screenParams));
109
+        for (ScreenParams screen : screenParams.screens) {
110
+            newStack.pushInitialScreen(screen, createScreenLayoutParams(screen));
111
+        }
109
         screenStacks[position] = newStack;
112
         screenStacks[position] = newStack;
110
     }
113
     }
111
 
114
 

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

85
         stack = new ScreenStack(getActivity(), parent, screenParams.getNavigatorId(), this);
85
         stack = new ScreenStack(getActivity(), parent, screenParams.getNavigatorId(), this);
86
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
86
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
87
         pushInitialScreen(lp);
87
         pushInitialScreen(lp);
88
+        pushAdditionalScreens(lp);
89
+        stack.show(NavigationType.Push);
88
     }
90
     }
89
 
91
 
90
     protected void pushInitialScreen(LayoutParams lp) {
92
     protected void pushInitialScreen(LayoutParams lp) {
91
         stack.pushInitialScreen(screenParams, lp);
93
         stack.pushInitialScreen(screenParams, lp);
92
-        stack.show(NavigationType.Push);
94
+    }
95
+
96
+    private void pushAdditionalScreens(LayoutParams lp) {
97
+        for (ScreenParams screen : screenParams.screens) {
98
+            stack.pushInitialScreen(screen, lp);
99
+        }
93
     }
100
     }
94
 
101
 
95
     private void sendScreenChangedEventAfterInitialPush() {
102
     private void sendScreenChangedEventAfterInitialPush() {

+ 2
- 0
android/app/src/main/java/com/reactnativenavigation/params/ScreenParams.java View File

1
 package com.reactnativenavigation.params;
1
 package com.reactnativenavigation.params;
2
 
2
 
3
+import java.util.Collections;
3
 import java.util.List;
4
 import java.util.List;
4
 
5
 
5
 public class ScreenParams extends BaseScreenParams {
6
 public class ScreenParams extends BaseScreenParams {
6
     public String tabLabel;
7
     public String tabLabel;
7
     public List<PageParams> topTabParams;
8
     public List<PageParams> topTabParams;
8
     public List<String> sharedElementsTransitions;
9
     public List<String> sharedElementsTransitions;
10
+    public List<ScreenParams> screens = Collections.EMPTY_LIST; // used to init a stack with multiple screens
9
 
11
 
10
     public boolean hasTopTabs() {
12
     public boolean hasTopTabs() {
11
         return topTabParams != null && !topTabParams.isEmpty();
13
         return topTabParams != null && !topTabParams.isEmpty();

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

42
         result.leftButton = ButtonParser.parseLeftButton(params);
42
         result.leftButton = ButtonParser.parseLeftButton(params);
43
 
43
 
44
         result.topTabParams = parseTopTabs(params);
44
         result.topTabParams = parseTopTabs(params);
45
+        if (hasKey(params, "screens")) {
46
+            result.screens = parseScreens(params.getBundle("screens"));
47
+        }
45
 
48
 
46
         if (hasKey(params, FRAGMENT_CREATOR_CLASS_NAME)) {
49
         if (hasKey(params, FRAGMENT_CREATOR_CLASS_NAME)) {
47
             result.fragmentCreatorClassName = params.getString(FRAGMENT_CREATOR_CLASS_NAME);
50
             result.fragmentCreatorClassName = params.getString(FRAGMENT_CREATOR_CLASS_NAME);
105
             }
108
             }
106
         });
109
         });
107
     }
110
     }
111
+
112
+    private static List<ScreenParams> parseScreens(Bundle screens) {
113
+        return new Parser().parseBundle(screens, new ParseStrategy<ScreenParams>() {
114
+            @Override
115
+            public ScreenParams parse(Bundle screen) {
116
+                return ScreenParamsParser.parse(screen);
117
+            }
118
+        });
119
+    }
108
 }
120
 }

+ 5
- 0
android/app/src/main/java/com/reactnativenavigation/screens/ScreenStack.java View File

95
     public void pushInitialScreen(ScreenParams initialScreenParams, LayoutParams params) {
95
     public void pushInitialScreen(ScreenParams initialScreenParams, LayoutParams params) {
96
         Screen initialScreen = ScreenFactory.create(activity, initialScreenParams, leftButtonOnClickListener);
96
         Screen initialScreen = ScreenFactory.create(activity, initialScreenParams, leftButtonOnClickListener);
97
         initialScreen.setVisibility(View.INVISIBLE);
97
         initialScreen.setVisibility(View.INVISIBLE);
98
+        removeCurrentScreen();
98
         addScreen(initialScreen, params);
99
         addScreen(initialScreen, params);
99
     }
100
     }
100
 
101
 
102
+    private void removeCurrentScreen() {
103
+        if (!stack.empty()) parent.removeView(peek());
104
+    }
105
+
101
     public void push(final ScreenParams params, LayoutParams layoutParams, Promise onPushComplete) {
106
     public void push(final ScreenParams params, LayoutParams layoutParams, Promise onPushComplete) {
102
         Screen nextScreen = ScreenFactory.create(activity, params, leftButtonOnClickListener);
107
         Screen nextScreen = ScreenFactory.create(activity, params, leftButtonOnClickListener);
103
         final Screen previousScreen = stack.peek();
108
         final Screen previousScreen = stack.peek();

+ 58
- 31
src/deprecated/platformSpecificDeprecated.android.js View File

11
 import * as newPlatformSpecific from './../platformSpecific';
11
 import * as newPlatformSpecific from './../platformSpecific';
12
 
12
 
13
 async function startSingleScreenApp(params) {
13
 async function startSingleScreenApp(params) {
14
-  const screen = params.screen;
15
-  if (!screen.screen) {
14
+  const components = params.components;
15
+  if (!params.screen && !components) {
16
     console.error('startSingleScreenApp(params): screen must include a screen property');
16
     console.error('startSingleScreenApp(params): screen must include a screen property');
17
     return;
17
     return;
18
   }
18
   }
19
+
20
+  if (components) {
21
+    params.screen = createSingleScreen(components[0]);
22
+    components.shift();
23
+    params.screen.screens = components.map(createSingleScreen);
24
+  } else {
25
+    params.screen = createSingleScreen(params.screen);
26
+  }
27
+
28
+  params.sideMenu = convertDrawerParamsToSideMenuParams(params.drawer);
29
+  params.overrideBackPress = params.screen.overrideBackPress;
30
+  params.animateShow = convertAnimationType(params.animationType);
31
+  params.appStyle = convertStyleParams(params.appStyle);
32
+    if (params.appStyle) {
33
+      params.appStyle.orientation = getOrientation(params);
34
+    }
35
+
36
+  return await newPlatformSpecific.startApp(params);
37
+}
38
+
39
+function createSingleScreen(params) {
40
+  let screen = params;
19
   addNavigatorParams(screen);
41
   addNavigatorParams(screen);
20
   addNavigatorButtons(screen, params.drawer);
42
   addNavigatorButtons(screen, params.drawer);
21
   addNavigationStyleParams(screen);
43
   addNavigationStyleParams(screen);
22
   screen.passProps = params.passProps;
44
   screen.passProps = params.passProps;
23
-
24
   /*
45
   /*
25
    * adapt to new API
46
    * adapt to new API
26
    */
47
    */
27
   adaptTopTabs(screen, screen.navigatorID);
48
   adaptTopTabs(screen, screen.navigatorID);
28
   screen.screenId = screen.screen;
49
   screen.screenId = screen.screen;
29
-  params.screen = adaptNavigationStyleToScreenStyle(screen);
30
-  params.screen = adaptNavigationParams(screen);
31
-  params.appStyle = convertStyleParams(params.appStyle);
32
-  if (params.appStyle) {
33
-    params.appStyle.orientation = getOrientation(params);
34
-  }
35
-  params.sideMenu = convertDrawerParamsToSideMenuParams(params.drawer);
36
-  params.overrideBackPress = screen.overrideBackPress;
37
-  params.animateShow = convertAnimationType(params.animationType);
38
-
39
-  return await newPlatformSpecific.startApp(params);
50
+  screen = adaptNavigationStyleToScreenStyle(screen);
51
+  screen = adaptNavigationParams(screen);
52
+  return screen;
40
 }
53
 }
41
 
54
 
42
 function getOrientation(params) {
55
 function getOrientation(params) {
297
   params.tabs = _.cloneDeep(params.tabs);
310
   params.tabs = _.cloneDeep(params.tabs);
298
 
311
 
299
   params.tabs.forEach(function(tab, idx) {
312
   params.tabs.forEach(function(tab, idx) {
300
-    addNavigatorParams(tab, null, idx);
301
-    addNavigatorButtons(tab, params.drawer);
302
-    addNavigationStyleParams(tab);
303
-    addTabIcon(tab);
304
-    if (!tab.passProps) {
305
-      tab.passProps = params.passProps;
313
+    if (tab.components) {
314
+      const components = tab.components;
315
+      const screen = createBottomTabScreen(components[0], idx, params)
316
+      const {label, icon} = components[0];
317
+      components.shift();
318
+      console.log('guyca', `${JSON.stringify(components[0])}`);
319
+      screen.screens = components.map(c => createBottomTabScreen({...c, icon, label}, idx, params));
320
+      
321
+      newTabs.push(screen);
322
+    } else {
323
+      newTabs.push(createBottomTabScreen(tab, idx, params));
306
     }
324
     }
307
-
308
-    adaptTopTabs(tab, tab.navigatorID);
309
-
310
-    tab.screenId = tab.screen;
311
-
312
-    let newtab = adaptNavigationStyleToScreenStyle(tab);
313
-    newtab = adaptNavigationParams(tab);
314
-    newtab.overrideBackPress = tab.overrideBackPress;
315
-    newtab.timestamp = Date.now();
316
-    newTabs.push(newtab);
317
   });
325
   });
318
   params.tabs = newTabs;
326
   params.tabs = newTabs;
319
 
327
 
327
   return await newPlatformSpecific.startApp(params);
335
   return await newPlatformSpecific.startApp(params);
328
 }
336
 }
329
 
337
 
338
+function createBottomTabScreen(tab, idx, params) {
339
+  addNavigatorParams(tab, null, idx);
340
+  addNavigatorButtons(tab, params.drawer);
341
+  addNavigationStyleParams(tab);
342
+  addTabIcon(tab);
343
+  if (!tab.passProps) {
344
+    tab.passProps = params.passProps;
345
+  }
346
+
347
+  adaptTopTabs(tab, tab.navigatorID);
348
+
349
+  tab.screenId = tab.screen;
350
+
351
+  let newtab = adaptNavigationStyleToScreenStyle(tab);
352
+  newtab = adaptNavigationParams(tab);
353
+  newtab.overrideBackPress = tab.overrideBackPress;
354
+  newtab.timestamp = Date.now();
355
+  return newtab;
356
+};
357
+
330
 function addTabIcon(tab) {
358
 function addTabIcon(tab) {
331
   if (tab.icon) {
359
   if (tab.icon) {
332
     const icon = resolveAssetSource(tab.icon);
360
     const icon = resolveAssetSource(tab.icon);
553
 }
581
 }
554
 
582
 
555
 function addNavigatorButtons(screen, sideMenuParams) {
583
 function addNavigatorButtons(screen, sideMenuParams) {
556
-
557
   const Screen = Navigation.getRegisteredScreen(screen.screen);
584
   const Screen = Navigation.getRegisteredScreen(screen.screen);
558
   if (screen.navigatorButtons == null) {
585
   if (screen.navigatorButtons == null) {
559
     screen.navigatorButtons = _.cloneDeep(Screen.navigatorButtons);
586
     screen.navigatorButtons = _.cloneDeep(Screen.navigatorButtons);