Browse Source

navigationOptions

Daniel Zlotin 7 years ago
parent
commit
30d0111f16

+ 2
- 2
lib/android/app/src/main/java/com/reactnativenavigation/layout/LayoutFactory.java View File

@@ -3,8 +3,8 @@ package com.reactnativenavigation.layout;
3 3
 import android.app.Activity;
4 4
 
5 5
 import com.facebook.react.ReactInstanceManager;
6
-import com.reactnativenavigation.viewcontrollers.SideMenuController;
7 6
 import com.reactnativenavigation.viewcontrollers.BottomTabsController;
7
+import com.reactnativenavigation.viewcontrollers.SideMenuController;
8 8
 import com.reactnativenavigation.viewcontrollers.StackController;
9 9
 import com.reactnativenavigation.viewcontrollers.ViewController;
10 10
 
@@ -76,7 +76,7 @@ public class LayoutFactory {
76 76
 	}
77 77
 
78 78
 	private ViewController createContainer(LayoutNode node) {
79
-		return new ReactRootViewController(activity, node.id, node.data.optString("name"), reactInstanceManager);
79
+		return new ReactRootViewController(activity, node.id, node.data.optString("name"), node.data.optJSONObject("navigationOptions").optString("title"), reactInstanceManager);
80 80
 	}
81 81
 
