Browse Source

Removed NavigationOptionsListener

This commit removes NavigationOptionsListener as it was not needed anymore.
As a result, it uncovered a few issues which this commit also aims to fix.

* Set SideMenuController as parent of left, right and centre controllers
* Select tab by id with tabSelector interface
* mergeOptions now also applies options after merge - in ViewController base class
* Pull presentation logic from ComponentLayout to ComponentViewController
Guy Carmeli 6 years ago
parent
commit
6a69287242
26 changed files with 277 additions and 299 deletions
  1. 8
    7
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java
  2. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/BottomTabsOptionsPresenter.java
  3. 0
    31
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/ComponentOptionsPresenter.java
  4. 0
    8
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/NavigationOptionsListener.java
  5. 11
    166
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java
  6. 187
    0
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/StackOptionsPresenter.java
  7. 3
    4
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ComponentViewController.java
  8. 2
    6
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/Navigator.java
  9. 11
    4
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/SideMenuController.java
  10. 0
    5
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java
  11. 12
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java
  12. 1
    8
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java
  13. 0
    5
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewController.java
  14. 1
    7
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java
  15. 0
    3
      lib/android/app/src/main/java/com/reactnativenavigation/views/Component.java
  16. 0
    5
      lib/android/app/src/main/java/com/reactnativenavigation/views/ComponentLayout.java
  17. 0
    7
      lib/android/app/src/main/java/com/reactnativenavigation/views/ExternalComponentLayout.java
  18. 3
    3
      lib/android/app/src/main/java/com/reactnativenavigation/views/StackLayout.java
  19. 4
    5
      lib/android/app/src/main/java/com/reactnativenavigation/views/toptabs/TopTabsViewPager.java
  20. 8
    6
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleViewController.java
  21. 0
    2
      lib/android/app/src/test/java/com/reactnativenavigation/parse/OptionsTest.java
  22. 16
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/BottomTabsControllerTest.java
  23. 3
    3
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsMergingTest.java
  24. 3
    3
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/SideMenuControllerTest.java
  25. 1
    8
      playground/src/screens/TextScreen.js
  26. 1
    0
      playground/src/screens/WelcomeScreen.js

+ 8
- 7
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java View File

@@ -72,24 +72,25 @@ public class LayoutFactory {
72 72
 	}
73 73
 
74 74
     private ViewController createSideMenuRoot(LayoutNode node) {
75
-        SideMenuController sideMenuLayout = new SideMenuController(activity, node.id, getOptions(node));
75
+        SideMenuController sideMenuController = new SideMenuController(activity, node.id, getOptions(node));
76 76
 		for (LayoutNode child : node.children) {
77
-			ViewController childLayout = create(child);
77
+			ViewController childController = create(child);
78
+            childController.setParentController(sideMenuController);
78 79
 			switch (child.type) {
79 80
 				case SideMenuCenter:
80
-					sideMenuLayout.setCenterController(childLayout);
81
+					sideMenuController.setCenterController(childController);
81 82
 					break;
82 83
 				case SideMenuLeft:
83
-					sideMenuLayout.setLeftController(childLayout);
84
+					sideMenuController.setLeftController(childController);
84 85
 					break;
85 86
 				case SideMenuRight:
86
-					sideMenuLayout.setRightController(childLayout);
87
+					sideMenuController.setRightController(childController);
87 88
 					break;
88 89
 				default:
89 90
 					throw new IllegalArgumentException("Invalid node type in sideMenu: " + node.type);
90 91
 			}
91
-		}
92
-		return sideMenuLayout;
92
+        }
93
+		return sideMenuController;
93 94
 	}
94 95
 
