Explorar el Código

composition of layouts (view controllers)

Daniel Zlotin hace 7 años
padre
commit
21ed2b740d
Se han modificado 15 ficheros con 318 adiciones y 229 borrados
  1. 4
    2
      lib/android/app/src/main/java/com/reactnativenavigation/NavigationActivity.java
  2. 9
    0
      lib/android/app/src/main/java/com/reactnativenavigation/layout/Layout.java
  3. 32
    40
      lib/android/app/src/main/java/com/reactnativenavigation/layout/LayoutFactory.java
  4. 0
    28
      lib/android/app/src/main/java/com/reactnativenavigation/layout/LayoutNode.java
  5. 38
    25
      lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/BottomTabsLayout.java
  6. 0
    63
      lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/Container.java
  7. 0
    47
      lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/ContainerStack.java
  8. 59
    0
      lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/LayoutStack.java
  9. 70
    0
      lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/RootLayout.java
  10. 43
    2
      lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/SideMenuLayout.java
  11. 2
    2
      lib/android/app/src/main/java/com/reactnativenavigation/parse/JSONParser.java
  12. 39
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutNodeParser.java
  13. 13
    13
      lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java
  14. 5
    4
      lib/android/app/src/test/java/com/reactnativenavigation/parse/JSONParserTest.java
  15. 4
    3
      lib/android/app/src/test/java/com/reactnativenavigation/parse/LayoutNodeParserTest.java

+ 4
- 2
lib/android/app/src/main/java/com/reactnativenavigation/NavigationActivity.java Ver fichero

@@ -6,10 +6,12 @@ import android.support.v7.app.AppCompatActivity;
6 6
 import android.view.View;
7 7
 
8 8
 import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
9
-import com.reactnativenavigation.layout.containers.ContainerStack;
9
+import com.reactnativenavigation.layout.Layout;
10
+import com.reactnativenavigation.layout.containers.LayoutStack;
10 11
 
11 12
 public class NavigationActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
12 13
 	private View contentView;
14
+	private Layout layout;
13 15
 
14 16
 	@Override
15 17
 	protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -53,7 +55,7 @@ public class NavigationActivity extends AppCompatActivity implements DefaultHard
53 55
 
54 56
 	@Override