82 82
 	private ViewController createContainerStack(LayoutNode node) {

+ 4
- 1
lib/android/app/src/main/java/com/reactnativenavigation/layout/ReactRootViewController.java View File

@@ -13,13 +13,15 @@ import com.reactnativenavigation.viewcontrollers.ViewController;
13 13
 public class ReactRootViewController extends ViewController {
14 14
 
15 15
 	private final String name;
16
+	private final String title;
16 17
 	private final ReactInstanceManager reactInstanceManager;
17 18
 	private boolean attachedToReactInstance = false;
18 19
 	private ReactRootView reactRootView;
19 20
 
20
-	public ReactRootViewController(final Activity activity, final String id, final String name, final ReactInstanceManager reactInstanceManager) {
21
+	public ReactRootViewController(final Activity activity, final String id, final String name, String title, final ReactInstanceManager reactInstanceManager) {
21 22
 		super(activity, id);
22 23
 		this.name = name;
24
+		this.title = title;
23 25
 		this.reactInstanceManager = reactInstanceManager;
24 26
 	}
25 27
 
@@ -33,6 +35,7 @@ public class ReactRootViewController extends ViewController {
33 35
 	@Override
34 36
 	public void onViewAppeared() {
35 37
 		super.onViewAppeared();
38
+		if (getParentStackController() != null) getParentStackController().setTitle(title);
36 39
 		new NavigationEvent(reactInstanceManager.getCurrentReactContext()).containerStart(getId());
37 40
 	}
38 41
 

+ 29
- 12
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java View File

@@ -2,16 +2,20 @@ package com.reactnativenavigation.viewcontrollers;
2 2
 
3 3
 import android.app.Activity;
4 4
 import android.support.annotation.NonNull;
5
+import android.view.View;
5 6
 import android.view.ViewGroup;
6
-import android.widget.FrameLayout;
7
+import android.widget.LinearLayout;
7 8
 
8 9
 import com.reactnativenavigation.anim.StackAnimator;
10
+import com.reactnativenavigation.utils.CompatUtils;
11
+import com.reactnativenavigation.views.TopBar;
9 12
 
10 13
 import java.util.Collection;
11 14
 
12 15
 public class StackController extends ParentController {
13 16
 	private final IdStack<ViewController> stack = new IdStack<>();
14
-	private StackAnimator animator;
17
+	private final StackAnimator animator;
18
+	private TopBar topBar;
15 19
 
16 20
 	public StackController(final Activity activity, String id) {
17 21
 		this(activity, id, new StackAnimator(activity));
@@ -29,7 +33,7 @@ public class StackController extends ParentController {
29 33
 		stack.push(child.getId(), child);
30 34
 
31 35
 		getView().addView(child.getView());
32
-
36
+//TODO animate only when needed
33 37
 		if (previousTop != null) {
34 38
 			animator.animatePush(child.getView(), previousTop.getView(), new Runnable() {
35 39
 				@Override
@@ -50,15 +54,19 @@ public class StackController extends ParentController {
50 54
 		final ViewController poppedTop = stack.pop();
51 55
 		ViewController newTop = peek();
52 56
 
53
-		getView().addView(newTop.getView());
57
+		final View enteringView = newTop.getView();
58
+		final View exitingView = poppedTop.getView();
59
+
60
+		getView().addView(enteringView);
54 61
 
55
-		animator.animatePop(newTop.getView(), poppedTop.getView(), new Runnable() {
56
-			@Override
57
-			public void run() {
58
-				getView().removeView(poppedTop.getView());
59
-				poppedTop.destroy();
60
-			}
61
-		});
62
+		//TODO animate only when needed
63
+//		animator.animatePop(enteringView, exitingView, new Runnable() {
64
+//			@Override
65
+//			public void run() {
66
+		getView().removeView(exitingView);
67
+		poppedTop.destroy();
68
+//			}
69
+//		});
62 70
 	}
63 71
 
64 72
 	public void popSpecific(final ViewController childController) {
@@ -110,7 +118,12 @@ public class StackController extends ParentController {
110 118
 	@NonNull
111 119
 	@Override
112 120
 	protected ViewGroup createView() {
113
-		return new FrameLayout(getActivity());
121
+		LinearLayout root = new LinearLayout(getActivity());
122
+		root.setOrientation(LinearLayout.VERTICAL);
123
+		topBar = new TopBar(getActivity());
124
+		topBar.setId(CompatUtils.generateViewId());
125
+		root.addView(topBar);
126
+		return root;
114 127
 	}
115 128
 
116 129
 	@NonNull
@@ -118,4 +131,8 @@ public class StackController extends ParentController {
118 131
 	public Collection<ViewController> getChildControllers() {
119 132
 		return stack.values();
120 133
 	}
134
+
135
+	public void setTitle(final String title) {
136
+		topBar.setTitle(title);
137
+	}
121 138
 }

+ 2
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java View File

@@ -7,6 +7,7 @@ import android.view.View;
7 7
 import android.view.ViewGroup;
8 8
 import android.view.ViewTreeObserver;
9 9
 
10
+import com.reactnativenavigation.utils.CompatUtils;
10 11
 import com.reactnativenavigation.utils.StringUtils;
11 12
 
12 13
 public abstract class ViewController implements ViewTreeObserver.OnGlobalLayoutListener {
@@ -46,6 +47,7 @@ public abstract class ViewController implements ViewTreeObserver.OnGlobalLayoutL
46 47
 	public View getView() {
47 48
 		if (view == null) {
48 49
 			view = createView();
50
+			view.setId(CompatUtils.generateViewId());
49 51
 			view.getViewTreeObserver().addOnGlobalLayoutListener(this);
50 52
 		}
51 53
 		return view;

+ 18
- 0
lib/android/app/src/main/java/com/reactnativenavigation/views/TopBar.java View File

@@ -0,0 +1,18 @@
1
+package com.reactnativenavigation.views;
2
+
3
+import android.app.Activity;
4
+import android.support.design.widget.AppBarLayout;
5
+import android.support.v7.widget.Toolbar;
6
+
7
+public class TopBar extends AppBarLayout {
8
+	private final Toolbar titleBar;
9
+
10
+	public TopBar(final Activity context) {
11
+		super(context);
12
+		titleBar = new Toolbar(context);
13
+	}
14
+
15
+	public void setTitle(String title) {
16
+		titleBar.setTitle(title);
17
+	}
18
+}

+ 18
- 0
lib/android/app/src/test/java/com/reactnativenavigation/BaseTest.java View File

@@ -1,6 +1,8 @@
1 1
 package com.reactnativenavigation;
2 2
 
3 3
 import android.app.Activity;
4
+import android.view.View;
5
+import android.view.ViewGroup;
4 6
 
5 7
 import org.junit.After;
6 8
 import org.junit.Before;
@@ -9,6 +11,8 @@ import org.robolectric.Robolectric;
9 11
 import org.robolectric.RobolectricTestRunner;
10 12
 import org.robolectric.annotation.Config;
11 13
 
14
+import static org.assertj.core.api.Java6Assertions.assertThat;
15
+
12 16
 @RunWith(RobolectricTestRunner.class)
13 17
 @Config(sdk = 25, constants = BuildConfig.class, manifest = "/../../../../../src/test/AndroidManifest.xml")
14 18
 public abstract class BaseTest {
@@ -25,4 +29,18 @@ public abstract class BaseTest {
25 29
 	public Activity newActivity() {
26 30
 		return Robolectric.setupActivity(Activity.class);
27 31
 	}
32
+
33
+	public void assertIsChildById(ViewGroup parent, View child) {
34
+		assertThat(parent).isNotNull();
35
+		assertThat(child).isNotNull();
36
+		assertThat(child.getId()).isNotZero().isPositive();
37
+		assertThat(parent.findViewById(child.getId())).isNotNull().isEqualTo(child);
38
+	}
39
+
40
+	public void assertNotChildOf(ViewGroup parent, View child) {
41
+		assertThat(parent).isNotNull();
42
+		assertThat(child).isNotNull();
43
+		assertThat(child.getId()).isNotZero().isPositive();
44
+		assertThat(parent.findViewById(child.getId())).isNull();
45
+	}
28 46
 }

+ 7
- 13
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/NavigatorTest.java View File

@@ -2,7 +2,6 @@ package com.reactnativenavigation.viewcontrollers;
2 2
 
3 3
 import android.app.Activity;
4 4
 import android.support.annotation.NonNull;
5
-import android.view.ViewGroup;
6 5
 
7 6
 import com.reactnativenavigation.BaseTest;
8 7
 import com.reactnativenavigation.mocks.SimpleViewController;
@@ -44,14 +43,14 @@ public class NavigatorTest extends BaseTest {
44 43
 	public void setRoot_AddsChildControllerView() throws Exception {
45 44
 		assertThat(uut.getView().getChildCount()).isZero();
46 45
 		uut.setRoot(child1);
47
-		assertHasSingleChildViewOf(uut, child1);
46
+		assertIsChildById(uut.getView(), child1.getView());
48 47
 	}
49 48
 
50 49
 	@Test
51 50
 	public void setRoot_ReplacesExistingChildControllerViews() throws Exception {
52 51
 		uut.setRoot(child1);
53 52
 		uut.setRoot(child2);
54
-		assertHasSingleChildViewOf(uut, child2);
53
+		assertIsChildById(uut.getView(), child2.getView());
55 54
 	}
56 55
 
57 56
 	@Test
@@ -66,20 +65,20 @@ public class NavigatorTest extends BaseTest {
66 65
 		stackController.push(child1);
67 66
 		uut.setRoot(stackController);
68 67
 
69
-		assertHasSingleChildViewOf(uut, stackController);
70
-		assertHasSingleChildViewOf(stackController, child1);
68
+		assertIsChildById(uut.getView(), stackController.getView());
69
+		assertIsChildById(stackController.getView(), child1.getView());
71 70
 
72 71
 		uut.push(child1.getId(), child2);
73 72
 
74
-		assertHasSingleChildViewOf(uut, stackController);
75
-		assertHasSingleChildViewOf(stackController, child2);
73
+		assertIsChildById(uut.getView(), stackController.getView());
74
+		assertIsChildById(stackController.getView(), child2.getView());
76 75
 	}
77 76
 
78 77
 	@Test
79 78
 	public void push_InvalidPushWithoutAStack_DoesNothing() throws Exception {
80 79
 		uut.setRoot(child1);
81 80
 		uut.push(child1.getId(), child2);
82
-		assertHasSingleChildViewOf(uut, child1);
81
+		assertIsChildById(uut.getView(), child1.getView());
83 82
 	}
84 83
 
85 84
 	@Test
@@ -193,11 +192,6 @@ public class NavigatorTest extends BaseTest {
193 192
 		return new BottomTabsController(activity, "tabsController");
194 193
 	}
195 194
 
196
-	private void assertHasSingleChildViewOf(ViewController parent, ViewController child) {
197
-		assertThat(((ViewGroup) parent.getView()).getChildCount()).isEqualTo(1);
198
-		assertThat(((ViewGroup) parent.getView()).getChildAt(0)).isEqualTo(child.getView()).isNotNull();
199
-	}
200
-
201 195
 	@NonNull
202 196
 	private StackController newStack() {
203 197
 		return new StackController(activity, "stack" + CompatUtils.generateViewId(), new TestStackAnimator());

+ 13
- 26
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/StackControllerTest.java View File

@@ -1,8 +1,6 @@
1 1
 package com.reactnativenavigation.viewcontrollers;
2 2
 
3 3
 import android.app.Activity;
4
-import android.view.ViewGroup;
5
-import android.widget.FrameLayout;
6 4
 
7 5
 import com.reactnativenavigation.BaseTest;
8 6
 import com.reactnativenavigation.mocks.SimpleViewController;
@@ -126,37 +124,32 @@ public class StackControllerTest extends BaseTest {
126 124
 		assertThat(uut.canPop()).isTrue();
127 125
 	}
128 126
 
129
-	@Test
130
-	public void constructsSelfWithFrameLayout() throws Exception {
131
-		assertThat(uut.getView())
132
-				.isNotNull()
133
-				.isInstanceOf(ViewGroup.class)
134
-				.isInstanceOf(FrameLayout.class);
135
-	}
136
-
137 127
 	@Test
138 128
 	public void pushAddsToViewTree() throws Exception {
139
-		assertThat(uut.getView().getChildCount()).isZero();
129
+		assertThat(uut.getView().findViewById(child1.getView().getId())).isNull();
140 130
 		uut.push(child1);
141
-		assertHasSingleChildViewOfController(child1);
131
+		assertThat(uut.getView().findViewById(child1.getView().getId())).isNotNull();
142 132
 	}
143 133
 
144 134
 	@Test
145 135
 	public void pushRemovesPreviousFromTree() throws Exception {
146
-		assertThat(uut.getView().getChildCount()).isZero();
136
+		assertThat(uut.getView().findViewById(child1.getView().getId())).isNull();
147 137
 		uut.push(child1);
148
-		assertHasSingleChildViewOfController(child1);
138
+		assertThat(uut.getView().findViewById(child1.getView().getId())).isNotNull();
149 139
 		uut.push(child2);
150
-		assertHasSingleChildViewOfController(child2);
140
+		assertThat(uut.getView().findViewById(child1.getView().getId())).isNull();
141
+		assertThat(uut.getView().findViewById(child2.getView().getId())).isNotNull();
151 142
 	}
152 143
 
153 144
 	@Test
154 145
 	public void popReplacesViewWithPrevious() throws Exception {
155 146
 		uut.push(child1);
156 147
 		uut.push(child2);
157
-		assertHasSingleChildViewOfController(child2);
148
+		assertIsChildById(uut.getView(), child2.getView());
149
+		assertNotChildOf(uut.getView(), child1.getView());
158 150
 		uut.pop();
159
-		assertHasSingleChildViewOfController(child1);
151
+		assertNotChildOf(uut.getView(), child2.getView());
152
+		assertIsChildById(uut.getView(), child1.getView());
160 153
 	}
161 154
 
162 155
 	@Test
@@ -165,18 +158,17 @@ public class StackControllerTest extends BaseTest {
165 158
 		uut.push(child2);
166 159
 		uut.popSpecific(child2);
167 160
 		assertContainsOnlyId(child1.getId());
168
-		assertHasSingleChildViewOfController(child1);
161
+		assertIsChildById(uut.getView(), child1.getView());
169 162
 	}
170 163
 
171 164
 	@Test
172 165
 	public void popSpecificDeepInStack() throws Exception {
173 166
 		uut.push(child1);
174 167
 		uut.push(child2);
175
-		assertHasSingleChildViewOfController(child2);
176
-
168
+		assertIsChildById(uut.getView(), child2.getView());
177 169
 		uut.popSpecific(child1);
178 170
 		assertContainsOnlyId(child2.getId());
179
-		assertHasSingleChildViewOfController(child2);
171
+		assertIsChildById(uut.getView(), child2.getView());
180 172
 	}
181 173
 
182 174
 	@Test
@@ -285,11 +277,6 @@ public class StackControllerTest extends BaseTest {
285 277
 		verify(child3, times(1)).destroy();
286 278
 	}
287 279
 
288
-	private void assertHasSingleChildViewOfController(ViewController childController) {
289
-		assertThat(uut.getView().getChildCount()).isEqualTo(1);
290
-		assertThat(uut.getView().getChildAt(0)).isEqualTo(childController.getView());
291
-	}
292
-
293 280
 	private void assertContainsOnlyId(String... ids) {
294 281
 		assertThat(uut.size()).isEqualTo(ids.length);
295 282
 		assertThat(uut.getChildControllers()).extracting(new Extractor<ViewController, String>() {

+ 5
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ViewControllerTest.java View File

@@ -172,6 +172,11 @@ public class ViewControllerTest extends BaseTest {
172 172
 		verify(spy, times(1)).onViewDisappear();
173 173
 	}
174 174
 
175
+	@Test
176
+	public void assignsIdToCreatedView() throws Exception {
177
+		assertThat(uut.getView().getId()).isPositive();
178
+	}
179
+
175 180
 	@Test
176 181
 	public void onDestroy_RemovesSelfFromParentIfExists() throws Exception {
177 182
 		LinearLayout parent = new LinearLayout(activity);

+ 1
- 1
playground/src/containers/OptionsScreen.js View File

@@ -22,7 +22,7 @@ class OptionsScreen extends Component {
22 22
   render() {
23 23
     return (
24 24
       <View style={styles.root}>
25
-        <Text style={styles.h1}>{`Style Screen`}</Text>
25
+        <Text style={styles.h1}>{`Options Screen`}</Text>
26 26
         <Button title="Dynamic Options" onPress={this.onClickDynamicOptions} />
27 27
         <Text style={styles.footer}>{`this.props.id = ${this.props.id}`}</Text>
28 28
       </View>