95 96
 	private ViewController createSideMenuContent(LayoutNode node) {

+ 2
- 1
lib/android/app/src/main/java/com/reactnativenavigation/presentation/BottomTabsOptionsPresenter.java View File

@@ -27,6 +27,7 @@ public class BottomTabsOptionsPresenter {
27 27
     }
28 28
 
29 29
     public void present(Options options, int tabIndex) {
30
+        applyBottomTabsOptions(options.bottomTabsOptions, options.animations);
30 31
         applyBottomTabOptions(options.bottomTabOptions, tabIndex);
31 32
     }
32 33
 
@@ -55,7 +56,7 @@ public class BottomTabsOptionsPresenter {
55 56
         }
56 57
         if (options.currentTabId.hasValue()) {
57 58
             int tabIndex = bottomTabFinder.findByControllerId(options.currentTabId.get());
58
-            if (tabIndex >= 0) bottomTabs.setCurrentItem(tabIndex);
59
+            if (tabIndex >= 0) tabSelector.selectTab(tabIndex);
59 60
         }
60 61
         if (options.visible.isTrueOrUndefined()) {
61 62
             if (options.animate.isTrueOrUndefined()) {

+ 0
- 31
lib/android/app/src/main/java/com/reactnativenavigation/presentation/ComponentOptionsPresenter.java View File

@@ -1,31 +0,0 @@
1
-package com.reactnativenavigation.presentation;
2
-
3
-import android.app.Activity;
4
-import android.view.View;
5
-
6
-import com.reactnativenavigation.parse.Options;
7
-import com.reactnativenavigation.parse.OrientationOptions;
8
-
9
-public class ComponentOptionsPresenter {
10
-    private View component;
11
-
12
-    public ComponentOptionsPresenter(View component) {
13
-        this.component = component;
14
-    }
15
-
16
-    public void present(Options options) {
17
-        applyOrientation(options.orientationOptions);
18
-        applyOtherOptions(options);
19
-    }
20
-
21
-    private void applyOrientation(OrientationOptions options) {
22
-        ((Activity) component.getContext()).setRequestedOrientation(options.getValue());
23
-    }
24
-
25
-    private void applyOtherOptions(Options options) {
26
-        if (options.screenBackgroundColor.hasValue()) {
27
-            component.setBackgroundColor(options.screenBackgroundColor.get());
28
-        }
29
-    }
30
-
31
-}

+ 0
- 8
lib/android/app/src/main/java/com/reactnativenavigation/presentation/NavigationOptionsListener.java View File

@@ -1,8 +0,0 @@
1
-package com.reactnativenavigation.presentation;
2
-
3
-
4
-import com.reactnativenavigation.parse.Options;
5
-
6
-public interface NavigationOptionsListener {
7
-	void mergeOptions(Options options);
8
-}

+ 11
- 166
lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java View File

@@ -1,187 +1,32 @@
1 1
 package com.reactnativenavigation.presentation;
2 2
 
3 3
 import android.app.Activity;
4
-import android.graphics.Color;
4
+import android.view.View;
5 5
 
6
-import com.reactnativenavigation.parse.AnimationsOptions;
7 6
 import com.reactnativenavigation.parse.Options;
8 7
 import com.reactnativenavigation.parse.OrientationOptions;
9
-import com.reactnativenavigation.parse.TopBarOptions;
10
-import com.reactnativenavigation.parse.TopTabOptions;
11
-import com.reactnativenavigation.parse.TopTabsOptions;
12
-import com.reactnativenavigation.parse.params.Button;
13
-import com.reactnativenavigation.utils.UiUtils;
14
-import com.reactnativenavigation.viewcontrollers.IReactView;
15
-import com.reactnativenavigation.views.Component;
16
-import com.reactnativenavigation.views.topbar.TopBar;
17
-
18
-import java.util.ArrayList;
19 8
 
20 9
 public class OptionsPresenter {
21
-    private static final int DEFAULT_TITLE_COLOR = Color.BLACK;
22
-    private static final int DEFAULT_SUBTITLE_COLOR = Color.GRAY;
23
-    private final float defaultTitleFontSize;
24
-    private final float defaultSubtitleFontSize;
25 10
 
26
-    private TopBar topBar;
11
+    private Activity activity;
27 12
 
28
-    public OptionsPresenter(TopBar topBar) {
29
-        this.topBar = topBar;
30
-        defaultTitleFontSize = UiUtils.dpToSp(topBar.getContext(), 18);
31
-        defaultSubtitleFontSize = UiUtils.dpToSp(topBar.getContext(), 14);
13
+    public OptionsPresenter(Activity activity) {
14
+        this.activity = activity;
32 15
     }
33 16
 
34
-    public void applyChildOptions(Options options, Component child) {
17
+    public void present(View view, Options options) {
35 18
         applyOrientation(options.orientationOptions);
36
-        applyButtons(options.topBar.leftButtons, options.topBar.rightButtons);
37
-        applyTopBarOptions(options.topBar, options.animations, child, options);
38
-        applyTopTabsOptions(options.topTabsOptions);
39
-        applyTopTabOptions(options.topTabOptions);
19
+        applyViewOptions(view, options);
40 20
     }
41 21
 
42
-    public void applyOrientation(OrientationOptions options) {
43
-        ((Activity) topBar.getContext()).setRequestedOrientation(options.getValue());
22
+    private void applyOrientation(OrientationOptions options) {
23
+        activity.setRequestedOrientation(options.getValue());
44 24
     }
45 25
 
46
-    private void applyTopBarOptions(TopBarOptions options, AnimationsOptions animationOptions, Component component, Options componentOptions) {
47
-        topBar.setTitle(options.title.text.get(""));
48
-        if (options.title.component.hasValue()) topBar.setTitleComponent(options.title.component);
49
-        topBar.setTitleFontSize(options.title.fontSize.get(defaultTitleFontSize));
50
-        topBar.setTitleTextColor(options.title.color.get(DEFAULT_TITLE_COLOR));
51
-        topBar.setTitleTypeface(options.title.fontFamily);
52
-        topBar.setTitleAlignment(options.title.alignment);
53
-
54
-        topBar.setSubtitle(options.subtitle.text.get(""));
55
-        topBar.setSubtitleFontSize(options.subtitle.fontSize.get(defaultSubtitleFontSize));
56
-        topBar.setSubtitleColor(options.subtitle.color.get(DEFAULT_SUBTITLE_COLOR));
57
-        topBar.setSubtitleFontFamily(options.subtitle.fontFamily);
58
-        topBar.setSubtitleAlignment(options.subtitle.alignment);
59
-
60
-        topBar.setBackgroundColor(options.background.color);
61
-        topBar.setBackgroundComponent(options.background.component);
62
-        if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
63
-
64
-        if (options.visible.isFalse()) {
65
-            if (options.animate.isTrueOrUndefined() && componentOptions.animations.push.enable.isTrueOrUndefined()) {
66
-                topBar.hideAnimate(animationOptions.pop.topBar);
67
-            } else {
68
-                topBar.hide();
69
-            }
70
-        }
71
-        if (options.visible.isTrueOrUndefined()) {
72
-            if (options.animate.isTrueOrUndefined() && componentOptions.animations.push.enable.isTrueOrUndefined()) {
73
-                topBar.showAnimate(animationOptions.push.topBar);
74
-            } else {
75
-                topBar.show();
76
-            }
77
-        }
78
-        if (options.drawBehind.isTrue()) {
79
-            component.drawBehindTopBar();
80
-        } else if (options.drawBehind.isFalseOrUndefined()) {
81
-            component.drawBelowTopBar(topBar);
82
-        }
83
-        if (options.hideOnScroll.isTrue()) {
84
-            if (component instanceof IReactView) {
85
-                topBar.enableCollapse(((IReactView) component).getScrollEventListener());
86
-            }
87
-        } else if (options.hideOnScroll.isFalseOrUndefined()) {
88
-            topBar.disableCollapse();
26
+    private void applyViewOptions(View view, Options options) {
27
+        if (options.screenBackgroundColor.hasValue()) {
28
+            view.setBackgroundColor(options.screenBackgroundColor.get());
89 29
         }
90 30
     }
91 31
 
92
-    private void applyButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
93
-        topBar.setLeftButtons(leftButtons);
94
-        topBar.setRightButtons(rightButtons);
95
-    }
96
-
97
-    private void applyTopTabsOptions(TopTabsOptions options) {
98
-        topBar.applyTopTabsColors(options.selectedTabColor, options.unselectedTabColor);
99
-        topBar.applyTopTabsFontSize(options.fontSize);
100
-        topBar.setTopTabsVisible(options.visible.isTrueOrUndefined());
101
-    }
102
-
103
-    private void applyTopTabOptions(TopTabOptions topTabOptions) {
104
-        if (topTabOptions.fontFamily != null) topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
105
-    }
106
-
107
-    public void onChildWillAppear(Options appearing, Options disappearing) {
108
-        if (disappearing.topBar.visible.isTrueOrUndefined() && appearing.topBar.visible.isFalse()) {
109
-            if (disappearing.topBar.animate.isTrueOrUndefined() && disappearing.animations.pop.enable.isTrueOrUndefined()) {
110
-                topBar.hideAnimate(disappearing.animations.pop.topBar);
111
-            } else {
112
-                topBar.hide();
113
-            }
114
-        }
115
-    }
116
-
117
-    public void mergeChildOptions(Options options, Component child) {
118
-        mergeOrientation(options.orientationOptions);
119
-        mergeButtons(options.topBar.leftButtons, options.topBar.rightButtons);
120
-        mergeTopBarOptions(options.topBar, options.animations, child);
121
-        mergeTopTabsOptions(options.topTabsOptions);
122
-        mergeTopTabOptions(options.topTabOptions);
123
-    }
124
-
125
-    private void mergeOrientation(OrientationOptions orientationOptions) {
126
-        if (orientationOptions.hasValue()) applyOrientation(orientationOptions);
127
-    }
128
-
129
-    private void mergeButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
130
-        if (leftButtons != null) topBar.setLeftButtons(leftButtons);
131
-        if (rightButtons != null) topBar.setRightButtons(rightButtons);
132
-    }
133
-
134
-    private void mergeTopBarOptions(TopBarOptions options, AnimationsOptions animationsOptions, Component component) {
135
-        if (options.title.text.hasValue()) topBar.setTitle(options.title.text.get());
136
-        if (options.title.component.hasValue()) topBar.setTitleComponent(options.title.component);
137
-        if (options.title.color.hasValue()) topBar.setTitleTextColor(options.title.color.get());
138
-        if (options.title.fontSize.hasValue()) topBar.setTitleFontSize(options.title.fontSize.get());
139
-        if (options.title.fontFamily != null) topBar.setTitleTypeface(options.title.fontFamily);
140
-
141
-        if (options.subtitle.text.hasValue()) topBar.setSubtitle(options.subtitle.text.get());
142
-        if (options.subtitle.color.hasValue()) topBar.setSubtitleColor(options.subtitle.color.get());
143
-        if (options.subtitle.fontSize.hasValue()) topBar.setSubtitleFontSize(options.subtitle.fontSize.get());
144
-        if (options.subtitle.fontFamily != null) topBar.setSubtitleFontFamily(options.subtitle.fontFamily);
145
-
146
-        if (options.background.color.hasValue()) topBar.setBackgroundColor(options.background.color);
147
-
148
-        if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
149
-
150
-        if (options.visible.isFalse()) {
151
-            if (options.animate.isTrueOrUndefined()) {
152
-                topBar.hideAnimate(animationsOptions.pop.topBar);
153
-            } else {
154
-                topBar.hide();
155
-            }
156
-        }
157
-        if (options.visible.isTrue()) {
158
-            if (options.animate.isTrueOrUndefined()) {
159
-                topBar.showAnimate(animationsOptions.push.topBar);
160
-            } else {
161
-                topBar.show();
162
-            }
163
-        }
164
-        if (options.drawBehind.isTrue()) {
165
-            component.drawBehindTopBar();
166
-        }
167
-        if (options.drawBehind.isFalse()) {
168
-            component.drawBelowTopBar(topBar);
169
-        }
170
-        if (options.hideOnScroll.isTrue() && component instanceof IReactView) {
171
-            topBar.enableCollapse(((IReactView) component).getScrollEventListener());
172
-        }
173
-        if (options.hideOnScroll.isFalse()) {
174
-            topBar.disableCollapse();
175
-        }
176
-    }
177
-
178
-    private void mergeTopTabsOptions(TopTabsOptions options) {
179
-        if (options.selectedTabColor.hasValue() && options.unselectedTabColor.hasValue()) topBar.applyTopTabsColors(options.selectedTabColor, options.unselectedTabColor);
180
-        if (options.fontSize.hasValue()) topBar.applyTopTabsFontSize(options.fontSize);
181
-        if (options.visible.hasValue()) topBar.setTopTabsVisible(options.visible.isTrue());
182
-    }
183
-
184
-    private void mergeTopTabOptions(TopTabOptions topTabOptions) {
185
-        if (topTabOptions.fontFamily != null) topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
186
-    }
187 32
 }

+ 187
- 0
lib/android/app/src/main/java/com/reactnativenavigation/presentation/StackOptionsPresenter.java View File

@@ -0,0 +1,187 @@
1
+package com.reactnativenavigation.presentation;
2
+
3
+import android.app.Activity;
4
+import android.graphics.Color;
5
+
6
+import com.reactnativenavigation.parse.AnimationsOptions;
7
+import com.reactnativenavigation.parse.Options;
8
+import com.reactnativenavigation.parse.OrientationOptions;
9
+import com.reactnativenavigation.parse.TopBarOptions;
10
+import com.reactnativenavigation.parse.TopTabOptions;
11
+import com.reactnativenavigation.parse.TopTabsOptions;
12
+import com.reactnativenavigation.parse.params.Button;
13
+import com.reactnativenavigation.utils.UiUtils;
14
+import com.reactnativenavigation.viewcontrollers.IReactView;
15
+import com.reactnativenavigation.views.Component;
16
+import com.reactnativenavigation.views.topbar.TopBar;
17
+
18
+import java.util.ArrayList;
19
+
20
+public class StackOptionsPresenter {
21
+    private static final int DEFAULT_TITLE_COLOR = Color.BLACK;
22
+    private static final int DEFAULT_SUBTITLE_COLOR = Color.GRAY;
23
+    private final float defaultTitleFontSize;
24
+    private final float defaultSubtitleFontSize;
25
+
26
+    private TopBar topBar;
27
+
28
+    public StackOptionsPresenter(TopBar topBar) {
29
+        this.topBar = topBar;
30
+        defaultTitleFontSize = UiUtils.dpToSp(topBar.getContext(), 18);
31
+        defaultSubtitleFontSize = UiUtils.dpToSp(topBar.getContext(), 14);
32
+    }
33
+
34
+    public void applyChildOptions(Options options, Component child) {
35
+        applyOrientation(options.orientationOptions);
36
+        applyButtons(options.topBar.leftButtons, options.topBar.rightButtons);
37
+        applyTopBarOptions(options.topBar, options.animations, child, options);
38
+        applyTopTabsOptions(options.topTabsOptions);
39
+        applyTopTabOptions(options.topTabOptions);
40
+    }
41
+
42
+    public void applyOrientation(OrientationOptions options) {
43
+        ((Activity) topBar.getContext()).setRequestedOrientation(options.getValue());
44
+    }
45
+
46
+    private void applyTopBarOptions(TopBarOptions options, AnimationsOptions animationOptions, Component component, Options componentOptions) {
47
+        topBar.setTitle(options.title.text.get(""));
48
+        if (options.title.component.hasValue()) topBar.setTitleComponent(options.title.component);
49
+        topBar.setTitleFontSize(options.title.fontSize.get(defaultTitleFontSize));
50
+        topBar.setTitleTextColor(options.title.color.get(DEFAULT_TITLE_COLOR));
51
+        topBar.setTitleTypeface(options.title.fontFamily);
52
+        topBar.setTitleAlignment(options.title.alignment);
53
+
54
+        topBar.setSubtitle(options.subtitle.text.get(""));
55
+        topBar.setSubtitleFontSize(options.subtitle.fontSize.get(defaultSubtitleFontSize));
56
+        topBar.setSubtitleColor(options.subtitle.color.get(DEFAULT_SUBTITLE_COLOR));
57
+        topBar.setSubtitleFontFamily(options.subtitle.fontFamily);
58
+        topBar.setSubtitleAlignment(options.subtitle.alignment);
59
+
60
+        topBar.setBackgroundColor(options.background.color);
61
+        topBar.setBackgroundComponent(options.background.component);
62
+        if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
63
+
64
+        if (options.visible.isFalse()) {
65
+            if (options.animate.isTrueOrUndefined() && componentOptions.animations.push.enable.isTrueOrUndefined()) {
66
+                topBar.hideAnimate(animationOptions.pop.topBar);
67
+            } else {
68
+                topBar.hide();
69
+            }
70
+        }
71
+        if (options.visible.isTrueOrUndefined()) {
72
+            if (options.animate.isTrueOrUndefined() && componentOptions.animations.push.enable.isTrueOrUndefined()) {
73
+                topBar.showAnimate(animationOptions.push.topBar);
74
+            } else {
75
+                topBar.show();
76
+            }
77
+        }
78
+        if (options.drawBehind.isTrue()) {
79
+            component.drawBehindTopBar();
80
+        } else if (options.drawBehind.isFalseOrUndefined()) {
81
+            component.drawBelowTopBar(topBar);
82
+        }
83
+        if (options.hideOnScroll.isTrue()) {
84
+            if (component instanceof IReactView) {
85
+                topBar.enableCollapse(((IReactView) component).getScrollEventListener());
86
+            }
87
+        } else if (options.hideOnScroll.isFalseOrUndefined()) {
88
+            topBar.disableCollapse();
89
+        }
90
+    }
91
+
92
+    private void applyButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
93
+        topBar.setLeftButtons(leftButtons);
94
+        topBar.setRightButtons(rightButtons);
95
+    }
96
+
97
+    private void applyTopTabsOptions(TopTabsOptions options) {
98
+        topBar.applyTopTabsColors(options.selectedTabColor, options.unselectedTabColor);
99
+        topBar.applyTopTabsFontSize(options.fontSize);
100
+        topBar.setTopTabsVisible(options.visible.isTrueOrUndefined());
101
+    }
102
+
103
+    private void applyTopTabOptions(TopTabOptions topTabOptions) {
104
+        if (topTabOptions.fontFamily != null) topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
105
+    }
106
+
107
+    public void onChildWillAppear(Options appearing, Options disappearing) {
108
+        if (disappearing.topBar.visible.isTrueOrUndefined() && appearing.topBar.visible.isFalse()) {
109
+            if (disappearing.topBar.animate.isTrueOrUndefined() && disappearing.animations.pop.enable.isTrueOrUndefined()) {
110
+                topBar.hideAnimate(disappearing.animations.pop.topBar);
111
+            } else {
112
+                topBar.hide();
113
+            }
114
+        }
115
+    }
116
+
117
+    public void mergeChildOptions(Options options, Component child) {
118
+        mergeOrientation(options.orientationOptions);
119
+        mergeButtons(options.topBar.leftButtons, options.topBar.rightButtons);
120
+        mergeTopBarOptions(options.topBar, options.animations, child);
121
+        mergeTopTabsOptions(options.topTabsOptions);
122
+        mergeTopTabOptions(options.topTabOptions);
123
+    }
124
+
125
+    private void mergeOrientation(OrientationOptions orientationOptions) {
126
+        if (orientationOptions.hasValue()) applyOrientation(orientationOptions);
127
+    }
128
+
129
+    private void mergeButtons(ArrayList<Button> leftButtons, ArrayList<Button> rightButtons) {
130
+        if (leftButtons != null) topBar.setLeftButtons(leftButtons);
131
+        if (rightButtons != null) topBar.setRightButtons(rightButtons);
132
+    }
133
+
134
+    private void mergeTopBarOptions(TopBarOptions options, AnimationsOptions animationsOptions, Component component) {
135
+        if (options.title.text.hasValue()) topBar.setTitle(options.title.text.get());
136
+        if (options.title.component.hasValue()) topBar.setTitleComponent(options.title.component);
137
+        if (options.title.color.hasValue()) topBar.setTitleTextColor(options.title.color.get());
138
+        if (options.title.fontSize.hasValue()) topBar.setTitleFontSize(options.title.fontSize.get());
139
+        if (options.title.fontFamily != null) topBar.setTitleTypeface(options.title.fontFamily);
140
+
141
+        if (options.subtitle.text.hasValue()) topBar.setSubtitle(options.subtitle.text.get());
142
+        if (options.subtitle.color.hasValue()) topBar.setSubtitleColor(options.subtitle.color.get());
143
+        if (options.subtitle.fontSize.hasValue()) topBar.setSubtitleFontSize(options.subtitle.fontSize.get());
144
+        if (options.subtitle.fontFamily != null) topBar.setSubtitleFontFamily(options.subtitle.fontFamily);
145
+
146
+        if (options.background.color.hasValue()) topBar.setBackgroundColor(options.background.color);
147
+
148
+        if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
149
+
150
+        if (options.visible.isFalse()) {
151
+            if (options.animate.isTrueOrUndefined()) {
152
+                topBar.hideAnimate(animationsOptions.pop.topBar);
153
+            } else {
154
+                topBar.hide();
155
+            }
156
+        }
157
+        if (options.visible.isTrue()) {
158
+            if (options.animate.isTrueOrUndefined()) {
159
+                topBar.showAnimate(animationsOptions.push.topBar);
160
+            } else {
161
+                topBar.show();
162
+            }
163
+        }
164
+        if (options.drawBehind.isTrue()) {
165
+            component.drawBehindTopBar();
166
+        }
167
+        if (options.drawBehind.isFalse()) {
168
+            component.drawBelowTopBar(topBar);
169
+        }
170
+        if (options.hideOnScroll.isTrue() && component instanceof IReactView) {
171
+            topBar.enableCollapse(((IReactView) component).getScrollEventListener());
172
+        }
173
+        if (options.hideOnScroll.isFalse()) {
174
+            topBar.disableCollapse();
175
+        }
176
+    }
177
+
178
+    private void mergeTopTabsOptions(TopTabsOptions options) {
179
+        if (options.selectedTabColor.hasValue() && options.unselectedTabColor.hasValue()) topBar.applyTopTabsColors(options.selectedTabColor, options.unselectedTabColor);
180
+        if (options.fontSize.hasValue()) topBar.applyTopTabsFontSize(options.fontSize);
181
+        if (options.visible.hasValue()) topBar.setTopTabsVisible(options.visible.isTrue());
182
+    }
183
+
184
+    private void mergeTopTabOptions(TopTabOptions topTabOptions) {
185
+        if (topTabOptions.fontFamily != null) topBar.setTopTabFontFamily(topTabOptions.tabIndex, topTabOptions.fontFamily);
186
+    }
187
+}

+ 3
- 4
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ComponentViewController.java View File

@@ -4,11 +4,10 @@ import android.app.Activity;
4 4
 import android.support.annotation.NonNull;
5 5
 
6 6
 import com.reactnativenavigation.parse.Options;
7
-import com.reactnativenavigation.presentation.NavigationOptionsListener;
8 7
 import com.reactnativenavigation.views.ComponentLayout;
9 8
 import com.reactnativenavigation.views.ReactComponent;
10 9
 
11
-public class ComponentViewController extends ViewController<ComponentLayout> implements NavigationOptionsListener {
10
+public class ComponentViewController extends ViewController<ComponentLayout> {
12 11
 
13 12
     private final String componentName;
14 13
 
@@ -43,6 +42,7 @@ public class ComponentViewController extends ViewController<ComponentLayout> imp
43 42
 
44 43
     @Override
45 44
     public void applyOptions(Options options) {
45
+        super.applyOptions(options);
46 46
         view.applyOptions(options);
47 47
     }
48 48
 
@@ -60,9 +60,8 @@ public class ComponentViewController extends ViewController<ComponentLayout> imp
60 60
 
61 61
     @Override
62 62
     public void mergeOptions(Options options) {
63
-        view.applyOptions(options);
64 63
         applyOnParentController(parentController -> parentController.mergeChildOptions(options, view));
65
-        this.options = this.options.mergeWith(options);
64
+        super.mergeOptions(options);
66 65
     }
67 66
 
68 67
     ReactComponent getComponent() {

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

@@ -11,7 +11,6 @@ import android.widget.FrameLayout;
11 11
 import com.reactnativenavigation.anim.ModalAnimator;
12 12
 import com.reactnativenavigation.anim.NavigationAnimator;
13 13
 import com.reactnativenavigation.parse.Options;
14
-import com.reactnativenavigation.presentation.NavigationOptionsListener;
15 14
 import com.reactnativenavigation.presentation.OverlayManager;
16 15
 import com.reactnativenavigation.react.JsDevReloadHandler;
17 16
 import com.reactnativenavigation.utils.CommandListener;
@@ -119,11 +118,8 @@ public class Navigator extends ParentController implements JsDevReloadHandler.Re
119 118
 
120 119
     public void mergeOptions(final String componentId, Options options) {
121 120
         ViewController target = findControllerById(componentId);
122
-        if (target instanceof NavigationOptionsListener) {
123
-            ((NavigationOptionsListener) target).mergeOptions(options);
124
-        }
125
-        if (root instanceof NavigationOptionsListener) {
126
-            ((NavigationOptionsListener) root).mergeOptions(options);
121
+        if (target != null) {
122
+            target.mergeOptions(options);
127 123
         }
128 124
     }
129 125
 

+ 11
- 4
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/SideMenuController.java View File

@@ -8,7 +8,6 @@ import android.view.Gravity;
8 8
 import android.view.View;
9 9
 
10 10
 import com.reactnativenavigation.parse.Options;
11
-import com.reactnativenavigation.presentation.NavigationOptionsListener;
12 11
 import com.reactnativenavigation.presentation.SideMenuOptionsPresenter;
13 12
 import com.reactnativenavigation.views.Component;
14 13
 
@@ -17,7 +16,7 @@ import java.util.Collection;
17 16
 
18 17
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
19 18
 
20
-public class SideMenuController extends ParentController<DrawerLayout> implements NavigationOptionsListener {
19
+public class SideMenuController extends ParentController<DrawerLayout> {
21 20
 
22 21
 	private ViewController centerController;
23 22
 	private ViewController leftController;
@@ -56,11 +55,19 @@ public class SideMenuController extends ParentController<DrawerLayout> implement
56 55
         );
57 56
     }
58 57
 
58
+    @Override
59
+    public void mergeChildOptions(Options options, Component child) {
60
+        super.mergeChildOptions(options, child);
61
+        new SideMenuOptionsPresenter(getView()).present(options.sideMenuRootOptions);
62
+        applyOnParentController(parentController ->
63
+                ((ParentController) parentController).mergeChildOptions(options.copy().clearSideMenuOptions(), child)
64
+        );
65
+    }
66
+
59 67
     @Override
60 68
     public void mergeOptions(Options options) {
61
-        this.options = this.options.mergeWith(options);
69
+        super.mergeOptions(options);
62 70
         new SideMenuOptionsPresenter(getView()).present(this.options.sideMenuRootOptions);
63
-        this.options = this.options.copy().clearSideMenuOptions();
64 71
     }
65 72
 
66 73
     public void setCenterController(ViewController centerController) {

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

@@ -40,11 +40,6 @@ public class StackController extends ParentController<StackLayout> {
40 40
         this.animator = animator;
41 41
     }
42 42
 
43
-    public void applyOptions(Options options) {
44
-        super.applyOptions(options);
45
-        getView().applyChildOptions(options);
46
-    }
47
-
48 43
     @Override
49 44
     public void applyChildOptions(Options options, Component child) {
50 45
         super.applyChildOptions(options, child);

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

@@ -12,6 +12,7 @@ import android.view.ViewTreeObserver;
12 12
 
13 13
 import com.reactnativenavigation.parse.Options;
14 14
 import com.reactnativenavigation.presentation.FabOptionsPresenter;
15
+import com.reactnativenavigation.presentation.OptionsPresenter;
15 16
 import com.reactnativenavigation.utils.CommandListener;
16 17
 import com.reactnativenavigation.utils.StringUtils;
17 18
 import com.reactnativenavigation.utils.Task;
@@ -42,11 +43,13 @@ public abstract class ViewController<T extends ViewGroup> implements ViewTreeObs
42 43
     private boolean isShown;
43 44
     private boolean isDestroyed;
44 45
     private ViewVisibilityListener viewVisibilityListener = new ViewVisibilityListenerAdapter();
46
+    private OptionsPresenter presenter;
45 47
     FabOptionsPresenter fabOptionsPresenter;
46 48
 
47 49
     public ViewController(Activity activity, String id, Options initialOptions) {
48 50
         this.activity = activity;
49 51
         this.id = id;
52
+        presenter = new OptionsPresenter(activity);
50 53
         fabOptionsPresenter = new FabOptionsPresenter();
51 54
         this.initialOptions = initialOptions;
52 55
         options = initialOptions.copy();
@@ -67,8 +70,16 @@ public abstract class ViewController<T extends ViewGroup> implements ViewTreeObs
67 70
         return false;
68 71
     }
69 72
 
70
-    public void applyOptions(Options options) {
73
+    @CallSuper
74
+    public void mergeOptions(Options options) {
75
+        this.options = this.options.mergeWith(options);
76
+        applyOptions(this.options);
77
+        this.options.clearOneTimeOptions();
78
+    }
71 79
 
80
+    @CallSuper
81
+    public void applyOptions(Options options) {
82
+        presenter.present(getView(), options);
72 83
     }
73 84
 
74 85
     public Activity getActivity() {

+ 1
- 8
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java View File

@@ -11,7 +11,6 @@ import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
11 11
 import com.reactnativenavigation.parse.BottomTabOptions;
12 12
 import com.reactnativenavigation.parse.Options;
13 13
 import com.reactnativenavigation.presentation.BottomTabsOptionsPresenter;
14
-import com.reactnativenavigation.presentation.NavigationOptionsListener;
15 14
 import com.reactnativenavigation.react.EventEmitter;
16 15
 import com.reactnativenavigation.utils.CommandListener;
17 16
 import com.reactnativenavigation.utils.ImageLoader;
@@ -28,7 +27,7 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
28 27
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
29 28
 import static android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM;
30 29
 
31
-public class BottomTabsController extends ParentController implements AHBottomNavigation.OnTabSelectedListener, NavigationOptionsListener, TabSelector {
30
+public class BottomTabsController extends ParentController implements AHBottomNavigation.OnTabSelectedListener, TabSelector {
32 31
 
33 32
 	private BottomTabs bottomTabs;
34 33
 	private List<ViewController> tabs = new ArrayList<>();
@@ -147,12 +146,6 @@ public class BottomTabsController extends ParentController implements AHBottomNa
147 146
 		return tabs;
148 147
 	}
149 148
 
150
-	@Override
151
-	public void mergeOptions(Options options) {
152
-        this.options = this.options.mergeWith(options);
153
-        presenter.present(this.options);
154
-    }
155
-
156 149
     @Override
157 150
     public void selectTab(final int newIndex) {
158 151
         getView().removeView(getCurrentView());

+ 0
- 5
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/externalcomponent/ExternalComponentViewController.java View File

@@ -21,11 +21,6 @@ public class ExternalComponentViewController extends ViewController<ExternalComp
21 21
         this.reactInstanceManager = reactInstanceManager;
22 22
     }
23 23
 
24
-    @Override
25
-    public void applyOptions(Options options) {
26
-        getView().applyOptions(options);
27
-    }
28
-
29 24
     @Override
30 25
     protected ExternalComponentLayout createView() {
31 26
         ExternalComponentLayout content = new ExternalComponentLayout(getActivity());

+ 1
- 7
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java View File

@@ -5,7 +5,6 @@ import android.support.annotation.NonNull;
5 5
 import android.view.View;
6 6
 
7 7
 import com.reactnativenavigation.parse.Options;
8
-import com.reactnativenavigation.presentation.NavigationOptionsListener;
9 8
 import com.reactnativenavigation.utils.Task;
10 9
 import com.reactnativenavigation.viewcontrollers.ParentController;
11 10
 import com.reactnativenavigation.viewcontrollers.ViewController;
@@ -17,7 +16,7 @@ import com.reactnativenavigation.views.toptabs.TopTabsViewPager;
17 16
 import java.util.Collection;
18 17
 import java.util.List;
19 18
 
20
-public class TopTabsController extends ParentController<TopTabsViewPager> implements NavigationOptionsListener {
19
+public class TopTabsController extends ParentController<TopTabsViewPager> {
21 20
 
22 21
     private List<ViewController> tabs;
23 22
     private TopTabsLayoutCreator viewCreator;
@@ -88,11 +87,6 @@ public class TopTabsController extends ParentController<TopTabsViewPager> implem
88 87
         );
89 88
     }
90 89
 
91
-    @Override
92
-    public void mergeOptions(Options options) {
93
-
94
-    }
95
-
96 90
     public void switchToTab(int index) {
97 91
         getView().switchToTab(index);
98 92
     }

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

@@ -1,11 +1,8 @@
1 1
 package com.reactnativenavigation.views;
2 2
 
3
-import com.reactnativenavigation.parse.Options;
4 3
 import com.reactnativenavigation.views.topbar.TopBar;
5 4
 
6 5
 public interface Component {
7
-    void applyOptions(Options options);
8
-
9 6
     void drawBehindTopBar();
10 7
 
11 8
     void drawBelowTopBar(TopBar topBar);

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

@@ -9,7 +9,6 @@ import android.widget.RelativeLayout;
9 9
 
10 10
 import com.reactnativenavigation.interfaces.ScrollEventListener;
11 11
 import com.reactnativenavigation.parse.Options;
12
-import com.reactnativenavigation.presentation.ComponentOptionsPresenter;
13 12
 import com.reactnativenavigation.viewcontrollers.IReactView;
14 13
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
15 14
 import com.reactnativenavigation.views.topbar.TopBar;
@@ -22,7 +21,6 @@ public class ComponentLayout extends FrameLayout implements ReactComponent, TopB
22 21
 
23 22
     private IReactView reactView;
24 23
     private final OverlayTouchDelegate touchDelegate;
25
-    private final ComponentOptionsPresenter optionsPresenter;
26 24
 
27 25
     public ComponentLayout(Context context, IReactView reactView) {
28 26
 		super(context);
@@ -30,7 +28,6 @@ public class ComponentLayout extends FrameLayout implements ReactComponent, TopB
30 28
         addView(reactView.asView(), MATCH_PARENT, MATCH_PARENT);
31 29
         setContentDescription("ComponentLayout");
32 30
         touchDelegate = new OverlayTouchDelegate(reactView);
33
-        optionsPresenter = new ComponentOptionsPresenter(this);
34 31
     }
35 32
 
36 33
     @Override
@@ -58,9 +55,7 @@ public class ComponentLayout extends FrameLayout implements ReactComponent, TopB
58 55
 		reactView.sendComponentStop();
59 56
 	}
60 57
 
61
-    @Override
62 58
     public void applyOptions(Options options) {
63
-        optionsPresenter.present(options);
64 59
         touchDelegate.setInterceptTouchOutside(options.overlayOptions.interceptTouchOutside.isTrue());
65 60
     }
66 61
 

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

@@ -5,8 +5,6 @@ import android.content.Context;
5 5
 import android.widget.FrameLayout;
6 6
 import android.widget.RelativeLayout;
7 7
 
8
-import com.reactnativenavigation.parse.Options;
9
-import com.reactnativenavigation.presentation.ComponentOptionsPresenter;
10 8
 import com.reactnativenavigation.views.topbar.TopBar;
11 9
 
12 10
 import static android.widget.RelativeLayout.BELOW;
@@ -18,11 +16,6 @@ public class ExternalComponentLayout extends FrameLayout implements Component {
18 16
         setContentDescription("ExternalComponentLayout");
19 17
     }
20 18
 
21
-    @Override
22
-    public void applyOptions(Options options) {
23
-        new ComponentOptionsPresenter(this).present(options);
24
-    }
25
-
26 19
     @Override
27 20
     public void drawBehindTopBar() {
28 21
         if (getParent() instanceof RelativeLayout) {

+ 3
- 3
lib/android/app/src/main/java/com/reactnativenavigation/views/StackLayout.java View File

@@ -5,7 +5,7 @@ import android.content.Context;
5 5
 import android.widget.RelativeLayout;
6 6
 
7 7
 import com.reactnativenavigation.parse.Options;
8
-import com.reactnativenavigation.presentation.OptionsPresenter;
8
+import com.reactnativenavigation.presentation.StackOptionsPresenter;
9 9
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
10 10
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
11 11
 import com.reactnativenavigation.viewcontrollers.ViewController;
@@ -19,13 +19,13 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
19 19
 @SuppressLint("ViewConstructor")
20 20
 public class StackLayout extends RelativeLayout {
21 21
     private String stackId;
22
-    private final OptionsPresenter optionsPresenter;
22
+    private final StackOptionsPresenter optionsPresenter;
23 23
 
24 24
     public StackLayout(Context context, ReactViewCreator topBarButtonCreator, TitleBarReactViewCreator titleBarReactViewCreator, TopBarBackgroundViewController topBarBackgroundViewController, TopBarController topBarController, TopBarButtonController.OnClickListener topBarButtonClickListener, String stackId) {
25 25
         super(context);
26 26
         this.stackId = stackId;
27 27
         createLayout(topBarButtonCreator, titleBarReactViewCreator, topBarBackgroundViewController, topBarController, topBarButtonClickListener);
28
-        optionsPresenter = new OptionsPresenter(topBarController.getView());
28
+        optionsPresenter = new StackOptionsPresenter(topBarController.getView());
29 29
         setContentDescription("StackLayout");
30 30
     }
31 31
 

+ 4
- 5
lib/android/app/src/main/java/com/reactnativenavigation/views/toptabs/TopTabsViewPager.java View File

@@ -41,11 +41,6 @@ public class TopTabsViewPager extends ViewPager implements Component, TopBarButt
41 41
         addOnPageChangeListener(adapter);
42 42
     }
43 43
 
44
-    @Override
45
-    public void applyOptions(Options options) {
46
-
47
-    }
48
-
49 44
     @Override
50 45
     public void drawBehindTopBar() {
51 46
         RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) getLayoutParams();
@@ -83,4 +78,8 @@ public class TopTabsViewPager extends ViewPager implements Component, TopBarButt
83 78
         }
84 79
         return false;
85 80
     }
81
+
82
+    public void applyOptions(Options options) {
83
+
84
+    }
86 85
 }

+ 8
- 6
lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleViewController.java View File

@@ -10,6 +10,7 @@ import android.widget.FrameLayout;
10 10
 import com.reactnativenavigation.interfaces.ScrollEventListener;
11 11
 import com.reactnativenavigation.parse.Options;
12 12
 import com.reactnativenavigation.viewcontrollers.ViewController;
13
+import com.reactnativenavigation.views.Component;
13 14
 import com.reactnativenavigation.views.ReactComponent;
14 15
 import com.reactnativenavigation.views.topbar.TopBar;
15 16
 
@@ -37,17 +38,18 @@ public class SimpleViewController extends ViewController<FrameLayout> {
37 38
         return "SimpleViewController " + getId();
38 39
     }
39 40
 
40
-    public class SimpleView extends FrameLayout implements ReactComponent {
41
+    @Override
42
+    public void mergeOptions(Options options) {
43
+        applyOnParentController(parentController -> parentController.mergeChildOptions(options, (Component) view));
44
+        super.mergeOptions(options);
45
+    }
46
+
47
+    public static class SimpleView extends FrameLayout implements ReactComponent {
41 48
 
42 49
         public SimpleView(@NonNull Context context) {
43 50
             super(context);
44 51
         }
45 52
 
46
-        @Override
47
-        public void applyOptions(Options options) {
48
-
49
-        }
50
-
51 53
         @Override
52 54
         public void drawBehindTopBar() {
53 55
 

+ 0
- 2
lib/android/app/src/test/java/com/reactnativenavigation/parse/OptionsTest.java View File

@@ -91,8 +91,6 @@ public class OptionsTest extends BaseTest {
91 91
         assertThat(result.topBar.hideOnScroll.get()).isEqualTo(TOP_BAR_HIDE_ON_SCROLL.get());
92 92
         assertThat(result.bottomTabsOptions.animate.get()).isEqualTo(BOTTOM_TABS_ANIMATE.get());
93 93
         assertThat(result.bottomTabsOptions.visible.get()).isEqualTo(BOTTOM_TABS_VISIBLE.get());
94
-        assertThat(result.bottomTabsOptions.currentTabId.get()).isEqualTo(BOTTOM_TABS_CURRENT_TAB_ID);
95
-        assertThat(result.bottomTabsOptions.currentTabIndex.get()).isEqualTo(BOTTOM_TABS_CURRENT_TAB_INDEX.get());
96 94
         assertThat(result.fabOptions.id.get()).isEqualTo(FAB_ID);
97 95
         assertThat(result.fabOptions.backgroundColor.get()).isEqualTo(FAB_BACKGROUND_COLOR);
98 96
         assertThat(result.fabOptions.clickColor.get()).isEqualTo(FAB_CLICK_COLOR);

+ 16
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/BottomTabsControllerTest.java View File

@@ -53,7 +53,6 @@ public class BottomTabsControllerTest extends BaseTest {
53 53
 
54 54
     @Override
55 55
     public void beforeEach() {
56
-        super.beforeEach();
57 56
         activity = newActivity();
58 57
         eventEmitter = Mockito.mock(EventEmitter.class);
59 58
         uut = spy(new BottomTabsController(activity, eventEmitter, imageLoaderMock, "uut", new Options()));
@@ -90,6 +89,7 @@ public class BottomTabsControllerTest extends BaseTest {
90 89
     public void setTabs_AddAllViews() {
91 90
         List<ViewController> tabs = createTabs();
92 91
         uut.setTabs(tabs);
92
+        uut.onViewAppeared();
93 93
         assertThat(uut.getView().getChildCount()).isEqualTo(2);
94 94
         assertThat(((ViewController) ((List) uut.getChildControllers()).get(0)).getView().getParent()).isNotNull();
95 95
     }
@@ -178,6 +178,21 @@ public class BottomTabsControllerTest extends BaseTest {
178 178
         verify(eventEmitter, times(0)).emitBottomTabSelected(any(Integer.class), any(Integer.class));
179 179
     }
180 180
 
181
+    @Test
182
+    public void child_mergeOptions_currentTabIndex() {
183
+        List<ViewController> tabs = createTabs();
184
+        uut.setTabs(tabs);
185
+        uut.ensureViewIsCreated();
186
+
187
+        assertThat(uut.getSelectedIndex()).isZero();
188
+
189
+        Options options = new Options();
190
+        options.bottomTabsOptions.currentTabIndex = new Number(1);
191
+        child1.mergeOptions(options);
192
+
193
+        assertThat(uut.getSelectedIndex()).isOne();
194
+    }
195
+
181 196
     @Test
182 197
     public void buttonPressInvokedOnCurrentTab() {
183 198
         uut.setTabs(createTabs());

+ 3
- 3
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsMergingTest.java View File

@@ -15,7 +15,7 @@ import com.reactnativenavigation.parse.params.Color;
15 15
 import com.reactnativenavigation.parse.params.Fraction;
16 16
 import com.reactnativenavigation.parse.params.Number;
17 17
 import com.reactnativenavigation.parse.params.Text;
18
-import com.reactnativenavigation.presentation.OptionsPresenter;
18
+import com.reactnativenavigation.presentation.StackOptionsPresenter;
19 19
 import com.reactnativenavigation.views.topbar.TopBar;
20 20
 
21 21
 import org.json.JSONObject;
@@ -35,7 +35,7 @@ import static org.mockito.Mockito.when;
35 35
 
36 36
 public class OptionsMergingTest extends BaseTest {
37 37
 
38
-    private OptionsPresenter uut;
38
+    private StackOptionsPresenter uut;
39 39
     private TestComponentLayout child;
40 40
     private Activity activity;
41 41
     private TopBar topBar;
@@ -44,7 +44,7 @@ public class OptionsMergingTest extends BaseTest {
44 44
     public void beforeEach() {
45 45
         activity = spy(newActivity());
46 46
         topBar = mockTopBar();
47
-        uut = spy(new OptionsPresenter(topBar));
47
+        uut = spy(new StackOptionsPresenter(topBar));
48 48
         child = spy(new TestComponentLayout(activity, new TestReactView(activity)));
49 49
     }
50 50
 

+ 3
- 3
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/SideMenuControllerTest.java View File

@@ -23,7 +23,7 @@ public class SideMenuControllerTest extends BaseTest {
23 23
     }
24 24
 
25 25
     @Test
26
-    public void mergeOptions_openLeftSideMenu() throws Exception {
26
+    public void mergeOptions_openLeftSideMenu() {
27 27
         uut.setLeftController(new SimpleComponentViewController(activity, "left", new Options()));
28 28
 
29 29
         Options options = new Options();
@@ -34,7 +34,7 @@ public class SideMenuControllerTest extends BaseTest {
34 34
     }
35 35
 
36 36
     @Test
37
-    public void mergeOptions_openRightSideMenu() throws Exception {
37
+    public void mergeOptions_openRightSideMenu() {
38 38
         uut.setRightController(new SimpleComponentViewController(activity, "right", new Options()));
39 39
 
40 40
         Options options = new Options();
@@ -45,7 +45,7 @@ public class SideMenuControllerTest extends BaseTest {
45 45
     }
46 46
 
47 47
     @Test
48
-    public void mergeOptions_optionsAreClearedAfterMerge() throws Exception {
48
+    public void mergeOptions_optionsAreClearedAfterMerge() {
49 49
         Options initialOptions = uut.options;
50 50
         Options options = new Options();
51 51
         uut.mergeOptions(options);

+ 1
- 8
playground/src/screens/TextScreen.js View File

@@ -6,8 +6,6 @@ const { View, Text, Button } = require('react-native');
6 6
 const { Navigation } = require('react-native-navigation');
7 7
 const testIDs = require('../testIDs');
8 8
 
9
-let globalFirstComponentID;
10
-
11 9
 class TextScreen extends Component {
12 10
   static get options() {
13 11
     return {
@@ -20,11 +18,6 @@ class TextScreen extends Component {
20 18
     };
21 19
   }
22 20
 
23
-  constructor(props) {
24
-    super(props);
25
-    globalFirstComponentID = (props.text === 'This is tab 1') ? props.componentId : globalFirstComponentID;
26
-  }
27
-
28 21
   render() {
29 22
     return (
30 23
       <View style={styles.root}>
@@ -79,7 +72,7 @@ class TextScreen extends Component {
79 72
   onClickSwitchToTabByComponentID() {
80 73
     Navigation.mergeOptions(this.props.componentId, {
81 74
       bottomTabs: {
82
-        currentTabId: globalFirstComponentID
75
+        currentTabId: 'TAB1_ID'
83 76
       }
84 77
     });
85 78
   }

+ 1
- 0
playground/src/screens/WelcomeScreen.js View File

@@ -50,6 +50,7 @@ class WelcomeScreen extends Component {
50 50
         children: [
51 51
           {
52 52
             stack: {
53
+              id: 'TAB1_ID',
53 54
               children: [
54 55
                 {
55 56
                   component: {