55 57
 	public void onBackPressed() {
56
-		if (!(contentView instanceof ContainerStack) || !((ContainerStack) contentView).onBackPressed()) {
58
+		if (!(contentView instanceof LayoutStack) || !((LayoutStack) contentView).onBackPressed()) {
57 59
 			super.onBackPressed();
58 60
 		}
59 61
 	}

+ 9
- 0
lib/android/app/src/main/java/com/reactnativenavigation/layout/Layout.java Ver fichero

@@ -0,0 +1,9 @@
1
+package com.reactnativenavigation.layout;
2
+
3
+import android.view.View;
4
+
5
+public interface Layout {
6
+	View getView();
7
+
8
+	void destroy();
9
+}

+ 32
- 40
lib/android/app/src/main/java/com/reactnativenavigation/layout/LayoutFactory.java Ver fichero

@@ -1,18 +1,12 @@
1 1
 package com.reactnativenavigation.layout;
2 2
 
3 3
 import android.app.Activity;
4
-import android.support.v4.widget.DrawerLayout;
5
-import android.view.Gravity;
6
-import android.view.View;
7
-import android.view.ViewGroup.LayoutParams;
8 4
 
9 5
 import com.facebook.react.ReactInstanceManager;
10
-import com.reactnativenavigation.layout.containers.BottomTabs;
11 6
 import com.reactnativenavigation.layout.containers.BottomTabsLayout;
12
-import com.reactnativenavigation.layout.containers.Container;
13
-import com.reactnativenavigation.layout.containers.ContainerStack;
7
+import com.reactnativenavigation.layout.containers.LayoutStack;
8
+import com.reactnativenavigation.layout.containers.RootLayout;
14 9
 import com.reactnativenavigation.layout.containers.SideMenuLayout;
15
-import com.reactnativenavigation.utils.CompatUtils;
16 10
 
17 11
 public class LayoutFactory {
18 12
 
@@ -24,7 +18,7 @@ public class LayoutFactory {
24 18
 		this.reactInstanceManager = reactInstanceManager;
25 19
 	}
26 20
 
27
-	public View create(LayoutNode node) {
21
+	public Layout create(LayoutNode node) {
28 22
 		switch (node.type) {
29 23
 			case Container:
30 24
 				return createContainer(node);
@@ -45,57 +39,55 @@ public class LayoutFactory {
45 39
 		}
46 40
 	}
47 41
 
48
-	private View createSideMenuRoot(LayoutNode node) {
42
+	private Layout createSideMenuRoot(LayoutNode node) {
49 43
 		SideMenuLayout sideMenuLayout = new SideMenuLayout(activity);
50 44
 		for (LayoutNode child : node.children) {
51
-			sideMenuLayout.addView(create(child));
45
+			Layout childLayout = create(child);
46
+			switch (child.type) {
47
+				case SideMenuCenter:
48
+					sideMenuLayout.addCenterLayout(childLayout);
49
+					break;
50
+				case SideMenuLeft:
51
+					sideMenuLayout.addLeftLayout(childLayout);
52
+					break;
53
+				case SideMenuRight:
54
+					sideMenuLayout.addRightLayout(childLayout);
55
+					break;
56
+				default:
57
+					throw new IllegalArgumentException("Invalid node type in sideMenu: " + node.type);
58
+			}
52 59
 		}
53 60
 		return sideMenuLayout;
54 61
 	}
55 62
 
56
-	private View createSideMenuContent(LayoutNode node) {
63
+	private Layout createSideMenuContent(LayoutNode node) {
57 64
 		return create(node.children.get(0));
58 65
 	}
59 66
 
60
-	private View createSideMenuLeft(LayoutNode node) {
61
-		View view = create(node.children.get(0));
62
-		view.setId(CompatUtils.generateViewId());
63
-		DrawerLayout.LayoutParams lp = new DrawerLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
64
-		lp.gravity = Gravity.LEFT;
65
-		view.setLayoutParams(lp);
66
-		return view;
67
+	private Layout createSideMenuLeft(LayoutNode node) {
68
+		return create(node.children.get(0));
67 69
 	}
68 70
 
69
-	private View createSideMenuRight(LayoutNode node) {
70
-		View view = create(node.children.get(0));
71
-		view.setId(CompatUtils.generateViewId());
72
-		DrawerLayout.LayoutParams lp = new DrawerLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
73
-		lp.gravity = Gravity.RIGHT;
74
-		view.setLayoutParams(lp);
75
-		return view;
71
+	private Layout createSideMenuRight(LayoutNode node) {
72
+		return create(node.children.get(0));
76 73
 	}
77 74
 
78
-	private View createContainer(LayoutNode node) {
79
-		final String name = node.data.optString("name");
80
-		Container container = new Container(activity, node.id, name, reactInstanceManager);
81
-		container.setId(CompatUtils.generateViewId());
82
-		return container;
83
-
75
+	private Layout createContainer(LayoutNode node) {
76
+		return new RootLayout(activity, node.id, node.data.optString("name"), reactInstanceManager);
84 77
 	}
85 78
 
86
-	private View createContainerStack(LayoutNode node) {
87
-		final ContainerStack containerStack = new ContainerStack(activity);
88
-		containerStack.setId(CompatUtils.generateViewId());
79
+	private Layout createContainerStack(LayoutNode node) {
80
+		final LayoutStack layoutStack = new LayoutStack(activity);
89 81
 		for (LayoutNode child : node.children) {
90
-			containerStack.addView(create(child));
82
+			layoutStack.push(create(child));
91 83
 		}
92
-		return containerStack;
84
+		return layoutStack;
93 85
 	}
94 86
 
95
-	private View createBottomTabs(LayoutNode node) {
96
-		final BottomTabsLayout tabsContainer = new BottomTabsLayout(activity, new BottomTabs());
87
+	private Layout createBottomTabs(LayoutNode node) {
88
+		final BottomTabsLayout tabsContainer = new BottomTabsLayout(activity);
97 89
 		for (int i = 0; i < node.children.size(); i++) {
98
-			final View tabContent = create(node.children.get(i));
90
+			final Layout tabContent = create(node.children.get(i));
99 91
 			tabsContainer.addTabContent("#" + i, tabContent);
100 92
 		}
101 93
 		return tabsContainer;

+ 0
- 28
lib/android/app/src/main/java/com/reactnativenavigation/layout/LayoutNode.java Ver fichero

@@ -1,8 +1,5 @@
1 1
 package com.reactnativenavigation.layout;
2 2
 
3
-import android.support.annotation.NonNull;
4
-
5
-import org.json.JSONArray;
6 3
 import org.json.JSONObject;
7 4
 
8 5
 import java.util.ArrayList;
@@ -19,31 +16,6 @@ public class LayoutNode {
19 16
 		SideMenuRight
20 17
 	}
21 18
 
22
-	@SuppressWarnings("unchecked")
23
-	public static LayoutNode parse(JSONObject layoutTree) {
24
-		String id = layoutTree.optString("id");
25
-		LayoutNode.Type type = LayoutNode.Type.valueOf(layoutTree.optString("type"));
26
-		JSONObject data = parseData(layoutTree);
27
-		List<LayoutNode> children = parseChildren(layoutTree);
28
-		return new LayoutNode(id, type, data, children);
29
-	}
30
-
31
-	@NonNull
32
-	private static List<LayoutNode> parseChildren(JSONObject layoutTree) {
33
-		List<LayoutNode> children = new ArrayList<>();
34
-		if (layoutTree.has("children")) {
35
-			JSONArray rawChildren = layoutTree.optJSONArray("children");
36
-			for (int i = 0; i < rawChildren.length(); i++) {
37
-				children.add(LayoutNode.parse(rawChildren.optJSONObject(i)));
38
-			}
39
-		}
40
-		return children;
41
-	}
42
-
43
-	private static JSONObject parseData(JSONObject layoutTree) {
44
-		return layoutTree.has("data") ? layoutTree.optJSONObject("data") : new JSONObject();
45
-	}
46
-
47 19
 	public final String id;
48 20
 	public final Type type;
49 21
 	public final JSONObject data;

+ 38
- 25
lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/BottomTabsLayout.java Ver fichero

@@ -4,34 +4,55 @@ import android.app.Activity;
4 4
 import android.view.View;
5 5
 import android.widget.RelativeLayout;
6 6
 
7
+import com.reactnativenavigation.layout.Layout;
8
+import com.reactnativenavigation.utils.CompatUtils;
9
+
7 10
 import java.util.ArrayList;
8 11
 import java.util.List;
9 12
 
10
-public class BottomTabsLayout extends RelativeLayout implements BottomTabs.BottomTabsSelectionListener {
13
+import static android.widget.RelativeLayout.ABOVE;
14
+
15
+public class BottomTabsLayout implements Layout, BottomTabs.BottomTabsSelectionListener {
11 16
 
12 17
 	public static class TooManyTabs extends RuntimeException {
13 18
 	}
14 19
 
15
-
16
-	private List<View> tabsContent;
17
-	private BottomTabs bottomTabs;
20
+	private final RelativeLayout view;
21
+	private final BottomTabs bottomTabs;
22
+	private final List<View> tabContentViews = new ArrayList<>();
18 23
 	private int currentTab;
19 24
 
20
-	public BottomTabsLayout(Activity activity, BottomTabs bottomTabs) {
21
-		super(activity);
22
-		initBottomTabs(bottomTabs);
25
+	public BottomTabsLayout(Activity activity) {
26
+		view = new RelativeLayout(activity);
27
+		view.setId(CompatUtils.generateViewId());
28
+
29
+		//TODO inline everything. unneeded complexity
30
+		bottomTabs = new BottomTabs();
31
+		bottomTabs.attach(view);
32
+		bottomTabs.setSelectionListener(this);
33
+	}
34
+
35
+	@Override
36
+	public View getView() {
37
+		return view;
38
+	}
39
+
40
+	@Override
41
+	public void destroy() {
42
+		//
23 43
 	}
24 44
 
25
-	public void addTabContent(String label, View tabContent) {
26
-		if (tabsContent.size() >= 5) {
45
+
46
+	public void addTabContent(String label, Layout tabContent) {
47
+		if (tabContentViews.size() >= 5) {
27 48
 			throw new TooManyTabs();
28 49
 		}
29 50
 		bottomTabs.add(label);
30
-		attachTabContent(tabContent);
31
-		tabsContent.add(tabContent);
51
+		attachTabContent(tabContent.getView());
52
+		tabContentViews.add(tabContent.getView());
32 53
 
33
-		if (tabsContent.size() > 1) {
34
-			tabContent.setVisibility(View.GONE);
54
+		if (tabContentViews.size() > 1) {
55
+			tabContent.getView().setVisibility(View.GONE);
35 56
 		}
36 57
 	}
37 58
 
@@ -42,25 +63,17 @@ public class BottomTabsLayout extends RelativeLayout implements BottomTabs.Botto
42 63
 		showTab(currentTab);
43 64
 	}
44 65
 
45
-	private void initBottomTabs(BottomTabs bottomTabs) {
46
-		this.bottomTabs = bottomTabs;
47
-		this.bottomTabs.attach(this);
48
-		this.bottomTabs.setSelectionListener(this);
49
-
50
-		tabsContent = new ArrayList<>();
51
-	}
52
-
53 66
 	private void attachTabContent(View tabContent) {
54
-		LayoutParams tabParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
67
+		RelativeLayout.LayoutParams tabParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
55 68
 		tabParams.addRule(ABOVE, bottomTabs.getViewId());
56
-		addView(tabContent, tabParams);
69
+		view.addView(tabContent, tabParams);
57 70
 	}
58 71
 
59 72
 	private void showTab(int tabId) {
60
-		tabsContent.get(tabId).setVisibility(View.VISIBLE);
73
+		tabContentViews.get(tabId).setVisibility(View.VISIBLE);
61 74
 	}
62 75
 
63 76
 	private void hideTab(int tabId) {
64
-		tabsContent.get(tabId).setVisibility(View.GONE);
77
+		tabContentViews.get(tabId).setVisibility(View.GONE);
65 78
 	}
66 79
 }

+ 0
- 63
lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/Container.java Ver fichero

@@ -1,63 +0,0 @@
1
-package com.reactnativenavigation.layout.containers;
2
-
3
-import android.app.Activity;
4
-import android.os.Bundle;
5
-import android.view.View;
6
-import android.widget.FrameLayout;
7
-
8
-import com.facebook.react.ReactInstanceManager;
9
-import com.facebook.react.ReactRootView;
10
-import com.reactnativenavigation.react.NavigationEventEmitter;
11
-
12
-public class Container extends FrameLayout {
13
-
14
-	private final String id;
15
-	private final String name;
16
-	private ReactRootView rootView;
17
-	private final ReactInstanceManager reactInstanceManager;
18
-
19
-
20
-	public Container(Activity activity, String id, String name, final ReactInstanceManager reactInstanceManager) {
21
-		super(activity);
22
-
23
-		this.id = id;
24
-		this.name = name;
25
-		this.reactInstanceManager = reactInstanceManager;
26
-		addView(createReactRootView());
27
-	}
28
-
29
-	@Override
30
-	protected void onDetachedFromWindow() {
31
-		super.onDetachedFromWindow();
32
-		onStop();
33
-	}
34
-
35
-
36
-	public void destroy() {
37
-		rootView.unmountReactApplication();
38
-	}
39
-
40
-	private View createReactRootView() {
41
-		rootView = new ReactRootView(getContext());
42
-		Bundle opts = new Bundle();
43
-		opts.putString("id", id);
44
-		rootView.startReactApplication(reactInstanceManager, name, opts);
45
-		rootView.setEventListener(new ReactRootView.ReactRootViewEventListener() {
46
-			@Override
47
-			public void onAttachedToReactInstance(final ReactRootView reactRootView) {
48
-				rootView.setEventListener(null);
49
-				onStart();
50
-			}
51
-		});
52
-		return rootView;
53
-	}
54
-
55
-	private void onStart() {
56
-		new NavigationEventEmitter(reactInstanceManager.getCurrentReactContext()).containerStart(id);
57
-	}
58
-
59
-	private void onStop() {
60
-		new NavigationEventEmitter(reactInstanceManager.getCurrentReactContext()).containerStop(id);
61
-	}
62
-
63
-}

+ 0
- 47
lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/ContainerStack.java Ver fichero

@@ -1,47 +0,0 @@
1
-package com.reactnativenavigation.layout.containers;
2
-
3
-import android.content.Context;
4
-import android.widget.FrameLayout;
5
-
6
-import java.util.Stack;
7
-
8
-public class ContainerStack extends FrameLayout {
9
-
10
-	private Stack<Container> stack = new Stack<>();
11
-
12
-	public ContainerStack(Context context) {
13
-		super(context);
14
-	}
15
-
16
-	public void push(Container view) {
17
-		stack.push(view);
18
-		addView(view);
19
-		if (stack.size() > 1) {
20
-			Container previousTop = stack.elementAt(stack.size() - 2);
21
-			removeView(previousTop);
22
-		}
23
-	}
24
-
25
-	public void pop() {
26
-		Container top = stack.pop();
27
-		removeView(top);
28
-		top.destroy();
29
-		if (!stack.isEmpty()) {
30
-			Container previousTop = stack.peek();
31
-			addView(previousTop);
32
-		}
33
-	}
34
-
35
-	public boolean onBackPressed() {
36
-		if (stack.isEmpty()) {
37
-			return false;
38
-		} else {
39
-			pop();
40
-			return true;
41
-		}
42
-	}
43
-
44
-	public boolean isEmpty() {
45
-		return stack.isEmpty();
46
-	}
47
-}

+ 59
- 0
lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/LayoutStack.java Ver fichero

@@ -0,0 +1,59 @@
1
+package com.reactnativenavigation.layout.containers;
2
+
3
+import android.content.Context;
4
+import android.view.View;
5
+import android.widget.FrameLayout;
6
+
7
+import com.reactnativenavigation.layout.Layout;
8
+import com.reactnativenavigation.utils.CompatUtils;
9
+
10
+import java.util.Stack;
11
+
12
+public class LayoutStack implements Layout {
13
+
14
+	private final Stack<Layout> stack = new Stack<>();
15
+	private final FrameLayout view;
16
+
17
+	public LayoutStack(Context context) {
18
+		view = new FrameLayout(context);
19
+		view.setId(CompatUtils.generateViewId());
20
+	}
21
+
22
+	public void push(Layout child) {
23
+		stack.push(child);
24
+		view.addView(child.getView());
25
+		if (stack.size() > 1) {
26
+			Layout previousTop = stack.elementAt(stack.size() - 2);
27
+			view.removeView(previousTop.getView());
28
+		}
29
+	}
30
+
31
+	public void pop() {
32
+		Layout top = stack.pop();
33
+		view.removeView(top.getView());
34
+		top.destroy();
35
+		if (!stack.isEmpty()) {
36
+			Layout previousTop = stack.peek();
37
+			view.addView(previousTop.getView());
38
+		}
39
+	}
40
+
41
+	public boolean onBackPressed() {
42
+		if (stack.isEmpty()) {
43
+			return false;
44
+		} else {
45
+			pop();
46
+			return true;
47
+		}
48
+	}
49
+
50
+	@Override
51
+	public View getView() {
52
+		return view;
53
+	}
54
+
55
+	@Override
56
+	public void destroy() {
57
+		//
58
+	}
59
+}

+ 70
- 0
lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/RootLayout.java Ver fichero

@@ -0,0 +1,70 @@
1
+package com.reactnativenavigation.layout.containers;
2
+
3
+import android.app.Activity;
4
+import android.os.Bundle;
5
+import android.view.View;
6
+import android.widget.FrameLayout;
7
+
8
+import com.facebook.react.ReactInstanceManager;
9
+import com.facebook.react.ReactRootView;
10
+import com.reactnativenavigation.layout.Layout;
11
+import com.reactnativenavigation.react.NavigationEventEmitter;
12
+import com.reactnativenavigation.utils.CompatUtils;
13
+
14
+public class RootLayout implements Layout, View.OnAttachStateChangeListener {
15
+
16
+	private final String id;
17
+	private final String name;
18
+	private final FrameLayout view;
19
+	private final ReactRootView reactRootView;
20
+	private final ReactInstanceManager reactInstanceManager;
21
+
22
+	public RootLayout(Activity activity, String id, String name, final ReactInstanceManager reactInstanceManager) {
23
+		this.id = id;
24
+		this.name = name;
25
+		this.reactInstanceManager = reactInstanceManager;
26
+		reactRootView = new ReactRootView(activity);
27
+		reactRootView.addOnAttachStateChangeListener(this);
28
+		Bundle opts = new Bundle();
29
+		opts.putString("id", this.id);
30
+		reactRootView.startReactApplication(this.reactInstanceManager, this.name, opts);
31
+		reactRootView.setEventListener(new ReactRootView.ReactRootViewEventListener() {
32
+			@Override
33
+			public void onAttachedToReactInstance(final ReactRootView reactRootView) {
34
+				reactRootView.setEventListener(null);
35
+				onStart();
36
+			}
37
+		});
38
+		view = new FrameLayout(activity);
39
+		view.addView(reactRootView);
40
+		view.setId(CompatUtils.generateViewId());
41
+	}
42
+
43
+	@Override
44
+	public void destroy() {
45
+		reactRootView.unmountReactApplication();
46
+	}
47
+
48
+	@Override
49
+	public void onViewAttachedToWindow(final View v) {
50
+		//
51
+	}
52
+
53
+	@Override
54
+	public void onViewDetachedFromWindow(final View v) {
55
+		onStop();
56
+	}
57
+
58
+	@Override
59
+	public View getView() {
60
+		return view;
61
+	}
62
+
63
+	private void onStart() {
64
+		new NavigationEventEmitter(reactInstanceManager.getCurrentReactContext()).containerStart(id);
65
+	}
66
+
67
+	private void onStop() {
68
+		new NavigationEventEmitter(reactInstanceManager.getCurrentReactContext()).containerStop(id);
69
+	}
70
+}

+ 43
- 2
lib/android/app/src/main/java/com/reactnativenavigation/layout/containers/SideMenuLayout.java Ver fichero

@@ -2,11 +2,52 @@ package com.reactnativenavigation.layout.containers;
2 2
 
3 3
 import android.content.Context;
4 4
 import android.support.v4.widget.DrawerLayout;
5
+import android.view.Gravity;
6
+import android.view.View;
5 7
 
6
-public class SideMenuLayout extends DrawerLayout {
8
+import com.reactnativenavigation.layout.Layout;
9
+import com.reactnativenavigation.utils.CompatUtils;
10
+
11
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
12
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
13
+
14
+public class SideMenuLayout implements Layout {
15
+
16
+	private DrawerLayout view;
7 17
 
8 18
 	public SideMenuLayout(Context context) {
9
-		super(context);
19
+		view = new DrawerLayout(context);
20
+		view.setId(CompatUtils.generateViewId());
21
+	}
22
+
23
+	@Override
24
+	public View getView() {
25
+		return view;
26
+	}
27
+
28
+	@Override
29
+	public void destroy() {
30
+		//
31
+	}
32
+
33
+	public void addLeftLayout(final Layout childLayout) {
34
+		View child = childLayout.getView();
35
+		DrawerLayout.LayoutParams lp = new DrawerLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
36
+		lp.gravity = Gravity.LEFT;
37
+		child.setLayoutParams(lp);
38
+		view.addView(child);
10 39
 	}
11 40
 
41
+	public void addRightLayout(final Layout childLayout) {
42
+		View child = childLayout.getView();
43
+		DrawerLayout.LayoutParams lp = new DrawerLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT);
44
+		lp.gravity = Gravity.RIGHT;
45
+		child.setLayoutParams(lp);
46
+		view.addView(child);
47
+	}
48
+
49
+	public void addCenterLayout(final Layout childLayout) {
50
+		View child = childLayout.getView();
51
+		view.addView(child);
52
+	}
12 53
 }

lib/android/app/src/main/java/com/reactnativenavigation/react/ArgsParser.java → lib/android/app/src/main/java/com/reactnativenavigation/parse/JSONParser.java Ver fichero

@@ -1,4 +1,4 @@
1
-package com.reactnativenavigation.react;
1
+package com.reactnativenavigation.parse;
2 2
 
3 3
 import com.facebook.react.bridge.ReadableArray;
4 4
 import com.facebook.react.bridge.ReadableMap;
@@ -8,7 +8,7 @@ import org.json.JSONArray;
8 8
 import org.json.JSONException;
9 9
 import org.json.JSONObject;
10 10
 
11
-public class ArgsParser {
11
+public class JSONParser {
12 12
 	public static JSONObject parse(ReadableMap map) {
13 13
 		try {
14 14
 			ReadableMapKeySetIterator it = map.keySetIterator();

+ 39
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutNodeParser.java Ver fichero

@@ -0,0 +1,39 @@
1
+package com.reactnativenavigation.parse;
2
+
3
+import android.support.annotation.NonNull;
4
+
5
+import com.reactnativenavigation.layout.LayoutNode;
6
+
7
+import org.json.JSONArray;
8
+import org.json.JSONObject;
9
+
10
+import java.util.ArrayList;
11
+import java.util.List;
12
+
13
+public class LayoutNodeParser {
14
+
15
+	@SuppressWarnings("unchecked")
16
+	public static LayoutNode parse(JSONObject layoutTree) {
17
+		String id = layoutTree.optString("id");
18
+		LayoutNode.Type type = LayoutNode.Type.valueOf(layoutTree.optString("type"));
19
+		JSONObject data = parseData(layoutTree);
20
+		List<LayoutNode> children = parseChildren(layoutTree);
21
+		return new LayoutNode(id, type, data, children);
22
+	}
23
+
24
+	@NonNull
25
+	private static List<LayoutNode> parseChildren(JSONObject layoutTree) {
26
+		List<LayoutNode> children = new ArrayList<>();
27
+		if (layoutTree.has("children")) {
28
+			JSONArray rawChildren = layoutTree.optJSONArray("children");
29
+			for (int i = 0; i < rawChildren.length(); i++) {
30
+				children.add(parse(rawChildren.optJSONObject(i)));
31
+			}
32
+		}
33
+		return children;
34
+	}
35
+
36
+	private static JSONObject parseData(JSONObject layoutTree) {
37
+		return layoutTree.has("data") ? layoutTree.optJSONObject("data") : new JSONObject();
38
+	}
39
+}

+ 13
- 13
lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java Ver fichero

@@ -1,17 +1,17 @@
1 1
 package com.reactnativenavigation.react;
2 2
 
3
-import android.view.View;
4
-
5 3
 import com.facebook.react.ReactInstanceManager;
6 4
 import com.facebook.react.bridge.ReactApplicationContext;
7 5
 import com.facebook.react.bridge.ReactContextBaseJavaModule;
8 6
 import com.facebook.react.bridge.ReactMethod;
9 7
 import com.facebook.react.bridge.ReadableMap;
10 8
 import com.reactnativenavigation.NavigationActivity;
9
+import com.reactnativenavigation.layout.Layout;
11 10
 import com.reactnativenavigation.layout.LayoutFactory;
12 11
 import com.reactnativenavigation.layout.LayoutNode;
13
-import com.reactnativenavigation.layout.containers.Container;
14
-import com.reactnativenavigation.layout.containers.ContainerStack;
12
+import com.reactnativenavigation.layout.containers.LayoutStack;
13
+import com.reactnativenavigation.parse.JSONParser;
14
+import com.reactnativenavigation.parse.LayoutNodeParser;
15 15
 import com.reactnativenavigation.utils.UiThread;
16 16
 
17 17
 public class NavigationModule extends ReactContextBaseJavaModule {
@@ -29,27 +29,27 @@ public class NavigationModule extends ReactContextBaseJavaModule {
29 29
 	}
30 30
 
31 31
 	@ReactMethod
32
-	public void setRoot(final ReadableMap layoutTree) {
32
+	public void setRoot(final ReadableMap rawLayoutTree) {
33 33
 		handle(new Runnable() {
34 34
 			@Override
35 35
 			public void run() {
36
-				final LayoutNode layoutTreeRoot = LayoutNode.parse(ArgsParser.parse(layoutTree));
36
+				final LayoutNode layoutTree = LayoutNodeParser.parse(JSONParser.parse(rawLayoutTree));
37 37
 				LayoutFactory factory = new LayoutFactory(activity(), reactInstanceManager);
38
-				final View rootView = factory.create(layoutTreeRoot);
39
-				activity().setContentView(rootView);
38
+				final Layout rootView = factory.create(layoutTree);
39
+				activity().setContentView(rootView.getView());
40 40
 			}
41 41
 		});
42 42
 	}
43 43
 
44 44
 	@ReactMethod
45
-	public void push(final String onContainerId, final ReadableMap layoutTree) {
45
+	public void push(final String onContainerId, final ReadableMap rawLayoutTree) {
46 46
 		handle(new Runnable() {
47 47
 			@Override
48 48
 			public void run() {
49
-				final LayoutNode layoutNode = LayoutNode.parse(ArgsParser.parse(layoutTree));
49
+				final LayoutNode layoutTree = LayoutNodeParser.parse(JSONParser.parse(rawLayoutTree));
50 50
 				LayoutFactory factory = new LayoutFactory(activity(), reactInstanceManager);
51
-				final View rootView = factory.create(layoutNode);
52
-				((ContainerStack) activity().getContentView()).push((Container) rootView);
51
+				final Layout rootView = factory.create(layoutTree);
52
+				((LayoutStack) activity().getContentView()).push(rootView);
53 53
 			}
54 54
 		});
55 55
 	}
@@ -59,7 +59,7 @@ public class NavigationModule extends ReactContextBaseJavaModule {
59 59
 		handle(new Runnable() {
60 60
 			@Override
61 61
 			public void run() {
62
-				((ContainerStack) activity().getContentView()).pop();
62
+				((LayoutStack) activity().getContentView()).pop();
63 63
 			}
64 64
 		});
65 65
 	}

lib/android/app/src/test/java/com/reactnativenavigation/react/ArgsParserTest.java → lib/android/app/src/test/java/com/reactnativenavigation/parse/JSONParserTest.java Ver fichero

@@ -1,8 +1,9 @@
1
-package com.reactnativenavigation.react;
1
+package com.reactnativenavigation.parse;
2 2
 
3 3
 import com.facebook.react.bridge.JavaOnlyArray;
4 4
 import com.facebook.react.bridge.JavaOnlyMap;
5 5
 import com.reactnativenavigation.BaseTest;
6
+import com.reactnativenavigation.parse.JSONParser;
6 7
 
7 8
 import org.json.JSONArray;
8 9
 import org.json.JSONObject;
@@ -10,7 +11,7 @@ import org.junit.Test;
10 11
 
11 12
 import static org.assertj.core.api.Java6Assertions.assertThat;
12 13
 
13
-public class ArgsParserTest extends BaseTest {
14
+public class JSONParserTest extends BaseTest {
14 15
 	@Test
15 16
 	public void parsesMap() throws Exception {
16 17
 		JavaOnlyMap input = new JavaOnlyMap();
@@ -22,7 +23,7 @@ public class ArgsParserTest extends BaseTest {
22 23
 		input.putMap("keyMap", new JavaOnlyMap());
23 24
 		input.putNull("bla");
24 25
 
25
-		JSONObject result = ArgsParser.parse(input);
26
+		JSONObject result = JSONParser.parse(input);
26 27
 
27 28
 
28 29
 		assertThat(result.keys()).containsOnly(
@@ -52,7 +53,7 @@ public class ArgsParserTest extends BaseTest {
52 53
 		input.pushMap(new JavaOnlyMap());
53 54
 		input.pushNull();
54 55
 
55
-		JSONArray result = ArgsParser.parse(input);
56
+		JSONArray result = JSONParser.parse(input);
56 57
 		assertThat(result.length()).isEqualTo(6);
57 58
 		assertThat(result.get(0)).isEqualTo("Hello");
58 59
 		assertThat(result.get(1)).isEqualTo(123);

lib/android/app/src/test/java/com/reactnativenavigation/layout/LayoutNodeTest.java → lib/android/app/src/test/java/com/reactnativenavigation/parse/LayoutNodeParserTest.java Ver fichero

@@ -1,13 +1,14 @@
1
-package com.reactnativenavigation.layout;
1
+package com.reactnativenavigation.parse;
2 2
 
3 3
 import com.reactnativenavigation.BaseTest;
4
+import com.reactnativenavigation.layout.LayoutNode;
4 5
 
5 6
 import org.json.JSONObject;
6 7
 import org.junit.Test;
7 8
 
8 9
 import static org.assertj.core.api.Java6Assertions.assertThat;
9 10
 
10
-public class LayoutNodeTest extends BaseTest {
11
+public class LayoutNodeParserTest extends BaseTest {
11 12
 	@Test
12 13
 	public void dto() throws Exception {
13 14
 		LayoutNode node = new LayoutNode("the id", LayoutNode.Type.Container);
@@ -34,7 +35,7 @@ public class LayoutNodeTest extends BaseTest {
34 35
 				"data: {dataKey: dataValue}, " +
35 36
 				"children: [{id: childId1, type: Container}]}");
36 37
 
37
-		LayoutNode result = LayoutNode.parse(tree);
38
+		LayoutNode result = LayoutNodeParser.parse(tree);
38 39
 
39 40
 		assertThat(result).isNotNull();
40 41
 		assertThat(result.id).isEqualTo("node1");