소스 검색

[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 년 전
부모
커밋
e0a6ff2dad
No account linked to committer's email address

+ 3
- 0
android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java 파일 보기

@@ -106,6 +106,9 @@ public class BottomTabsLayout extends BaseLayout implements AHBottomNavigation.O
106 106
         ScreenParams screenParams = params.tabParams.get(position);
107 107
         ScreenStack newStack = new ScreenStack(getActivity(), getScreenStackParent(), screenParams.getNavigatorId(), this);
108 108
         newStack.pushInitialScreen(screenParams, createScreenLayoutParams(screenParams));
109
+        for (ScreenParams screen : screenParams.screens) {
110
+            newStack.pushInitialScreen(screen, createScreenLayoutParams(screen));
111
+        }
109 112
         screenStacks[position] = newStack;
110 113
     }
111 114
 

+ 8
- 1
android/app/src/main/java/com/reactnativenavigation/layouts/SingleScreenLayout.java 파일 보기

@@ -85,11 +85,18 @@ public class SingleScreenLayout extends BaseLayout {
85 85
         stack = new ScreenStack(getActivity(), parent, screenParams.getNavigatorId(), this);
86 86
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
87 87
         pushInitialScreen(lp);
88
+        pushAdditionalScreens(lp);
89
+        stack.show(NavigationType.Push);
88 90
     }
89 91
 
90 92
     protected void pushInitialScreen(LayoutParams lp) {
91 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 102
     private void sendScreenChangedEventAfterInitialPush() {

+ 2
- 0
android/app/src/main/java/com/reactnativenavigation/params/ScreenParams.java 파일 보기

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

+ 12
- 0
android/app/src/main/java/com/reactnativenavigation/params/parsers/ScreenParamsParser.java 파일 보기

@@ -42,6 +42,9 @@ public class ScreenParamsParser extends Parser {
42 42
         result.leftButton = ButtonParser.parseLeftButton(params);
43 43
 
44 44
         result.topTabParams = parseTopTabs(params);
45
+        if (hasKey(params, "screens")) {
46
+            result.screens = parseScreens(params.getBundle("screens"));
47
+        }
45 48
 
46 49
         if (hasKey(params, FRAGMENT_CREATOR_CLASS_NAME)) {
47 50
             result.fragmentCreatorClassName = params.getString(FRAGMENT_CREATOR_CLASS_NAME);
@@ -105,4 +108,13 @@ public class ScreenParamsParser extends Parser {
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 파일 보기

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

+ 58
- 31
src/deprecated/platformSpecificDeprecated.android.js 파일 보기

@@ -11,32 +11,45 @@ const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSou
11 11
 import * as newPlatformSpecific from './../platformSpecific';
12 12
 
13 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 16
     console.error('startSingleScreenApp(params): screen must include a screen property');
17 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 41
   addNavigatorParams(screen);
20 42
   addNavigatorButtons(screen, params.drawer);
21 43
   addNavigationStyleParams(screen);
22 44
   screen.passProps = params.passProps;
23
-
24 45
   /*
25 46
    * adapt to new API
26 47
    */
27 48
   adaptTopTabs(screen, screen.navigatorID);
28 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 55
 function getOrientation(params) {
@@ -297,23 +310,18 @@ async function startTabBasedApp(params) {
297 310
   params.tabs = _.cloneDeep(params.tabs);
298 311
 
299 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 326
   params.tabs = newTabs;
319 327
 
@@ -327,6 +335,26 @@ async function startTabBasedApp(params) {
327 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 358
 function addTabIcon(tab) {
331 359
   if (tab.icon) {
332 360
     const icon = resolveAssetSource(tab.icon);
@@ -553,7 +581,6 @@ function addNavigatorParams(screen, navigator = null, idx = '') {
553 581
 }
554 582
 
555 583
 function addNavigatorButtons(screen, sideMenuParams) {
556
-
557 584
   const Screen = Navigation.getRegisteredScreen(screen.screen);
558 585
   if (screen.navigatorButtons == null) {
559 586
     screen.navigatorButtons = _.cloneDeep(Screen.navigatorButtons);