Browse Source

[Breaking] Top bar API changes (#2895)

* Refactor TopBar options, introduce title options

* Update background to new api

* Refactored topBar options on iOS

* Initial react component in TitleBar android

* set height to react view in TitleBar

* fix tests and lint

* ios unit tests fix
Guy Carmeli 6 years ago
parent
commit
2c53b28660
No account linked to committer's email address
56 changed files with 657 additions and 306 deletions
  1. 4
    1
      e2e/Orientations.test.js
  2. 7
    1
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java
  3. 75
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/TitleOptions.java
  4. 30
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/TopBarBackground.java
  5. 22
    71
      lib/android/app/src/main/java/com/reactnativenavigation/parse/TopBarOptions.java
  6. 6
    5
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java
  7. 6
    3
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java
  8. 36
    0
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/TitleBarReactViewController.java
  9. 1
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/TopBarButtonController.java
  10. 3
    2
      lib/android/app/src/main/java/com/reactnativenavigation/views/StackLayout.java
  11. 17
    4
      lib/android/app/src/main/java/com/reactnativenavigation/views/TopBar.java
  12. 0
    1
      lib/android/app/src/main/java/com/reactnativenavigation/views/TopBarButtonCreator.java
  13. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/views/TopBarReactButtonView.java
  14. 16
    7
      lib/android/app/src/main/java/com/reactnativenavigation/views/titlebar/TitleBar.java
  15. 15
    0
      lib/android/app/src/main/java/com/reactnativenavigation/views/titlebar/TitleBarReactView.java
  16. 20
    0
      lib/android/app/src/main/java/com/reactnativenavigation/views/titlebar/TitleBarReactViewCreator.java
  17. 20
    0
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/TitleBarReactViewCreatorMock.java
  18. 1
    1
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/TopBarButtonCreatorMock.java
  19. 31
    21
      lib/android/app/src/test/java/com/reactnativenavigation/parse/OptionsTest.java
  20. 7
    2
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/BottomTabsControllerTest.java
  21. 2
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ComponentViewControllerTest.java
  22. 2
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/FloatingActionButtonTest.java
  23. 7
    6
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/NavigatorTest.java
  24. 16
    15
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsApplyingTest.java
  25. 12
    7
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ParentControllerTest.java
  26. 13
    8
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/StackControllerTest.java
  27. 16
    2
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TitleBarTest.java
  28. 2
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopBarButtonControllerTest.java
  29. 12
    6
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsViewControllerTest.java
  30. 2
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ViewControllerTest.java
  31. 3
    2
      lib/android/app/src/test/java/com/reactnativenavigation/views/TopBarTest.java
  32. 5
    2
      lib/ios/RNNCustomTitleView.h
  33. 41
    33
      lib/ios/RNNCustomTitleView.m
  34. 6
    1
      lib/ios/RNNOptions.m
  35. 17
    6
      lib/ios/RNNRootViewController.m
  36. 13
    0
      lib/ios/RNNTitleOptions.h
  37. 32
    0
      lib/ios/RNNTitleOptions.m
  38. 4
    6
      lib/ios/RNNTopBarOptions.h
  39. 9
    25
      lib/ios/RNNTopBarOptions.m
  40. 8
    0
      lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj
  41. 1
    1
      lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m
  42. 2
    2
      lib/ios/ReactNativeNavigationTests/RNNNavigationOptionsTest.m
  43. 12
    12
      lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m
  44. 4
    2
      lib/src/commands/LayoutTreeParser.test.ts
  45. 3
    1
      playground/src/screens/BackHandlerModalScreen.js
  46. 5
    3
      playground/src/screens/BackHandlerScreen.js
  47. 1
    1
      playground/src/screens/CustomTopBar.js
  48. 4
    2
      playground/src/screens/CustomTransitionDestination.js
  49. 4
    2
      playground/src/screens/CustomTransitionOrigin.js
  50. 27
    13
      playground/src/screens/OptionsScreen.js
  51. 3
    1
      playground/src/screens/PushedScreen.js
  52. 5
    3
      playground/src/screens/ScrollViewScreen.js
  53. 11
    7
      playground/src/screens/TopTabOptionsScreen.js
  54. 5
    3
      playground/src/screens/TopTabScreen.js
  55. 28
    9
      playground/src/screens/WelcomeScreen.js
  56. 1
    0
      playground/src/testIDs.js

+ 4
- 1
e2e/Orientations.test.js View File

8
 
8
 
9
   beforeEach(async () => {
9
   beforeEach(async () => {
10
     await device.relaunchApp();
10
     await device.relaunchApp();
11
-    waitForDeviceToSettleAfterOrientationChangeAndroid = ms => new Promise(res => setTimeout(res, device.getPlatform() === 'ios' ? 0 : 150));
11
+    waitForDeviceToSettleAfterOrientationChangeAndroid = ms => new Promise(res => setTimeout(res, device.getPlatform() === 'ios' ? 0 : 400));
12
   });
12
   });
13
 
13
 
14
   it('default allows all', async () => {
14
   it('default allows all', async () => {
15
     await elementById(testIDs.ORIENTATION_BUTTON).tap();
15
     await elementById(testIDs.ORIENTATION_BUTTON).tap();
16
     await elementById(testIDs.DEFAULT_ORIENTATION_BUTTON).tap();
16
     await elementById(testIDs.DEFAULT_ORIENTATION_BUTTON).tap();
17
+    waitForDeviceToSettleAfterOrientationChangeAndroid();
17
     await expect(elementById(testIDs.PORTRAIT_ELEMENT)).toBeVisible();
18
     await expect(elementById(testIDs.PORTRAIT_ELEMENT)).toBeVisible();
18
     await device.setOrientation('landscape');
19
     await device.setOrientation('landscape');
20
+    waitForDeviceToSettleAfterOrientationChangeAndroid();
19
     await expect(elementById(testIDs.LANDSCAPE_ELEMENT)).toBeVisible();
21
     await expect(elementById(testIDs.LANDSCAPE_ELEMENT)).toBeVisible();
20
     await device.setOrientation('portrait');
22
     await device.setOrientation('portrait');
21
     waitForDeviceToSettleAfterOrientationChangeAndroid();
23
     waitForDeviceToSettleAfterOrientationChangeAndroid();
28
     await elementById(testIDs.LANDSCAPE_PORTRAIT_ORIENTATION_BUTTON).tap();
30
     await elementById(testIDs.LANDSCAPE_PORTRAIT_ORIENTATION_BUTTON).tap();
29
     await expect(element(by.id(testIDs.PORTRAIT_ELEMENT))).toBeVisible();
31
     await expect(element(by.id(testIDs.PORTRAIT_ELEMENT))).toBeVisible();
30
     await device.setOrientation('landscape');
32
     await device.setOrientation('landscape');
33
+    waitForDeviceToSettleAfterOrientationChangeAndroid();
31
     await expect(element(by.id(testIDs.LANDSCAPE_ELEMENT))).toBeVisible();
34
     await expect(element(by.id(testIDs.LANDSCAPE_ELEMENT))).toBeVisible();
32
     await device.setOrientation('portrait');
35
     await device.setOrientation('portrait');
33
     waitForDeviceToSettleAfterOrientationChangeAndroid();
36
     waitForDeviceToSettleAfterOrientationChangeAndroid();

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

15
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentViewController;
15
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentViewController;
16
 import com.reactnativenavigation.viewcontrollers.toptabs.TopTabsController;
16
 import com.reactnativenavigation.viewcontrollers.toptabs.TopTabsController;
17
 import com.reactnativenavigation.views.ComponentViewCreator;
17
 import com.reactnativenavigation.views.ComponentViewCreator;
18
+import com.reactnativenavigation.views.titlebar.TitleBarReactViewCreator;
18
 import com.reactnativenavigation.views.TopBarButtonCreator;
19
 import com.reactnativenavigation.views.TopBarButtonCreator;
19
 import com.reactnativenavigation.views.TopTabsLayoutCreator;
20
 import com.reactnativenavigation.views.TopTabsLayoutCreator;
20
 
21
 
118
     }
119
     }
119
 
120
 
120
 	private ViewController createStack(LayoutNode node) {
121
 	private ViewController createStack(LayoutNode node) {
121
-        StackController stackController = new StackController(activity, new TopBarButtonCreator(reactInstanceManager), node.id, getOptions(node));
122
+        StackController stackController = new StackController(activity,
123
+                new TopBarButtonCreator(reactInstanceManager),
124
+                new TitleBarReactViewCreator(reactInstanceManager),
125
+                node.id,
126
+                getOptions(node)
127
+        );
122
         addChildrenToStack(node.children, stackController);
128
         addChildrenToStack(node.children, stackController);
123
         return stackController;
129
         return stackController;
124
 	}
130
 	}

+ 75
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/TitleOptions.java View File

1
+package com.reactnativenavigation.parse;
2
+
3
+import android.graphics.Typeface;
4
+import android.support.annotation.Nullable;
5
+
6
+import com.reactnativenavigation.parse.params.Color;
7
+import com.reactnativenavigation.parse.params.Fraction;
8
+import com.reactnativenavigation.parse.params.NullColor;
9
+import com.reactnativenavigation.parse.params.NullFraction;
10
+import com.reactnativenavigation.parse.params.NullText;
11
+import com.reactnativenavigation.parse.params.Text;
12
+import com.reactnativenavigation.parse.parsers.ColorParser;
13
+import com.reactnativenavigation.parse.parsers.FractionParser;
14
+import com.reactnativenavigation.parse.parsers.TextParser;
15
+import com.reactnativenavigation.utils.TypefaceLoader;
16
+
17
+import org.json.JSONObject;
18
+
19
+public class TitleOptions {
20
+    public enum Alignment {
21
+        Center, Fill, Default;
22
+
23
+        public static Alignment fromString(String alignment) {
24
+            switch (alignment) {
25
+                case "center":
26
+                    return Center;
27
+                case "fill":
28
+                    return Fill;
29
+                default:
30
+                    return Default;
31
+            }
32
+        }
33
+    }
34
+
35
+    public static TitleOptions parse(TypefaceLoader typefaceManager, JSONObject json) {
36
+        final TitleOptions options = new TitleOptions();
37
+        if (json == null) {
38
+            return options;
39
+        }
40
+
41
+        options.text = TextParser.parse(json, "text");
42
+        options.color = ColorParser.parse(json, "color");
43
+        options.fontSize = FractionParser.parse(json, "fontSize");
44
+        options.fontFamily = typefaceManager.getTypeFace(json.optString("fontFamily", ""));
45
+        options.component = TextParser.parse(json, "component");
46
+        options.alignment = Alignment.fromString(TextParser.parse(json, "alignment").get(""));
47
+
48
+        return options;
49
+    }
50
+
51
+    public Text text = new NullText();
52
+    public Color color = new NullColor();
53
+    public Fraction fontSize = new NullFraction();
54
+    @Nullable public Typeface fontFamily;
55
+    public Text component = new NullText();
56
+    public Alignment alignment = Alignment.Default;
57
+
58
+    void mergeWith(final TitleOptions other) {
59
+        if (other.text.hasValue()) text = other.text;
60
+        if (other.color.hasValue()) color = other.color;
61
+        if (other.fontSize.hasValue()) fontSize = other.fontSize;
62
+        if (other.fontFamily != null) fontFamily = other.fontFamily;
63
+        if (other.component.hasValue()) component = other.component;
64
+        if (other.alignment != Alignment.Default) alignment = other.alignment;
65
+    }
66
+
67
+    void mergeWithDefault(TitleOptions defaultOptions) {
68
+        if (!text.hasValue()) text = defaultOptions.text;
69
+        if (!color.hasValue()) color = defaultOptions.color;
70
+        if (!fontSize.hasValue()) fontSize = defaultOptions.fontSize;
71
+        if (fontFamily == null) fontFamily = defaultOptions.fontFamily;
72
+        if (!component.hasValue()) component = defaultOptions.component;
73
+        if (alignment == Alignment.Default) alignment = defaultOptions.alignment;
74
+    }
75
+}

+ 30
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/TopBarBackground.java View File

1
+package com.reactnativenavigation.parse;
2
+
3
+import com.reactnativenavigation.parse.params.Color;
4
+import com.reactnativenavigation.parse.params.NullColor;
5
+import com.reactnativenavigation.parse.parsers.ColorParser;
6
+
7
+import org.json.JSONObject;
8
+
9
+public class TopBarBackground {
10
+    public static TopBarBackground parse(JSONObject json) {
11
+        TopBarBackground options = new TopBarBackground();
12
+        if (json == null) {
13
+            return options;
14
+        }
15
+
16
+        options.color = ColorParser.parse(json, "color");
17
+
18
+        return options;
19
+    }
20
+
21
+    public Color color = new NullColor();
22
+
23
+    void mergeWith(final TopBarBackground other) {
24
+        if (other.color.hasValue()) color = other.color;
25
+    }
26
+
27
+    void mergeWithDefault(TopBarBackground defaultOptions) {
28
+        if (!color.hasValue()) color = defaultOptions.color;
29
+    }
30
+}

+ 22
- 71
lib/android/app/src/main/java/com/reactnativenavigation/parse/TopBarOptions.java View File

1
 package com.reactnativenavigation.parse;
1
 package com.reactnativenavigation.parse;
2
 
2
 
3
 
3
 
4
-import android.graphics.Typeface;
5
 import android.support.annotation.Nullable;
4
 import android.support.annotation.Nullable;
6
 
5
 
7
 import com.reactnativenavigation.parse.params.Bool;
6
 import com.reactnativenavigation.parse.params.Bool;
8
 import com.reactnativenavigation.parse.params.Button;
7
 import com.reactnativenavigation.parse.params.Button;
9
-import com.reactnativenavigation.parse.params.Color;
10
-import com.reactnativenavigation.parse.params.Fraction;
11
 import com.reactnativenavigation.parse.params.NullBool;
8
 import com.reactnativenavigation.parse.params.NullBool;
12
-import com.reactnativenavigation.parse.params.NullColor;
13
-import com.reactnativenavigation.parse.params.NullFraction;
14
 import com.reactnativenavigation.parse.params.NullText;
9
 import com.reactnativenavigation.parse.params.NullText;
15
 import com.reactnativenavigation.parse.params.Text;
10
 import com.reactnativenavigation.parse.params.Text;
16
 import com.reactnativenavigation.parse.parsers.BoolParser;
11
 import com.reactnativenavigation.parse.parsers.BoolParser;
17
-import com.reactnativenavigation.parse.parsers.ColorParser;
18
-import com.reactnativenavigation.parse.parsers.FractionParser;
19
 import com.reactnativenavigation.parse.parsers.TextParser;
12
 import com.reactnativenavigation.parse.parsers.TextParser;
20
 import com.reactnativenavigation.utils.TypefaceLoader;
13
 import com.reactnativenavigation.utils.TypefaceLoader;
21
 
14
 
29
         TopBarOptions options = new TopBarOptions();
22
         TopBarOptions options = new TopBarOptions();
30
         if (json == null) return options;
23
         if (json == null) return options;
31
 
24
 
32
-        options.title = TextParser.parse(json, "title");
33
-        options.backgroundColor = ColorParser.parse(json, "backgroundColor");
34
-        options.textColor = ColorParser.parse(json, "textColor");
35
-        options.textFontSize = FractionParser.parse(json, "textFontSize");
36
-        options.textFontFamily = typefaceManager.getTypeFace(json.optString("textFontFamily", ""));
25
+        options.title = TitleOptions.parse(typefaceManager, json.optJSONObject("title"));
26
+        options.background = TopBarBackground.parse(json.optJSONObject("background"));
37
         options.visible = BoolParser.parse(json, "visible");
27
         options.visible = BoolParser.parse(json, "visible");
38
         options.animate = BoolParser.parse(json,"animate");
28
         options.animate = BoolParser.parse(json,"animate");
39
         options.hideOnScroll = BoolParser.parse(json,"hideOnScroll");
29
         options.hideOnScroll = BoolParser.parse(json,"hideOnScroll");
45
         return options;
35
         return options;
46
     }
36
     }
47
 
37
 
48
-    public Text title = new NullText();
38
+    public TitleOptions title = new TitleOptions();
49
     public Text testId = new NullText();
39
     public Text testId = new NullText();
50
-    public Color backgroundColor = new NullColor();
51
-    public Color textColor = new NullColor();
52
-    public Fraction textFontSize = new NullFraction();
53
-    @Nullable public Typeface textFontFamily;
40
+    public TopBarBackground background = new TopBarBackground();
54
     public Bool visible = new NullBool();
41
     public Bool visible = new NullBool();
55
     public Bool animate = new NullBool();
42
     public Bool animate = new NullBool();
56
     public Bool hideOnScroll = new NullBool();
43
     public Bool hideOnScroll = new NullBool();
59
     @Nullable public ArrayList<Button> rightButtons;
46
     @Nullable public ArrayList<Button> rightButtons;
60
 
47
 
61
     void mergeWith(final TopBarOptions other) {
48
     void mergeWith(final TopBarOptions other) {
62
-        if (other.testId.hasValue()) {
63
-            testId = other.testId;
64
-        }
65
-        if (other.title.hasValue())
66
-            title = other.title;
67
-        if (other.backgroundColor.hasValue())
68
-            backgroundColor = other.backgroundColor;
69
-        if (other.textColor.hasValue())
70
-            textColor = other.textColor;
71
-        if (other.textFontSize.hasValue())
72
-            textFontSize = other.textFontSize;
73
-        if (other.textFontFamily != null)
74
-            textFontFamily = other.textFontFamily;
75
-        if (other.visible.hasValue()) {
76
-            visible = other.visible;
77
-        }
78
-        if (other.animate.hasValue()) {
79
-            animate = other.animate;
80
-        }
81
-        if (other.hideOnScroll.hasValue()) {
82
-            hideOnScroll = other.hideOnScroll;
83
-        }
84
-        if (other.drawBehind.hasValue()) {
85
-            drawBehind = other.drawBehind;
86
-        }
87
-        if (other.leftButtons != null)
88
-            leftButtons = other.leftButtons;
89
-        if (other.rightButtons != null)
90
-            rightButtons = other.rightButtons;
49
+        title.mergeWith(other.title);
50
+        background.mergeWith(other.background);
51
+        if (other.testId.hasValue()) testId = other.testId;
52
+        if (other.visible.hasValue()) visible = other.visible;
53
+        if (other.animate.hasValue()) animate = other.animate;
54
+        if (other.hideOnScroll.hasValue()) hideOnScroll = other.hideOnScroll;
55
+        if (other.drawBehind.hasValue()) drawBehind = other.drawBehind;
56
+        if (other.leftButtons != null) leftButtons = other.leftButtons;
57
+        if (other.rightButtons != null) rightButtons = other.rightButtons;
91
     }
58
     }
92
 
59
 
93
     void mergeWithDefault(TopBarOptions defaultOptions) {
60
     void mergeWithDefault(TopBarOptions defaultOptions) {
94
-        if (title == null)
95
-            title = defaultOptions.title;
96
-        if (!backgroundColor.hasValue())
97
-            backgroundColor = defaultOptions.backgroundColor;
98
-        if (!textColor.hasValue())
99
-            textColor = defaultOptions.textColor;
100
-        if (!textFontSize.hasValue())
101
-            textFontSize = defaultOptions.textFontSize;
102
-        if (textFontFamily == null)
103
-            textFontFamily = defaultOptions.textFontFamily;
104
-        if (!visible.hasValue())
105
-            visible = defaultOptions.visible;
106
-        if (!animate.hasValue())
107
-            animate = defaultOptions.animate;
108
-        if (!hideOnScroll.hasValue())
109
-            hideOnScroll = defaultOptions.hideOnScroll;
110
-        if (!drawBehind.hasValue())
111
-            drawBehind = defaultOptions.drawBehind;
112
-        if (leftButtons == null)
113
-            leftButtons = defaultOptions.leftButtons;
114
-        if (rightButtons == null)
115
-            rightButtons = defaultOptions.rightButtons;
116
-        if (!testId.hasValue()) {
117
-            testId = defaultOptions.testId;
118
-        }
61
+        title.mergeWithDefault(defaultOptions.title);
62
+        background.mergeWithDefault(defaultOptions.background);
63
+        if (!visible.hasValue()) visible = defaultOptions.visible;
64
+        if (!animate.hasValue()) animate = defaultOptions.animate;
65
+        if (!hideOnScroll.hasValue()) hideOnScroll = defaultOptions.hideOnScroll;
66
+        if (!drawBehind.hasValue()) drawBehind = defaultOptions.drawBehind;
67
+        if (leftButtons == null) leftButtons = defaultOptions.leftButtons;
68
+        if (rightButtons == null) rightButtons = defaultOptions.rightButtons;
69
+        if (!testId.hasValue()) testId = defaultOptions.testId;
119
     }
70
     }
120
 }
71
 }

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

40
     }
40
     }
41
 
41
 
42
     private void applyTopBarOptions(TopBarOptions options) {
42
     private void applyTopBarOptions(TopBarOptions options) {
43
-        if (options.title.hasValue()) topBar.setTitle(options.title.get());
44
-        topBar.setBackgroundColor(options.backgroundColor);
45
-        topBar.setTitleTextColor(options.textColor);
46
-        topBar.setTitleFontSize(options.textFontSize);
43
+        if (options.title.text.hasValue()) topBar.setTitle(options.title.text.get());
44
+        if (options.title.component.hasValue()) topBar.setComponent(options.title.component.get(), options.title.alignment);
45
+        topBar.setBackgroundColor(options.background.color);
46
+        topBar.setTitleTextColor(options.title.color);
47
+        topBar.setTitleFontSize(options.title.fontSize);
47
         if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
48
         if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
48
 
49
 
49
-        topBar.setTitleTypeface(options.textFontFamily);
50
+        topBar.setTitleTypeface(options.title.fontFamily);
50
         if (options.visible.isFalse()) {
51
         if (options.visible.isFalse()) {
51
             topBar.hide(options.animate);
52
             topBar.hide(options.animate);
52
         }
53
         }

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

14
 import com.reactnativenavigation.views.ReactComponent;
14
 import com.reactnativenavigation.views.ReactComponent;
15
 import com.reactnativenavigation.views.StackLayout;
15
 import com.reactnativenavigation.views.StackLayout;
16
 import com.reactnativenavigation.views.TopBar;
16
 import com.reactnativenavigation.views.TopBar;
17
+import com.reactnativenavigation.views.titlebar.TitleBarReactViewCreator;
17
 
18
 
18
 import java.util.Collection;
19
 import java.util.Collection;
19
 import java.util.Iterator;
20
 import java.util.Iterator;
25
     private static final NoOpPromise NO_OP = new NoOpPromise();
26
     private static final NoOpPromise NO_OP = new NoOpPromise();
26
     private final IdStack<ViewController> stack = new IdStack<>();
27
     private final IdStack<ViewController> stack = new IdStack<>();
27
     private final NavigationAnimator animator;
28
     private final NavigationAnimator animator;
28
-    private ReactViewCreator topBarButtonCreator;
29
+    private final ReactViewCreator topBarButtonCreator;
30
+    private final TitleBarReactViewCreator titleBarReactViewCreator;
29
 
31
 
30
-    public StackController(final Activity activity, ReactViewCreator topBarButtonCreator, String id, Options initialOptions) {
32
+    public StackController(final Activity activity, ReactViewCreator topBarButtonCreator, TitleBarReactViewCreator titleBarReactViewCreator, String id, Options initialOptions) {
31
         super(activity, id, initialOptions);
33
         super(activity, id, initialOptions);
32
         animator = new NavigationAnimator(activity);
34
         animator = new NavigationAnimator(activity);
33
         this.topBarButtonCreator = topBarButtonCreator;
35
         this.topBarButtonCreator = topBarButtonCreator;
36
+        this.titleBarReactViewCreator = titleBarReactViewCreator;
34
     }
37
     }
35
 
38
 
36
     public void applyOptions(Options options) {
39
     public void applyOptions(Options options) {
202
     @NonNull
205
     @NonNull
203
     @Override
206
     @Override
204
     protected StackLayout createView() {
207
     protected StackLayout createView() {
205
-        return new StackLayout(getActivity(), topBarButtonCreator, this::sendOnNavigationButtonPressed);
208
+        return new StackLayout(getActivity(), topBarButtonCreator, titleBarReactViewCreator, this::sendOnNavigationButtonPressed);
206
     }
209
     }
207
 
210
 
208
 	@NonNull
211
 	@NonNull

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

1
+package com.reactnativenavigation.viewcontrollers;
2
+
3
+import android.app.Activity;
4
+
5
+import com.reactnativenavigation.parse.Options;
6
+import com.reactnativenavigation.parse.TitleOptions;
7
+import com.reactnativenavigation.utils.CompatUtils;
8
+import com.reactnativenavigation.views.titlebar.TitleBarReactView;
9
+import com.reactnativenavigation.views.titlebar.TitleBarReactViewCreator;
10
+
11
+public class TitleBarReactViewController extends ViewController<TitleBarReactView> {
12
+
13
+    private final TitleBarReactViewCreator reactViewCreator;
14
+    private String componentName;
15
+    private TitleOptions.Alignment alignment;
16
+
17
+    public TitleBarReactViewController(Activity activity, TitleBarReactViewCreator reactViewCreator) {
18
+        super(activity, CompatUtils.generateViewId() + "", new Options());
19
+        this.reactViewCreator = reactViewCreator;
20
+    }
21
+
22
+    @Override
23
+    protected TitleBarReactView createView() {
24
+        return reactViewCreator.create(getActivity(), getId(), componentName);
25
+    }
26
+
27
+    @Override
28
+    public void sendOnNavigationButtonPressed(String buttonId) {
29
+
30
+    }
31
+
32
+    public void setComponent(String componentName, TitleOptions.Alignment alignment) {
33
+        this.componentName = componentName;
34
+        this.alignment = alignment;
35
+    }
36
+}

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

18
 import com.reactnativenavigation.parse.Options;
18
 import com.reactnativenavigation.parse.Options;
19
 import com.reactnativenavigation.parse.params.Button;
19
 import com.reactnativenavigation.parse.params.Button;
20
 import com.reactnativenavigation.parse.params.Text;
20
 import com.reactnativenavigation.parse.params.Text;
21
-import com.reactnativenavigation.react.TopBarReactButtonView;
21
+import com.reactnativenavigation.views.TopBarReactButtonView;
22
 import com.reactnativenavigation.utils.ArrayUtils;
22
 import com.reactnativenavigation.utils.ArrayUtils;
23
 import com.reactnativenavigation.utils.ImageLoader;
23
 import com.reactnativenavigation.utils.ImageLoader;
24
 import com.reactnativenavigation.utils.ImageLoadingListenerAdapter;
24
 import com.reactnativenavigation.utils.ImageLoadingListenerAdapter;

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

11
 import com.reactnativenavigation.utils.CompatUtils;
11
 import com.reactnativenavigation.utils.CompatUtils;
12
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
12
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
13
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
13
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
14
+import com.reactnativenavigation.views.titlebar.TitleBarReactViewCreator;
14
 
15
 
15
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
16
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
16
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
17
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
19
 public class StackLayout extends RelativeLayout {
20
 public class StackLayout extends RelativeLayout {
20
     private TopBar topBar;
21
     private TopBar topBar;
21
 
22
 
22
-    public StackLayout(Context context, ReactViewCreator topBarButtonCreator, TopBarButtonController.OnClickListener topBarButtonClickListener) {
23
+    public StackLayout(Context context, ReactViewCreator topBarButtonCreator, TitleBarReactViewCreator titleBarReactViewCreator, TopBarButtonController.OnClickListener topBarButtonClickListener) {
23
         super(context);
24
         super(context);
24
-        topBar = new TopBar(context, topBarButtonCreator, topBarButtonClickListener, this);
25
+        topBar = new TopBar(context, topBarButtonCreator, titleBarReactViewCreator, topBarButtonClickListener, this);
25
         topBar.setId(CompatUtils.generateViewId());
26
         topBar.setId(CompatUtils.generateViewId());
26
         addView(topBar, MATCH_PARENT, WRAP_CONTENT);
27
         addView(topBar, MATCH_PARENT, WRAP_CONTENT);
27
         setContentDescription("StackLayout");
28
         setContentDescription("StackLayout");

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

1
 package com.reactnativenavigation.views;
1
 package com.reactnativenavigation.views;
2
 
2
 
3
 import android.annotation.SuppressLint;
3
 import android.annotation.SuppressLint;
4
+import android.app.Activity;
4
 import android.content.Context;
5
 import android.content.Context;
5
 import android.graphics.Typeface;
6
 import android.graphics.Typeface;
6
 import android.support.annotation.RestrictTo;
7
 import android.support.annotation.RestrictTo;
14
 import com.reactnativenavigation.anim.TopBarAnimator;
15
 import com.reactnativenavigation.anim.TopBarAnimator;
15
 import com.reactnativenavigation.anim.TopBarCollapseBehavior;
16
 import com.reactnativenavigation.anim.TopBarCollapseBehavior;
16
 import com.reactnativenavigation.interfaces.ScrollEventListener;
17
 import com.reactnativenavigation.interfaces.ScrollEventListener;
18
+import com.reactnativenavigation.parse.TitleOptions;
17
 import com.reactnativenavigation.parse.params.Bool;
19
 import com.reactnativenavigation.parse.params.Bool;
18
 import com.reactnativenavigation.parse.params.Button;
20
 import com.reactnativenavigation.parse.params.Button;
19
 import com.reactnativenavigation.parse.params.Color;
21
 import com.reactnativenavigation.parse.params.Color;
20
 import com.reactnativenavigation.parse.params.Fraction;
22
 import com.reactnativenavigation.parse.params.Fraction;
21
 import com.reactnativenavigation.parse.params.Number;
23
 import com.reactnativenavigation.parse.params.Number;
22
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
24
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
25
+import com.reactnativenavigation.viewcontrollers.TitleBarReactViewController;
23
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
26
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
27
+import com.reactnativenavigation.views.titlebar.TitleBar;
28
+import com.reactnativenavigation.views.titlebar.TitleBarReactViewCreator;
24
 
29
 
25
 import java.util.List;
30
 import java.util.List;
26
 
31
 
35
     private TopTabs topTabs;
40
     private TopTabs topTabs;
36
     private StackLayout parentView;
41
     private StackLayout parentView;
37
 
42
 
38
-    public TopBar(final Context context, ReactViewCreator buttonCreator, TopBarButtonController.OnClickListener onClickListener, StackLayout parentView) {
43
+    public TopBar(final Context context, ReactViewCreator buttonCreator, TitleBarReactViewCreator titleBarReactViewCreator, TopBarButtonController.OnClickListener onClickListener, StackLayout parentView) {
39
         super(context);
44
         super(context);
40
         collapsingBehavior = new TopBarCollapseBehavior(this);
45
         collapsingBehavior = new TopBarCollapseBehavior(this);
41
         topTabs = new TopTabs(getContext());
46
         topTabs = new TopTabs(getContext());
42
         animator = new TopBarAnimator(this);
47
         animator = new TopBarAnimator(this);
43
         this.parentView = parentView;
48
         this.parentView = parentView;
44
-        titleBar = createTitleBar(context, buttonCreator, onClickListener);
49
+        titleBar = createTitleBar(context, buttonCreator, titleBarReactViewCreator, onClickListener);
45
         addView(titleBar);
50
         addView(titleBar);
46
         setContentDescription("TopBar");
51
         setContentDescription("TopBar");
47
     }
52
     }
48
 
53
 
49
-    protected TitleBar createTitleBar(Context context, ReactViewCreator buttonCreator, TopBarButtonController.OnClickListener onClickListener) {
50
-        return new TitleBar(context, buttonCreator, onClickListener);
54
+    protected TitleBar createTitleBar(Context context, ReactViewCreator buttonCreator, TitleBarReactViewCreator reactViewCreator, TopBarButtonController.OnClickListener onClickListener) {
55
+        return new TitleBar(context,
56
+                buttonCreator,
57
+                new TitleBarReactViewController((Activity) context, reactViewCreator),
58
+                onClickListener
59
+        );
51
     }
60
     }
52
 
61
 
53
     public void setTitle(String title) {
62
     public void setTitle(String title) {
74
         titleBar.setTitleTypeface(typeface);
83
         titleBar.setTitleTypeface(typeface);
75
     }
84
     }
76
 
85
 
86
+    public void setComponent(String componentName, TitleOptions.Alignment alignment) {
87
+        titleBar.setComponent(componentName, alignment);
88
+    }
89
+
77
     public void setTopTabFontFamily(int tabIndex, Typeface fontFamily) {
90
     public void setTopTabFontFamily(int tabIndex, Typeface fontFamily) {
78
         topTabs.setFontFamily(tabIndex, fontFamily);
91
         topTabs.setFontFamily(tabIndex, fontFamily);
79
     }
92
     }

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

3
 import android.app.Activity;
3
 import android.app.Activity;
4
 
4
 
5
 import com.facebook.react.ReactInstanceManager;
5
 import com.facebook.react.ReactInstanceManager;
6
-import com.reactnativenavigation.react.TopBarReactButtonView;
7
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
6
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
8
 
7
 
9
 public class TopBarButtonCreator implements ReactViewCreator {
8
 public class TopBarButtonCreator implements ReactViewCreator {

lib/android/app/src/main/java/com/reactnativenavigation/react/TopBarReactButtonView.java → lib/android/app/src/main/java/com/reactnativenavigation/views/TopBarReactButtonView.java View File

1
-package com.reactnativenavigation.react;
1
+package com.reactnativenavigation.views;
2
 
2
 
3
 import android.annotation.SuppressLint;
3
 import android.annotation.SuppressLint;
4
 import android.content.Context;
4
 import android.content.Context;
5
 
5
 
6
 import com.facebook.react.ReactInstanceManager;
6
 import com.facebook.react.ReactInstanceManager;
7
+import com.reactnativenavigation.react.ReactView;
7
 
8
 
8
 @SuppressLint("ViewConstructor")
9
 @SuppressLint("ViewConstructor")
9
 public class TopBarReactButtonView extends ReactView {
10
 public class TopBarReactButtonView extends ReactView {

lib/android/app/src/main/java/com/reactnativenavigation/views/TitleBar.java → lib/android/app/src/main/java/com/reactnativenavigation/views/titlebar/TitleBar.java View File

1
-package com.reactnativenavigation.views;
1
+package com.reactnativenavigation.views.titlebar;
2
 
2
 
3
 import android.annotation.SuppressLint;
3
 import android.annotation.SuppressLint;
4
 import android.app.Activity;
4
 import android.app.Activity;
11
 import android.view.ViewGroup;
11
 import android.view.ViewGroup;
12
 import android.widget.TextView;
12
 import android.widget.TextView;
13
 
13
 
14
+import com.reactnativenavigation.parse.TitleOptions;
14
 import com.reactnativenavigation.parse.params.Button;
15
 import com.reactnativenavigation.parse.params.Button;
15
 import com.reactnativenavigation.parse.params.Color;
16
 import com.reactnativenavigation.parse.params.Color;
16
 import com.reactnativenavigation.parse.params.Fraction;
17
 import com.reactnativenavigation.parse.params.Fraction;
17
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
18
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
19
+import com.reactnativenavigation.viewcontrollers.TitleBarReactViewController;
18
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
20
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
19
 
21
 
20
 import java.util.ArrayList;
22
 import java.util.ArrayList;
23
 @SuppressLint("ViewConstructor")
25
 @SuppressLint("ViewConstructor")
24
 public class TitleBar extends Toolbar {
26
 public class TitleBar extends Toolbar {
25
     private final ReactViewCreator buttonCreator;
27
     private final ReactViewCreator buttonCreator;
28
+    private TitleBarReactViewController reactViewController;
26
     private final TopBarButtonController.OnClickListener onClickListener;
29
     private final TopBarButtonController.OnClickListener onClickListener;
27
     private final List<TopBarButtonController> rightButtonControllers = new ArrayList<>();
30
     private final List<TopBarButtonController> rightButtonControllers = new ArrayList<>();
28
     private TopBarButtonController leftButtonController;
31
     private TopBarButtonController leftButtonController;
29
 
32
 
30
-    public TitleBar(Context context, ReactViewCreator buttonCreator, TopBarButtonController.OnClickListener onClickListener) {
33
+    public TitleBar(Context context, ReactViewCreator buttonCreator, TitleBarReactViewController reactViewController, TopBarButtonController.OnClickListener onClickListener) {
31
         super(context);
34
         super(context);
32
         this.buttonCreator = buttonCreator;
35
         this.buttonCreator = buttonCreator;
36
+        this.reactViewController = reactViewController;
33
         this.onClickListener = onClickListener;
37
         this.onClickListener = onClickListener;
34
         getMenu();
38
         getMenu();
35
         setContentDescription("titleBar");
39
         setContentDescription("titleBar");
39
         return super.getTitle() == null ? "" : (String) super.getTitle();
43
         return super.getTitle() == null ? "" : (String) super.getTitle();
40
     }
44
     }
41
 
45
 
42
-    void setTitleTextColor(Color color) {
46
+    public void setTitleTextColor(Color color) {
43
         if (color.hasValue()) setTitleTextColor(color.get());
47
         if (color.hasValue()) setTitleTextColor(color.get());
44
     }
48
     }
45
 
49
 
46
-    void setBackgroundColor(Color color) {
50
+    public void setComponent(String componentName, TitleOptions.Alignment alignment) {
51
+        reactViewController.setComponent(componentName, alignment);
52
+        addView(reactViewController.getView(), ViewGroup.LayoutParams.WRAP_CONTENT, getHeight());
53
+    }
54
+
55
+    public void setBackgroundColor(Color color) {
47
         if (color.hasValue()) setBackgroundColor(color.get());
56
         if (color.hasValue()) setBackgroundColor(color.get());
48
     }
57
     }
49
 
58
 
50
-    void setTitleFontSize(Fraction size) {
59
+    public void setTitleFontSize(Fraction size) {
51
         TextView titleTextView = getTitleTextView();
60
         TextView titleTextView = getTitleTextView();
52
         if (titleTextView != null && size.hasValue()) {
61
         if (titleTextView != null && size.hasValue()) {
53
             titleTextView.setTextSize(size.get());
62
             titleTextView.setTextSize(size.get());
54
         }
63
         }
55
     }
64
     }
56
 
65
 
57
-    void setTitleTypeface(Typeface typeface) {
66
+    public void setTitleTypeface(Typeface typeface) {
58
         TextView titleTextView = getTitleTextView();
67
         TextView titleTextView = getTitleTextView();
59
         if (titleTextView != null) {
68
         if (titleTextView != null) {
60
             titleTextView.setTypeface(typeface);
69
             titleTextView.setTypeface(typeface);
61
         }
70
         }
62
     }
71
     }
63
 
72
 
64
-    TextView getTitleTextView() {
73
+    public TextView getTitleTextView() {
65
         return findTextView(this);
74
         return findTextView(this);
66
     }
75
     }
67
 
76
 

+ 15
- 0
lib/android/app/src/main/java/com/reactnativenavigation/views/titlebar/TitleBarReactView.java View File

1
+package com.reactnativenavigation.views.titlebar;
2
+
3
+import android.annotation.SuppressLint;
4
+import android.content.Context;
5
+
6
+import com.facebook.react.ReactInstanceManager;
7
+import com.reactnativenavigation.react.ReactView;
8
+
9
+@SuppressLint("ViewConstructor")
10
+public class TitleBarReactView extends ReactView {
11
+
12
+    public TitleBarReactView(Context context, ReactInstanceManager reactInstanceManager, String componentId, String componentName) {
13
+        super(context, reactInstanceManager, componentId, componentName);
14
+    }
15
+}

+ 20
- 0
lib/android/app/src/main/java/com/reactnativenavigation/views/titlebar/TitleBarReactViewCreator.java View File

1
+package com.reactnativenavigation.views.titlebar;
2
+
3
+import android.app.Activity;
4
+
5
+import com.facebook.react.ReactInstanceManager;
6
+import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
7
+
8
+public class TitleBarReactViewCreator implements ReactViewCreator {
9
+
10
+    protected ReactInstanceManager instanceManager;
11
+
12
+    public TitleBarReactViewCreator(ReactInstanceManager instanceManager) {
13
+        this.instanceManager = instanceManager;
14
+	}
15
+
16
+	@Override
17
+	public TitleBarReactView create(Activity activity, String componentId, String componentName) {
18
+        return new TitleBarReactView(activity, instanceManager, componentId, componentName);
19
+    }
20
+}

+ 20
- 0
lib/android/app/src/test/java/com/reactnativenavigation/mocks/TitleBarReactViewCreatorMock.java View File

1
+package com.reactnativenavigation.mocks;
2
+
3
+import android.app.Activity;
4
+
5
+import com.facebook.react.ReactInstanceManager;
6
+import com.reactnativenavigation.views.titlebar.TitleBarReactView;
7
+import com.reactnativenavigation.views.titlebar.TitleBarReactViewCreator;
8
+
9
+import static org.mockito.Mockito.mock;
10
+
11
+public class TitleBarReactViewCreatorMock extends TitleBarReactViewCreator {
12
+    public TitleBarReactViewCreatorMock() {
13
+        super(mock(ReactInstanceManager.class));
14
+    }
15
+
16
+    @Override
17
+    public TitleBarReactView create(Activity activity, String componentId, String componentName) {
18
+        return new TitleBarReactView(activity, instanceManager, componentId, componentName);
19
+    }
20
+}

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/mocks/TopBarButtonCreatorMock.java View File

3
 import android.app.Activity;
3
 import android.app.Activity;
4
 
4
 
5
 import com.facebook.react.ReactInstanceManager;
5
 import com.facebook.react.ReactInstanceManager;
6
-import com.reactnativenavigation.react.TopBarReactButtonView;
6
+import com.reactnativenavigation.views.TopBarReactButtonView;
7
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
7
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
8
 
8
 
9
 import static org.mockito.Mockito.mock;
9
 import static org.mockito.Mockito.mock;

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

31
     private static final int TOP_BAR_FONT_SIZE = 18;
31
     private static final int TOP_BAR_FONT_SIZE = 18;
32
     private static final String TOP_BAR_FONT_FAMILY = "HelveticaNeue-CondensedBold";
32
     private static final String TOP_BAR_FONT_FAMILY = "HelveticaNeue-CondensedBold";
33
     private static final Typeface TOP_BAR_TYPEFACE = Typeface.create("HelveticaNeue-CondensedBold", Typeface.BOLD);
33
     private static final Typeface TOP_BAR_TYPEFACE = Typeface.create("HelveticaNeue-CondensedBold", Typeface.BOLD);
34
+    private static final String TITLE_ALIGNMENT = "center";
34
     private static final Bool TOP_BAR_VISIBLE = new Bool(true);
35
     private static final Bool TOP_BAR_VISIBLE = new Bool(true);
35
     private static final Bool TOP_BAR_DRAW_BEHIND = new Bool(true);
36
     private static final Bool TOP_BAR_DRAW_BEHIND = new Bool(true);
36
     private static final Bool TOP_BAR_HIDE_ON_SCROLL = new Bool(true);
37
     private static final Bool TOP_BAR_HIDE_ON_SCROLL = new Bool(true);
63
     }
64
     }
64
 
65
 
65
     private void assertResult(Options result) {
66
     private void assertResult(Options result) {
66
-        assertThat(result.topBarOptions.title.get()).isEqualTo(TITLE);
67
-        assertThat(result.topBarOptions.backgroundColor.get()).isEqualTo(TOP_BAR_BACKGROUND_COLOR);
68
-        assertThat(result.topBarOptions.textColor.get()).isEqualTo(TOP_BAR_TEXT_COLOR);
69
-        assertThat(result.topBarOptions.textFontSize.get()).isEqualTo(TOP_BAR_FONT_SIZE);
70
-        assertThat(result.topBarOptions.textFontFamily).isEqualTo(TOP_BAR_TYPEFACE);
67
+        assertThat(result.topBarOptions.title.text.get()).isEqualTo(TITLE);
68
+        assertThat(result.topBarOptions.background.color.get()).isEqualTo(TOP_BAR_BACKGROUND_COLOR);
69
+        assertThat(result.topBarOptions.title.color.get()).isEqualTo(TOP_BAR_TEXT_COLOR);
70
+        assertThat(result.topBarOptions.title.fontSize.get()).isEqualTo(TOP_BAR_FONT_SIZE);
71
+        assertThat(result.topBarOptions.title.fontFamily).isEqualTo(TOP_BAR_TYPEFACE);
71
         assertThat(result.topBarOptions.visible.get()).isEqualTo(TOP_BAR_VISIBLE.get());
72
         assertThat(result.topBarOptions.visible.get()).isEqualTo(TOP_BAR_VISIBLE.get());
72
         assertThat(result.topBarOptions.drawBehind.get()).isEqualTo(TOP_BAR_DRAW_BEHIND.get());
73
         assertThat(result.topBarOptions.drawBehind.get()).isEqualTo(TOP_BAR_DRAW_BEHIND.get());
73
         assertThat(result.topBarOptions.hideOnScroll.get()).isEqualTo(TOP_BAR_HIDE_ON_SCROLL.get());
74
         assertThat(result.topBarOptions.hideOnScroll.get()).isEqualTo(TOP_BAR_HIDE_ON_SCROLL.get());
83
         assertThat(result.fabOptions.hideOnScroll.get()).isEqualTo(FAB_HIDE_ON_SCROLL);
84
         assertThat(result.fabOptions.hideOnScroll.get()).isEqualTo(FAB_HIDE_ON_SCROLL);
84
         assertThat(result.fabOptions.alignVertically.get()).isEqualTo(FAB_ALIGN_VERTICALLY);
85
         assertThat(result.fabOptions.alignVertically.get()).isEqualTo(FAB_ALIGN_VERTICALLY);
85
         assertThat(result.fabOptions.alignHorizontally.get()).isEqualTo(FAB_ALIGN_HORIZONTALLY);
86
         assertThat(result.fabOptions.alignHorizontally.get()).isEqualTo(FAB_ALIGN_HORIZONTALLY);
87
+        assertThat(result.topBarOptions.title.alignment).isEqualTo(TitleOptions.Alignment.Center);
86
     }
88
     }
87
 
89
 
88
     @NonNull
90
     @NonNull
97
     @NonNull
99
     @NonNull
98
     private JSONObject createTopBar(boolean visible) throws JSONException {
100
     private JSONObject createTopBar(boolean visible) throws JSONException {
99
         return new JSONObject()
101
         return new JSONObject()
100
-                .put("title", "the title")
101
-                .put("backgroundColor", TOP_BAR_BACKGROUND_COLOR)
102
-                .put("textColor", TOP_BAR_TEXT_COLOR)
103
-                .put("textFontSize", TOP_BAR_FONT_SIZE)
104
-                .put("textFontFamily", TOP_BAR_FONT_FAMILY)
102
+                .put("title", createTitle())
103
+                .put("background", createBackground())
105
                 .put("visible", visible)
104
                 .put("visible", visible)
106
                 .put("drawBehind", TOP_BAR_DRAW_BEHIND.get())
105
                 .put("drawBehind", TOP_BAR_DRAW_BEHIND.get())
107
                 .put("hideOnScroll", TOP_BAR_HIDE_ON_SCROLL.get());
106
                 .put("hideOnScroll", TOP_BAR_HIDE_ON_SCROLL.get());
108
     }
107
     }
109
 
108
 
109
+    private JSONObject createBackground() throws JSONException {
110
+        return new JSONObject()
111
+                .put("color", TOP_BAR_BACKGROUND_COLOR);
112
+    }
113
+
114
+    private JSONObject createTitle() throws JSONException {
115
+        return new JSONObject()
116
+                .put("text", "the title")
117
+                .put("color", TOP_BAR_TEXT_COLOR)
118
+                .put("fontSize", TOP_BAR_FONT_SIZE)
119
+                .put("fontFamily", TOP_BAR_FONT_FAMILY)
120
+                .put("alignment", TITLE_ALIGNMENT);
121
+    }
122
+
110
     @NonNull
123
     @NonNull
111
     private JSONObject createFab() throws JSONException {
124
     private JSONObject createFab() throws JSONException {
112
         return new JSONObject()
125
         return new JSONObject()
136
     @NonNull
149
     @NonNull
137
     private JSONObject createOtherTopBar() throws JSONException {
150
     private JSONObject createOtherTopBar() throws JSONException {
138
         return new JSONObject()
151
         return new JSONObject()
139
-                .put("title", "the title")
140
-                .put("backgroundColor", TOP_BAR_BACKGROUND_COLOR)
141
-                .put("textColor", TOP_BAR_TEXT_COLOR)
142
-                .put("textFontSize", TOP_BAR_FONT_SIZE)
143
-                .put("textFontFamily", TOP_BAR_FONT_FAMILY)
152
+                .put("title", createTitle())
153
+                .put("background", createBackground())
144
                 .put("visible", TOP_BAR_VISIBLE);
154
                 .put("visible", TOP_BAR_VISIBLE);
145
     }
155
     }
146
 
156
 
159
         JSONObject json1 = new JSONObject();
169
         JSONObject json1 = new JSONObject();
160
         json1.put("topBar", createTopBar(true));
170
         json1.put("topBar", createTopBar(true));
161
         Options options1 = Options.parse(mockLoader, json1);
171
         Options options1 = Options.parse(mockLoader, json1);
162
-        options1.topBarOptions.title = new Text("some title");
172
+        options1.topBarOptions.title.text = new Text("some title");
163
 
173
 
164
         JSONObject json2 = new JSONObject();
174
         JSONObject json2 = new JSONObject();
165
         json2.put("topBar", createTopBar(false));
175
         json2.put("topBar", createTopBar(false));
166
         Options options2 = Options.parse(mockLoader, json2);
176
         Options options2 = Options.parse(mockLoader, json2);
167
-        options2.topBarOptions.title = new NullText();
177
+        options2.topBarOptions.title.text = new NullText();
168
 
178
 
169
         Options merged = options1.mergeWith(options2);
179
         Options merged = options1.mergeWith(options2);
170
         assertThat(options1.topBarOptions.visible.get()).isTrue();
180
         assertThat(options1.topBarOptions.visible.get()).isTrue();
171
         assertThat(merged.topBarOptions.visible.get()).isFalse();
181
         assertThat(merged.topBarOptions.visible.get()).isFalse();
172
-        assertThat(merged.topBarOptions.title.get()).isEqualTo("some title");
182
+        assertThat(merged.topBarOptions.title.text.get()).isEqualTo("some title");
173
     }
183
     }
174
 
184
 
175
     @Test
185
     @Test
203
     @Test
213
     @Test
204
     public void defaultEmptyOptions() throws Exception {
214
     public void defaultEmptyOptions() throws Exception {
205
         Options uut = new Options();
215
         Options uut = new Options();
206
-        assertThat(uut.topBarOptions.title.get("")).isEmpty();
216
+        assertThat(uut.topBarOptions.title.text.get("")).isEmpty();
207
     }
217
     }
208
 
218
 
209
     @Test
219
     @Test
216
     @Test
226
     @Test
217
     public void clear_topBarOptions() throws Exception {
227
     public void clear_topBarOptions() throws Exception {
218
         Options uut = new Options();
228
         Options uut = new Options();
219
-        uut.topBarOptions.title = new Text("some title");
229
+        uut.topBarOptions.title.text = new Text("some title");
220
         uut.clearTopBarOptions();
230
         uut.clearTopBarOptions();
221
-        assertThat(uut.topBarOptions.title.hasValue()).isFalse();
231
+        assertThat(uut.topBarOptions.title.text.hasValue()).isFalse();
222
     }
232
     }
223
 
233
 
224
     @Test
234
     @Test

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

8
 import com.reactnativenavigation.mocks.ImageLoaderMock;
8
 import com.reactnativenavigation.mocks.ImageLoaderMock;
9
 import com.reactnativenavigation.mocks.MockPromise;
9
 import com.reactnativenavigation.mocks.MockPromise;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
11
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
11
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
12
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
12
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.parse.params.Color;
14
 import com.reactnativenavigation.parse.params.Color;
100
     public void findControllerById_ReturnsSelfOrChildren() throws Exception {
101
     public void findControllerById_ReturnsSelfOrChildren() throws Exception {
101
         assertThat(uut.findControllerById("123")).isNull();
102
         assertThat(uut.findControllerById("123")).isNull();
102
         assertThat(uut.findControllerById(uut.getId())).isEqualTo(uut);
103
         assertThat(uut.findControllerById(uut.getId())).isEqualTo(uut);
103
-        StackController inner = new StackController(activity, new TopBarButtonCreatorMock(), "inner", tabOptions);
104
+        StackController inner = createStack("inner");
104
         inner.animatePush(child1, new MockPromise());
105
         inner.animatePush(child1, new MockPromise());
105
         assertThat(uut.findControllerById(child1.getId())).isNull();
106
         assertThat(uut.findControllerById(child1.getId())).isNull();
106
         uut.setTabs(Collections.singletonList(inner));
107
         uut.setTabs(Collections.singletonList(inner));
131
         uut.setTabs(tabs);
132
         uut.setTabs(tabs);
132
         uut.ensureViewIsCreated();
133
         uut.ensureViewIsCreated();
133
 
134
 
134
-        StackController stack = spy(new StackController(activity, new TopBarButtonCreatorMock(), "stack", new Options()));
135
+        StackController stack = spy(createStack("stack"));
135
         stack.ensureViewIsCreated();
136
         stack.ensureViewIsCreated();
136
         stack.push(uut, new MockPromise());
137
         stack.push(uut, new MockPromise());
137
 
138
 
169
     private List<ViewController> createTabs() {
170
     private List<ViewController> createTabs() {
170
         return Arrays.asList(child1, child2, child3, child4, child5);
171
         return Arrays.asList(child1, child2, child3, child4, child5);
171
     }
172
     }
173
+
174
+    private StackController createStack(String id) {
175
+        return new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), id, tabOptions);
176
+    }
172
 }
177
 }

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

5
 import com.reactnativenavigation.BaseTest;
5
 import com.reactnativenavigation.BaseTest;
6
 import com.reactnativenavigation.mocks.TestComponentLayout;
6
 import com.reactnativenavigation.mocks.TestComponentLayout;
7
 import com.reactnativenavigation.mocks.TestReactView;
7
 import com.reactnativenavigation.mocks.TestReactView;
8
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
8
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
9
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
9
 import com.reactnativenavigation.parse.Options;
10
 import com.reactnativenavigation.parse.Options;
10
 import com.reactnativenavigation.views.StackLayout;
11
 import com.reactnativenavigation.views.StackLayout;
26
         super.beforeEach();
27
         super.beforeEach();
27
         Activity activity = newActivity();
28
         Activity activity = newActivity();
28
         view = spy(new TestComponentLayout(activity, new TestReactView(activity)));
29
         view = spy(new TestComponentLayout(activity, new TestReactView(activity)));
29
-        ParentController<StackLayout> parentController = new StackController(activity, new TopBarButtonCreatorMock(), "stack", new Options());
30
+        ParentController<StackLayout> parentController = new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), "stack", new Options());
30
         uut = new ComponentViewController(activity, "componentId1", "componentName", (activity1, componentId, componentName) -> view, new Options());
31
         uut = new ComponentViewController(activity, "componentId1", "componentName", (activity1, componentId, componentName) -> view, new Options());
31
         uut.setParentController(parentController);
32
         uut.setParentController(parentController);
32
         parentController.ensureViewIsCreated();
33
         parentController.ensureViewIsCreated();

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

8
 import com.reactnativenavigation.BaseTest;
8
 import com.reactnativenavigation.BaseTest;
9
 import com.reactnativenavigation.mocks.MockPromise;
9
 import com.reactnativenavigation.mocks.MockPromise;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
11
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
11
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
12
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
12
 import com.reactnativenavigation.parse.FabOptions;
13
 import com.reactnativenavigation.parse.FabOptions;
13
 import com.reactnativenavigation.parse.Options;
14
 import com.reactnativenavigation.parse.Options;
33
     public void beforeEach() {
34
     public void beforeEach() {
34
         super.beforeEach();
35
         super.beforeEach();
35
         activity = newActivity();
36
         activity = newActivity();
36
-        stackController = new StackController(activity, new TopBarButtonCreatorMock(), "stackController", new Options());
37
+        stackController = new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), "stackController", new Options());
37
         Options options = getOptionsWithFab();
38
         Options options = getOptionsWithFab();
38
         childFab = new SimpleViewController(activity, "child1", options);
39
         childFab = new SimpleViewController(activity, "child1", options);
39
         childNoFab = new SimpleViewController(activity, "child2", new Options());
40
         childNoFab = new SimpleViewController(activity, "child2", new Options());

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

8
 import com.reactnativenavigation.mocks.MockPromise;
8
 import com.reactnativenavigation.mocks.MockPromise;
9
 import com.reactnativenavigation.mocks.SimpleComponentViewController;
9
 import com.reactnativenavigation.mocks.SimpleComponentViewController;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
11
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
11
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
12
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
12
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.parse.params.Text;
14
 import com.reactnativenavigation.parse.params.Text;
46
         imageLoaderMock = ImageLoaderMock.mock();
47
         imageLoaderMock = ImageLoaderMock.mock();
47
         activity = newActivity();
48
         activity = newActivity();
48
         uut = new Navigator(activity);
49
         uut = new Navigator(activity);
49
-        parentController = spy(new StackController(activity, new TopBarButtonCreatorMock(), "stack", new Options()));
50
+        parentController = spy(newStack());
50
         parentController.ensureViewIsCreated();
51
         parentController.ensureViewIsCreated();
51
         child1 = new SimpleViewController(activity, "child1", tabOptions);
52
         child1 = new SimpleViewController(activity, "child1", tabOptions);
52
         child2 = new SimpleViewController(activity, "child2", tabOptions);
53
         child2 = new SimpleViewController(activity, "child2", tabOptions);
226
     public void setOptions_CallsApplyNavigationOptions() {
227
     public void setOptions_CallsApplyNavigationOptions() {
227
         ComponentViewController componentVc = new SimpleComponentViewController(activity, "theId", new Options());
228
         ComponentViewController componentVc = new SimpleComponentViewController(activity, "theId", new Options());
228
         componentVc.setParentController(parentController);
229
         componentVc.setParentController(parentController);
229
-        assertThat(componentVc.options.topBarOptions.title.get("")).isEmpty();
230
+        assertThat(componentVc.options.topBarOptions.title.text.get("")).isEmpty();
230
         uut.setRoot(componentVc, new MockPromise());
231
         uut.setRoot(componentVc, new MockPromise());
231
 
232
 
232
         Options options = new Options();
233
         Options options = new Options();
233
-        options.topBarOptions.title = new Text("new title");
234
+        options.topBarOptions.title.text = new Text("new title");
234
 
235
 
235
         uut.setOptions("theId", options);
236
         uut.setOptions("theId", options);
236
-        assertThat(componentVc.options.topBarOptions.title.get()).isEqualTo("new title");
237
+        assertThat(componentVc.options.topBarOptions.title.text.get()).isEqualTo("new title");
237
     }
238
     }
238
 
239
 
239
     @Test
240
     @Test
248
 
249
 
249
     @NonNull
250
     @NonNull
250
     private StackController newStack() {
251
     private StackController newStack() {
251
-        return new StackController(activity, new TopBarButtonCreatorMock(), "stack" + CompatUtils.generateViewId(), tabOptions);
252
+        return new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), "stack" + CompatUtils.generateViewId(), tabOptions);
252
     }
253
     }
253
 
254
 
254
     @Test
255
     @Test
325
 
326
 
326
     @Test
327
     @Test
327
     public void pushedStackCanBePopped() throws Exception {
328
     public void pushedStackCanBePopped() throws Exception {
328
-        StackController parent = new StackController(activity, new TopBarButtonCreatorMock(), "someStack", new Options());
329
+        StackController parent = newStack();
329
         parent.ensureViewIsCreated();
330
         parent.ensureViewIsCreated();
330
         uut.setRoot(parent, new MockPromise());
331
         uut.setRoot(parent, new MockPromise());
331
         parent.push(parentController, new MockPromise());
332
         parent.push(parentController, new MockPromise());

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

10
 import com.reactnativenavigation.mocks.MockPromise;
10
 import com.reactnativenavigation.mocks.MockPromise;
11
 import com.reactnativenavigation.mocks.TestComponentLayout;
11
 import com.reactnativenavigation.mocks.TestComponentLayout;
12
 import com.reactnativenavigation.mocks.TestReactView;
12
 import com.reactnativenavigation.mocks.TestReactView;
13
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
13
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
14
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
14
 import com.reactnativenavigation.parse.Options;
15
 import com.reactnativenavigation.parse.Options;
15
 import com.reactnativenavigation.parse.params.Bool;
16
 import com.reactnativenavigation.parse.params.Bool;
45
                 (activity1, componentId, componentName) -> view,
46
                 (activity1, componentId, componentName) -> view,
46
                 initialNavigationOptions
47
                 initialNavigationOptions
47
         );
48
         );
48
-        stackController = new StackController(activity, new TopBarButtonCreatorMock(), "stack", new Options());
49
+        stackController = new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), "stack", new Options());
49
         stackController.ensureViewIsCreated();
50
         stackController.ensureViewIsCreated();
50
         uut.setParentController(stackController);
51
         uut.setParentController(stackController);
51
     }
52
     }
61
 
62
 
62
     @Test
63
     @Test
63
     public void initialOptionsAppliedOnAppear() throws Exception {
64
     public void initialOptionsAppliedOnAppear() throws Exception {
64
-        uut.options.topBarOptions.title = new Text("the title");
65
-        StackController stackController = new StackController(activity, new TopBarButtonCreatorMock(), "stackId", new Options());
65
+        uut.options.topBarOptions.title.text = new Text("the title");
66
+        StackController stackController = new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), "stackId", new Options());
66
         stackController.animatePush(uut, new MockPromise() {});
67
         stackController.animatePush(uut, new MockPromise() {});
67
         assertThat(stackController.getTopBar().getTitle()).isEmpty();
68
         assertThat(stackController.getTopBar().getTitle()).isEmpty();
68
 
69
 
73
     @Test
74
     @Test
74
     public void mergeNavigationOptionsUpdatesCurrentOptions() throws Exception {
75
     public void mergeNavigationOptionsUpdatesCurrentOptions() throws Exception {
75
         uut.ensureViewIsCreated();
76
         uut.ensureViewIsCreated();
76
-        assertThat(uut.options.topBarOptions.title.get("")).isEmpty();
77
+        assertThat(uut.options.topBarOptions.title.text.get("")).isEmpty();
77
         Options options = new Options();
78
         Options options = new Options();
78
-        options.topBarOptions.title = new Text("new title");
79
+        options.topBarOptions.title.text = new Text("new title");
79
         uut.mergeOptions(options);
80
         uut.mergeOptions(options);
80
-        assertThat(uut.options.topBarOptions.title.get()).isEqualTo("new title");
81
+        assertThat(uut.options.topBarOptions.title.text.get()).isEqualTo("new title");
81
     }
82
     }
82
 
83
 
83
     @Test
84
     @Test
87
         assertThat(stackController.getTopBar().getTitle()).isEmpty();
88
         assertThat(stackController.getTopBar().getTitle()).isEmpty();
88
 
89
 
89
         Options opts = new Options();
90
         Options opts = new Options();
90
-        opts.topBarOptions.title = new Text("the new title");
91
+        opts.topBarOptions.title.text = new Text("the new title");
91
         uut.mergeOptions(opts);
92
         uut.mergeOptions(opts);
92
 
93
 
93
         assertThat(stackController.getTopBar().getTitle()).isEqualTo("the new title");
94
         assertThat(stackController.getTopBar().getTitle()).isEqualTo("the new title");
99
         uut.onViewAppeared();
100
         uut.onViewAppeared();
100
 
101
 
101
         Options opts = new Options();
102
         Options opts = new Options();
102
-        opts.topBarOptions.backgroundColor = new com.reactnativenavigation.parse.params.Color(Color.RED);
103
+        opts.topBarOptions.background.color = new com.reactnativenavigation.parse.params.Color(Color.RED);
103
         uut.mergeOptions(opts);
104
         uut.mergeOptions(opts);
104
 
105
 
105
         assertThat(((ColorDrawable) stackController.getTopBar().getTitleBar().getBackground()).getColor()).isEqualTo(Color.RED);
106
         assertThat(((ColorDrawable) stackController.getTopBar().getTitleBar().getBackground()).getColor()).isEqualTo(Color.RED);
112
             @Override
113
             @Override
113
             public void resolve(@Nullable Object value) {
114
             public void resolve(@Nullable Object value) {
114
                 Options opts = new Options();
115
                 Options opts = new Options();
115
-                opts.topBarOptions.title = new Text("the title");
116
-                opts.topBarOptions.textColor = new com.reactnativenavigation.parse.params.Color(Color.RED);
116
+                opts.topBarOptions.title.text = new Text("the title");
117
+                opts.topBarOptions.title.color = new com.reactnativenavigation.parse.params.Color(Color.RED);
117
                 uut.mergeOptions(opts);
118
                 uut.mergeOptions(opts);
118
 
119
 
119
                 assertThat(stackController.getTopBar().getTitleTextView()).isNotEqualTo(null);
120
                 assertThat(stackController.getTopBar().getTitleTextView()).isNotEqualTo(null);
125
     @Test
126
     @Test
126
     public void appliesTopBarTextSize() throws Exception {
127
     public void appliesTopBarTextSize() throws Exception {
127
         assertThat(uut.initialOptions).isSameAs(initialNavigationOptions);
128
         assertThat(uut.initialOptions).isSameAs(initialNavigationOptions);
128
-        initialNavigationOptions.topBarOptions.title = new Text("the title");
129
+        initialNavigationOptions.topBarOptions.title.text = new Text("the title");
129
         uut.ensureViewIsCreated();
130
         uut.ensureViewIsCreated();
130
         uut.onViewAppeared();
131
         uut.onViewAppeared();
131
 
132
 
132
         Options opts = new Options();
133
         Options opts = new Options();
133
-        opts.topBarOptions.title = new Text("the title");
134
-        opts.topBarOptions.textFontSize = new Fraction(18);
134
+        opts.topBarOptions.title.text = new Text("the title");
135
+        opts.topBarOptions.title.fontSize = new Fraction(18);
135
         uut.mergeOptions(opts);
136
         uut.mergeOptions(opts);
136
 
137
 
137
         assertThat(stackController.getTopBar().getTitleTextView()).isNotEqualTo(null);
138
         assertThat(stackController.getTopBar().getTitleTextView()).isNotEqualTo(null);
141
     @Test
142
     @Test
142
     public void appliesTopBarVisible() throws Exception {
143
     public void appliesTopBarVisible() throws Exception {
143
         assertThat(uut.initialOptions).isSameAs(initialNavigationOptions);
144
         assertThat(uut.initialOptions).isSameAs(initialNavigationOptions);
144
-        initialNavigationOptions.topBarOptions.title = new Text("the title");
145
+        initialNavigationOptions.topBarOptions.title.text = new Text("the title");
145
         uut.ensureViewIsCreated();
146
         uut.ensureViewIsCreated();
146
         uut.onViewAppeared();
147
         uut.onViewAppeared();
147
         assertThat(stackController.getTopBar().getVisibility()).isNotEqualTo(View.GONE);
148
         assertThat(stackController.getTopBar().getVisibility()).isNotEqualTo(View.GONE);
156
 
157
 
157
     @Test
158
     @Test
158
     public void appliesDrawUnder() throws Exception {
159
     public void appliesDrawUnder() throws Exception {
159
-        uut.options.topBarOptions.title = new Text("the title");
160
+        uut.options.topBarOptions.title.text = new Text("the title");
160
         uut.options.topBarOptions.drawBehind = new Bool(false);
161
         uut.options.topBarOptions.drawBehind = new Bool(false);
161
         uut.ensureViewIsCreated();
162
         uut.ensureViewIsCreated();
162
         stackController.animatePush(uut, new MockPromise() {
163
         stackController.animatePush(uut, new MockPromise() {

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

8
 import com.reactnativenavigation.BaseTest;
8
 import com.reactnativenavigation.BaseTest;
9
 import com.reactnativenavigation.mocks.MockPromise;
9
 import com.reactnativenavigation.mocks.MockPromise;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
11
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
11
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
12
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
12
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.parse.params.Text;
14
 import com.reactnativenavigation.parse.params.Text;
38
         activity = newActivity();
39
         activity = newActivity();
39
         children = new ArrayList<>();
40
         children = new ArrayList<>();
40
         Options initialOptions = new Options();
41
         Options initialOptions = new Options();
41
-        initialOptions.topBarOptions.title = new Text(INITIAL_TITLE);
42
+        initialOptions.topBarOptions.title.text = new Text(INITIAL_TITLE);
42
         uut = spy(new ParentController(activity, "uut", initialOptions) {
43
         uut = spy(new ParentController(activity, "uut", initialOptions) {
43
 
44
 
44
             @NonNull
45
             @NonNull
88
 
89
 
89
     @Test
90
     @Test
90
     public void findControllerById_Recursive() throws Exception {
91
     public void findControllerById_Recursive() throws Exception {
91
-        StackController stackController = new StackController(activity, new TopBarButtonCreatorMock(), "stack", new Options());
92
+        StackController stackController = createStack();
92
         SimpleViewController child1 = new SimpleViewController(activity, "child1", new Options());
93
         SimpleViewController child1 = new SimpleViewController(activity, "child1", new Options());
93
         SimpleViewController child2 = new SimpleViewController(activity, "child2", new Options());
94
         SimpleViewController child2 = new SimpleViewController(activity, "child2", new Options());
94
         stackController.animatePush(child1, new MockPromise());
95
         stackController.animatePush(child1, new MockPromise());
110
 
111
 
111
     @Test
112
     @Test
112
     public void optionsAreClearedWhenChildIsAppeared() throws Exception {
113
     public void optionsAreClearedWhenChildIsAppeared() throws Exception {
113
-        StackController stackController = spy(new StackController(activity, new TopBarButtonCreatorMock(), "stack", new Options()));
114
+        StackController stackController = spy(createStack());
114
         SimpleViewController child1 = new SimpleViewController(activity, "child1", new Options());
115
         SimpleViewController child1 = new SimpleViewController(activity, "child1", new Options());
115
         stackController.animatePush(child1, new MockPromise());
116
         stackController.animatePush(child1, new MockPromise());
116
 
117
 
121
     @Test
122
     @Test
122
     public void mergeOptions_optionsAreMergedWhenChildAppears() throws Exception {
123
     public void mergeOptions_optionsAreMergedWhenChildAppears() throws Exception {
123
         Options options = new Options();
124
         Options options = new Options();
124
-        options.topBarOptions.title = new Text("new title");
125
+        options.topBarOptions.title.text = new Text("new title");
125
         ViewController child1 = spy(new SimpleViewController(activity, "child1", options));
126
         ViewController child1 = spy(new SimpleViewController(activity, "child1", options));
126
         children.add(child1);
127
         children.add(child1);
127
         uut.ensureViewIsCreated();
128
         uut.ensureViewIsCreated();
132
         ArgumentCaptor<ReactComponent> viewCaptor = ArgumentCaptor.forClass(ReactComponent.class);
133
         ArgumentCaptor<ReactComponent> viewCaptor = ArgumentCaptor.forClass(ReactComponent.class);
133
         verify(uut, times(1)).clearOptions();
134
         verify(uut, times(1)).clearOptions();
134
         verify(uut, times(1)).applyOptions(optionsCaptor.capture(), viewCaptor.capture());
135
         verify(uut, times(1)).applyOptions(optionsCaptor.capture(), viewCaptor.capture());
135
-        assertThat(optionsCaptor.getValue().topBarOptions.title.get()).isEqualTo("new title");
136
+        assertThat(optionsCaptor.getValue().topBarOptions.title.text.get()).isEqualTo("new title");
136
         assertThat(viewCaptor.getValue()).isEqualTo(child1.getView());
137
         assertThat(viewCaptor.getValue()).isEqualTo(child1.getView());
137
     }
138
     }
138
 
139
 
139
     @Test
140
     @Test
140
     public void mergeOptions_initialParentOptionsAreNotMutatedWhenChildAppears() throws Exception {
141
     public void mergeOptions_initialParentOptionsAreNotMutatedWhenChildAppears() throws Exception {
141
         Options options = new Options();
142
         Options options = new Options();
142
-        options.topBarOptions.title = new Text("new title");
143
+        options.topBarOptions.title.text = new Text("new title");
143
         ViewController child1 = spy(new SimpleViewController(activity, "child1", options));
144
         ViewController child1 = spy(new SimpleViewController(activity, "child1", options));
144
         children.add(child1);
145
         children.add(child1);
145
 
146
 
147
 
148
 
148
         child1.ensureViewIsCreated();
149
         child1.ensureViewIsCreated();
149
         child1.onViewAppeared();
150
         child1.onViewAppeared();
150
-        assertThat(uut.initialOptions.topBarOptions.title.get()).isEqualTo(INITIAL_TITLE);
151
+        assertThat(uut.initialOptions.topBarOptions.title.text.get()).isEqualTo(INITIAL_TITLE);
152
+    }
153
+
154
+    private StackController createStack() {
155
+        return new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), "stack", new Options());
151
     }
156
     }
152
 }
157
 }

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

7
 import com.reactnativenavigation.BaseTest;
7
 import com.reactnativenavigation.BaseTest;
8
 import com.reactnativenavigation.mocks.MockPromise;
8
 import com.reactnativenavigation.mocks.MockPromise;
9
 import com.reactnativenavigation.mocks.SimpleViewController;
9
 import com.reactnativenavigation.mocks.SimpleViewController;
10
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
10
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
11
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
11
 import com.reactnativenavigation.parse.Options;
12
 import com.reactnativenavigation.parse.Options;
12
 import com.reactnativenavigation.parse.params.Bool;
13
 import com.reactnativenavigation.parse.params.Bool;
39
     public void beforeEach() {
40
     public void beforeEach() {
40
         super.beforeEach();
41
         super.beforeEach();
41
         activity = newActivity();
42
         activity = newActivity();
42
-        uut = new StackController(activity, new TopBarButtonCreatorMock(), "uut", new Options());
43
+        uut = createStackController("uut");
43
         child1 = spy(new SimpleViewController(activity, "child1", new Options()));
44
         child1 = spy(new SimpleViewController(activity, "child1", new Options()));
44
         child2 = spy(new SimpleViewController(activity, "child2", new Options()));
45
         child2 = spy(new SimpleViewController(activity, "child2", new Options()));
45
         child3 = spy(new SimpleViewController(activity, "child3", new Options()));
46
         child3 = spy(new SimpleViewController(activity, "child3", new Options()));
95
     @Test
96
     @Test
96
     public void pop_layoutHandlesChildWillDisappear() throws Exception {
97
     public void pop_layoutHandlesChildWillDisappear() throws Exception {
97
         final StackLayout[] stackLayout = new StackLayout[1];
98
         final StackLayout[] stackLayout = new StackLayout[1];
98
-        uut = new StackController(activity, new TopBarButtonCreatorMock(), "uut", new Options()) {
99
+        uut = new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), "uut", new Options()) {
99
             @NonNull
100
             @NonNull
100
             @Override
101
             @Override
101
             protected StackLayout createView() {
102
             protected StackLayout createView() {
134
         uut.animatePush(child1, new MockPromise());
135
         uut.animatePush(child1, new MockPromise());
135
         assertThat(child1.getParentController()).isEqualTo(uut);
136
         assertThat(child1.getParentController()).isEqualTo(uut);
136
 
137
 
137
-        StackController anotherNavController = new StackController(activity, new TopBarButtonCreatorMock(), "another", new Options());
138
+        StackController anotherNavController = createStackController("another");
138
         anotherNavController.animatePush(child2, new MockPromise());
139
         anotherNavController.animatePush(child2, new MockPromise());
139
         assertThat(child2.getParentController()).isEqualTo(anotherNavController);
140
         assertThat(child2.getParentController()).isEqualTo(anotherNavController);
140
     }
141
     }
314
 
315
 
315
     @Test
316
     @Test
316
     public void findControllerById_Deeply() throws Exception {
317
     public void findControllerById_Deeply() throws Exception {
317
-        StackController stack = new StackController(activity, new TopBarButtonCreatorMock(), "stack2", new Options());
318
+        StackController stack = createStackController("stack2");
318
         stack.animatePush(child2, new MockPromise());
319
         stack.animatePush(child2, new MockPromise());
319
         uut.animatePush(stack, new MockPromise());
320
         uut.animatePush(stack, new MockPromise());
320
         assertThat(uut.findControllerById(child2.getId())).isEqualTo(child2);
321
         assertThat(uut.findControllerById(child2.getId())).isEqualTo(child2);
409
 
410
 
410
     @Test
411
     @Test
411
     public void stackCanBePushed() throws Exception {
412
     public void stackCanBePushed() throws Exception {
412
-        StackController parent = new StackController(activity, new TopBarButtonCreatorMock(), "someStack", new Options());
413
+        StackController parent = createStackController("someStack");
413
         parent.ensureViewIsCreated();
414
         parent.ensureViewIsCreated();
414
         parent.push(uut, new MockPromise());
415
         parent.push(uut, new MockPromise());
415
         uut.onViewAppeared();
416
         uut.onViewAppeared();
418
 
419
 
419
     @Test
420
     @Test
420
     public void applyOptions_applyOnlyOnFirstStack() throws Exception {
421
     public void applyOptions_applyOnlyOnFirstStack() throws Exception {
421
-        StackController parent = spy(new StackController(activity, new TopBarButtonCreatorMock(), "someStack", new Options()));
422
+        StackController parent = spy(createStackController("someStack"));
422
         parent.ensureViewIsCreated();
423
         parent.ensureViewIsCreated();
423
         parent.push(uut, new MockPromise());
424
         parent.push(uut, new MockPromise());
424
 
425
 
425
         Options childOptions = new Options();
426
         Options childOptions = new Options();
426
-        childOptions.topBarOptions.title = new Text("Something");
427
+        childOptions.topBarOptions.title.text = new Text("Something");
427
         child1.options = childOptions;
428
         child1.options = childOptions;
428
         uut.push(child1, new MockPromise());
429
         uut.push(child1, new MockPromise());
429
         child1.ensureViewIsCreated();
430
         child1.ensureViewIsCreated();
432
         ArgumentCaptor<Options> optionsCaptor = ArgumentCaptor.forClass(Options.class);
433
         ArgumentCaptor<Options> optionsCaptor = ArgumentCaptor.forClass(Options.class);
433
         ArgumentCaptor<ReactComponent> viewCaptor = ArgumentCaptor.forClass(ReactComponent.class);
434
         ArgumentCaptor<ReactComponent> viewCaptor = ArgumentCaptor.forClass(ReactComponent.class);
434
         verify(parent, times(1)).applyOptions(optionsCaptor.capture(), viewCaptor.capture());
435
         verify(parent, times(1)).applyOptions(optionsCaptor.capture(), viewCaptor.capture());
435
-        assertThat(optionsCaptor.getValue().topBarOptions.title.hasValue()).isFalse();
436
+        assertThat(optionsCaptor.getValue().topBarOptions.title.text.hasValue()).isFalse();
436
     }
437
     }
437
 
438
 
438
     @Test
439
     @Test
456
         assertThat(uut.size()).isEqualTo(ids.length);
457
         assertThat(uut.size()).isEqualTo(ids.length);
457
         assertThat(uut.getChildControllers()).extracting((Extractor<ViewController, String>) ViewController::getId).containsOnly(ids);
458
         assertThat(uut.getChildControllers()).extracting((Extractor<ViewController, String>) ViewController::getId).containsOnly(ids);
458
     }
459
     }
460
+
461
+    private StackController createStackController(String id) {
462
+        return new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), id, new Options());
463
+    }
459
 }
464
 }

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

1
 package com.reactnativenavigation.viewcontrollers;
1
 package com.reactnativenavigation.viewcontrollers;
2
 
2
 
3
 import android.app.Activity;
3
 import android.app.Activity;
4
+import android.view.ViewGroup;
4
 
5
 
5
 import com.reactnativenavigation.BaseTest;
6
 import com.reactnativenavigation.BaseTest;
7
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
6
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
8
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
9
+import com.reactnativenavigation.parse.TitleOptions;
7
 import com.reactnativenavigation.parse.params.Button;
10
 import com.reactnativenavigation.parse.params.Button;
8
 import com.reactnativenavigation.parse.params.Text;
11
 import com.reactnativenavigation.parse.params.Text;
9
 import com.reactnativenavigation.react.ReactView;
12
 import com.reactnativenavigation.react.ReactView;
10
-import com.reactnativenavigation.views.TitleBar;
13
+import com.reactnativenavigation.views.titlebar.TitleBar;
14
+import com.reactnativenavigation.views.titlebar.TitleBarReactView;
11
 
15
 
12
 import org.junit.Test;
16
 import org.junit.Test;
13
 
17
 
19
 import java.util.Map;
23
 import java.util.Map;
20
 
24
 
21
 import static org.assertj.core.api.Java6Assertions.assertThat;
25
 import static org.assertj.core.api.Java6Assertions.assertThat;
26
+import static org.mockito.ArgumentMatchers.any;
27
+import static org.mockito.ArgumentMatchers.eq;
22
 import static org.mockito.Mockito.spy;
28
 import static org.mockito.Mockito.spy;
23
 import static org.mockito.Mockito.times;
29
 import static org.mockito.Mockito.times;
24
 import static org.mockito.Mockito.verify;
30
 import static org.mockito.Mockito.verify;
35
     public void beforeEach() {
41
     public void beforeEach() {
36
         final TopBarButtonCreatorMock buttonCreator = new TopBarButtonCreatorMock();
42
         final TopBarButtonCreatorMock buttonCreator = new TopBarButtonCreatorMock();
37
         final Activity activity = newActivity();
43
         final Activity activity = newActivity();
44
+        TitleBarReactViewController reactViewController = new TitleBarReactViewController(activity, new TitleBarReactViewCreatorMock());
38
         createButtons();
45
         createButtons();
39
         buttonControllers = new HashMap<>();
46
         buttonControllers = new HashMap<>();
40
-        uut = spy(new TitleBar(activity, buttonCreator, (buttonId -> {})) {
47
+        uut = spy(new TitleBar(activity, buttonCreator, reactViewController, (buttonId -> {})) {
41
             @Override
48
             @Override
42
             public TopBarButtonController createButtonController(Button button) {
49
             public TopBarButtonController createButtonController(Button button) {
43
                 TopBarButtonController controller = spy(super.createButtonController(button));
50
                 TopBarButtonController controller = spy(super.createButtonController(button));
120
         assertThat(uut.getMenu().getItem(1).getTitle()).isEqualTo(textButton.title.get());
127
         assertThat(uut.getMenu().getItem(1).getTitle()).isEqualTo(textButton.title.get());
121
     }
128
     }
122
 
129
 
130
+    @Test
131
+    public void setComponent_addsComponentToTitleBar() {
132
+        uut.setComponent("com.rnn.CustomView", TitleOptions.Alignment.Center);
133
+        final int height = uut.getHeight();
134
+        verify(uut, times(1)).addView(any(TitleBarReactView.class), eq(ViewGroup.LayoutParams.WRAP_CONTENT), eq(height));
135
+    }
136
+
123
     private List<Button> leftButton(Button leftButton) {
137
     private List<Button> leftButton(Button leftButton) {
124
         return Collections.singletonList(leftButton);
138
         return Collections.singletonList(leftButton);
125
     }
139
     }

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

4
 import android.support.annotation.NonNull;
4
 import android.support.annotation.NonNull;
5
 
5
 
6
 import com.reactnativenavigation.BaseTest;
6
 import com.reactnativenavigation.BaseTest;
7
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
7
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
8
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
8
 import com.reactnativenavigation.parse.Options;
9
 import com.reactnativenavigation.parse.Options;
9
 import com.reactnativenavigation.parse.params.Button;
10
 import com.reactnativenavigation.parse.params.Button;
28
 
29
 
29
         TopBarButtonCreatorMock buttonCreatorMock = new TopBarButtonCreatorMock();
30
         TopBarButtonCreatorMock buttonCreatorMock = new TopBarButtonCreatorMock();
30
         uut = spy(new TopBarButtonController(activity, button, buttonCreatorMock, (buttonId) -> {}));
31
         uut = spy(new TopBarButtonController(activity, button, buttonCreatorMock, (buttonId) -> {}));
31
-        stackController = spy(new StackController(activity, buttonCreatorMock, "stack", new Options()));
32
+        stackController = spy(new StackController(activity, buttonCreatorMock, new TitleBarReactViewCreatorMock(), "stack", new Options()));
32
 
33
 
33
     }
34
     }
34
 
35
 

+ 12
- 6
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsViewControllerTest.java View File

8
 import com.reactnativenavigation.mocks.MockPromise;
8
 import com.reactnativenavigation.mocks.MockPromise;
9
 import com.reactnativenavigation.mocks.TestComponentViewCreator;
9
 import com.reactnativenavigation.mocks.TestComponentViewCreator;
10
 import com.reactnativenavigation.mocks.TestReactView;
10
 import com.reactnativenavigation.mocks.TestReactView;
11
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
11
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
12
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
12
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.parse.Options;
13
 import com.reactnativenavigation.parse.params.Text;
14
 import com.reactnativenavigation.parse.params.Text;
60
         uut = spy(new TopTabsController(activity, "componentId", tabControllers, layoutCreator, options));
61
         uut = spy(new TopTabsController(activity, "componentId", tabControllers, layoutCreator, options));
61
         tabControllers.forEach(viewController -> viewController.setParentController(uut));
62
         tabControllers.forEach(viewController -> viewController.setParentController(uut));
62
 
63
 
63
-        parentController = spy(new StackController(activity, new TopBarButtonCreatorMock(), "stackId", new Options()));
64
+        parentController = spy(createStackController("stackId"));
64
         parentController.push(uut, new MockPromise());
65
         parentController.push(uut, new MockPromise());
65
         uut.setParentController(parentController);
66
         uut.setParentController(parentController);
66
     }
67
     }
67
 
68
 
69
+    @NonNull
70
+    private StackController createStackController(String id) {
71
+        return new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), id, new Options());
72
+    }
73
+
68
     @NonNull
74
     @NonNull
69
     private ArrayList<Options> createOptions() {
75
     private ArrayList<Options> createOptions() {
70
         ArrayList result = new ArrayList();
76
         ArrayList result = new ArrayList();
71
         for (int i = 0; i < SIZE; i++) {
77
         for (int i = 0; i < SIZE; i++) {
72
             final Options options = new Options();
78
             final Options options = new Options();
73
             options.topTabOptions.title = new Text("Tab " + i);
79
             options.topTabOptions.title = new Text("Tab " + i);
74
-            options.topBarOptions.title = new Text(createTabTopBarTitle(i));
80
+            options.topBarOptions.title.text = new Text(createTabTopBarTitle(i));
75
             result.add(options);
81
             result.add(options);
76
         }
82
         }
77
         return result;
83
         return result;
173
         uut.onViewAppeared();
179
         uut.onViewAppeared();
174
         ReactComponent currentTab = tabView(0);
180
         ReactComponent currentTab = tabView(0);
175
         verify(uut, times(1)).applyOptions(any(Options.class), eq(currentTab));
181
         verify(uut, times(1)).applyOptions(any(Options.class), eq(currentTab));
176
-        assertThat(uut.options.topBarOptions.title.get()).isEqualTo(createTabTopBarTitle(0));
182
+        assertThat(uut.options.topBarOptions.title.text.get()).isEqualTo(createTabTopBarTitle(0));
177
 
183
 
178
         uut.switchToTab(1);
184
         uut.switchToTab(1);
179
         currentTab = tabView(1);
185
         currentTab = tabView(1);
180
         verify(uut, times(1)).applyOptions(any(Options.class), eq(currentTab));
186
         verify(uut, times(1)).applyOptions(any(Options.class), eq(currentTab));
181
-        assertThat(uut.options.topBarOptions.title.get()).isEqualTo(createTabTopBarTitle(1));
187
+        assertThat(uut.options.topBarOptions.title.text.get()).isEqualTo(createTabTopBarTitle(1));
182
 
188
 
183
         uut.switchToTab(0);
189
         uut.switchToTab(0);
184
         currentTab = tabView(0);
190
         currentTab = tabView(0);
185
         verify(uut, times(2)).applyOptions(any(Options.class), eq(currentTab));
191
         verify(uut, times(2)).applyOptions(any(Options.class), eq(currentTab));
186
-        assertThat(uut.options.topBarOptions.title.get()).isEqualTo(createTabTopBarTitle(0));
192
+        assertThat(uut.options.topBarOptions.title.text.get()).isEqualTo(createTabTopBarTitle(0));
187
     }
193
     }
188
 
194
 
189
     private TestReactView getActualTabView(int index) {
195
     private TestReactView getActualTabView(int index) {
215
     public void applyOptions_tabsAreRemovedAfterViewDisappears() throws Exception {
221
     public void applyOptions_tabsAreRemovedAfterViewDisappears() throws Exception {
216
         parentController.getView().removeAllViews();
222
         parentController.getView().removeAllViews();
217
 
223
 
218
-        StackController stackController = spy(new StackController(activity, new TopBarButtonCreatorMock(), "stack", new Options()));
224
+        StackController stackController = spy(createStackController("stack"));
219
         ComponentViewController first = new ComponentViewController(
225
         ComponentViewController first = new ComponentViewController(
220
                 activity,
226
                 activity,
221
                 "firstScreen",
227
                 "firstScreen",

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

9
 import com.reactnativenavigation.BaseTest;
9
 import com.reactnativenavigation.BaseTest;
10
 import com.reactnativenavigation.mocks.MockPromise;
10
 import com.reactnativenavigation.mocks.MockPromise;
11
 import com.reactnativenavigation.mocks.SimpleViewController;
11
 import com.reactnativenavigation.mocks.SimpleViewController;
12
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
12
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
13
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
13
 import com.reactnativenavigation.parse.Options;
14
 import com.reactnativenavigation.parse.Options;
14
 
15
 
66
     @Test
67
     @Test
67
     public void holdsAReferenceToStackControllerOrNull() throws Exception {
68
     public void holdsAReferenceToStackControllerOrNull() throws Exception {
68
         assertThat(uut.getParentController()).isNull();
69
         assertThat(uut.getParentController()).isNull();
69
-        StackController nav = new StackController(activity, new TopBarButtonCreatorMock(), "stack", new Options());
70
+        StackController nav = new StackController(activity, new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), "stack", new Options());
70
         nav.animatePush(uut, new MockPromise());
71
         nav.animatePush(uut, new MockPromise());
71
         assertThat(uut.getParentController()).isEqualTo(nav);
72
         assertThat(uut.getParentController()).isEqualTo(nav);
72
     }
73
     }

+ 3
- 2
lib/android/app/src/test/java/com/reactnativenavigation/views/TopBarTest.java View File

5
 
5
 
6
 import com.reactnativenavigation.BaseTest;
6
 import com.reactnativenavigation.BaseTest;
7
 import com.reactnativenavigation.anim.TopBarAnimator;
7
 import com.reactnativenavigation.anim.TopBarAnimator;
8
+import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
8
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
9
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
9
 import com.reactnativenavigation.parse.params.Bool;
10
 import com.reactnativenavigation.parse.params.Bool;
10
 import com.reactnativenavigation.parse.params.Button;
11
 import com.reactnativenavigation.parse.params.Button;
38
                 Log.i("TopBarTest", "onPress: " + buttonId);
39
                 Log.i("TopBarTest", "onPress: " + buttonId);
39
             }
40
             }
40
         });
41
         });
41
-        StackLayout parent = new StackLayout(newActivity(), new TopBarButtonCreatorMock(), this.onClickListener);
42
-        uut = new TopBar(newActivity(), new TopBarButtonCreatorMock(), this.onClickListener, parent);
42
+        StackLayout parent = new StackLayout(newActivity(), new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), this.onClickListener);
43
+        uut = new TopBar(newActivity(), new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), this.onClickListener, parent);
43
         animator = spy(new TopBarAnimator(uut));
44
         animator = spy(new TopBarAnimator(uut));
44
         uut.setAnimator(animator);
45
         uut.setAnimator(animator);
45
         leftButton = createLeftButton();
46
         leftButton = createLeftButton();

+ 5
- 2
lib/ios/RNNCustomTitleView.h View File

1
 #import <UIKit/UIKit.h>
1
 #import <UIKit/UIKit.h>
2
+#import <React/RCTRootView.h>
3
+#import <React/RCTRootViewDelegate.h>
2
 
4
 
3
-@interface RNNCustomTitleView : UIView
5
+@interface RNNCustomTitleView : UIView <RCTRootViewDelegate>
4
 
6
 
5
--(instancetype)initWithFrame:(CGRect)frame subView:(UIView*)subView alignment:(NSString*)alignment;
7
+- (instancetype)initWithFrame:(CGRect)frame subView:(RCTRootView*)subView alignment:(NSString*)alignment;
6
 
8
 
7
 @end
9
 @end
10
+

+ 41
- 33
lib/ios/RNNCustomTitleView.m View File

1
 #import "RNNCustomTitleView.h"
1
 #import "RNNCustomTitleView.h"
2
 
2
 
3
 @interface RNNCustomTitleView ()
3
 @interface RNNCustomTitleView ()
4
-@property (nonatomic, strong) UIView *subView;
5
-@property (nonatomic, strong) NSString *subViewAlign;
4
+
5
+@property (nonatomic, strong) RCTRootView *subView;
6
+@property (nonatomic, strong) NSString *alignment;
7
+
6
 @end
8
 @end
7
 
9
 
8
 @implementation RNNCustomTitleView
10
 @implementation RNNCustomTitleView
9
 
11
 
12
+- (instancetype)initWithFrame:(CGRect)frame subView:(RCTRootView*)subView alignment:(NSString*)alignment {
13
+	self = [super init];
14
+	
15
+	if (self) {
16
+		self.subView = subView;
17
+		self.alignment = alignment;
18
+		
19
+		self.backgroundColor = [UIColor clearColor];
20
+		self.subView.backgroundColor = [UIColor clearColor];
21
+		
22
+		if ([alignment isEqualToString:@"fill"]) {
23
+			self.frame = frame;
24
+			subView.sizeFlexibility = RCTRootViewSizeFlexibilityNone;
25
+		} else {
26
+			self.subView.delegate = self;
27
+			subView.sizeFlexibility = RCTRootViewSizeFlexibilityWidthAndHeight;
28
+		}
29
+		
30
+		[self addSubview:subView];
31
+	}
32
+	
33
+	return self;
34
+}
10
 
35
 
11
--(instancetype)initWithFrame:(CGRect)frame subView:(UIView*)subView alignment:(NSString*)alignment {
12
-    self = [super initWithFrame:frame];
13
-    
14
-    if (self) {
15
-        self.backgroundColor = [UIColor clearColor];
16
-        self.subView = subView;
17
-        self.subViewAlign = alignment;
18
-        
19
-        subView.frame = self.bounds;
20
-        [self addSubview:subView];
21
-    }
22
-    
23
-    return self;
36
+- (void)layoutSubviews {
37
+	[super layoutSubviews];
38
+	if ([self.alignment isEqualToString:@"fill"]) {
39
+		[self.subView setFrame:self.bounds];
40
+	}
24
 }
41
 }
25
 
42
 
43
+- (NSString *)alignment {
44
+	return _alignment ? _alignment : @"center";
45
+}
26
 
46
 
27
--(void)layoutSubviews {
28
-    [super layoutSubviews];
29
-    
30
-    if ([self.subViewAlign isEqualToString:@"fill"]) {
31
-        self.subView.frame = self.bounds;
32
-    }
33
-    else {
34
-        
35
-        CGFloat superViewWidth = self.superview.frame.size.width;
36
-        CGFloat paddingLeftFromCenter = (superViewWidth/2) - self.frame.origin.x;
37
-        CGFloat paddingRightFromCenter = self.frame.size.width - paddingLeftFromCenter;;
38
-        CGRect reactViewFrame = self.subView.bounds;
39
-        CGFloat minPadding = MIN(paddingLeftFromCenter, paddingRightFromCenter);
40
-        
41
-        reactViewFrame.size.width = minPadding*2;
42
-        reactViewFrame.origin.x = paddingLeftFromCenter - minPadding;
43
-        self.subView.frame = reactViewFrame;
44
-    }
47
+- (void)rootViewDidChangeIntrinsicSize:(RCTRootView *)rootView {
48
+	if ([self.alignment isEqualToString:@"center"]) {
49
+		[self setFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y, self.subView.intrinsicContentSize.width, self.subView.intrinsicContentSize.height)];
50
+		[self.subView setFrame:CGRectMake(0, 0, rootView.intrinsicContentSize.width, rootView.intrinsicContentSize.height)];
51
+	}
45
 }
52
 }
46
 
53
 
47
 @end
54
 @end
55
+

+ 6
- 1
lib/ios/RNNOptions.m View File

17
 -(void)mergeWith:(NSDictionary *)otherOptions {
17
 -(void)mergeWith:(NSDictionary *)otherOptions {
18
 	for (id key in otherOptions) {
18
 	for (id key in otherOptions) {
19
 		if ([self hasProperty:key]) {
19
 		if ([self hasProperty:key]) {
20
-			[self setValue:[otherOptions objectForKey:key] forKey:key];
20
+			if ([[self valueForKey:key] isKindOfClass:[RNNOptions class]]) {
21
+				RNNOptions* options = [self valueForKey:key];
22
+				[options mergeWith:[otherOptions objectForKey:key]];
23
+			} else {
24
+				[self setValue:[otherOptions objectForKey:key] forKey:key];
25
+			}
21
 		}
26
 		}
22
 	}
27
 	}
23
 }
28
 }

+ 17
- 6
lib/ios/RNNRootViewController.m View File

44
 -(void)viewWillAppear:(BOOL)animated{
44
 -(void)viewWillAppear:(BOOL)animated{
45
 	[super viewWillAppear:animated];
45
 	[super viewWillAppear:animated];
46
 	[self.options applyOn:self];
46
 	[self.options applyOn:self];
47
+	
47
 	[self setCustomNavigationTitleView];
48
 	[self setCustomNavigationTitleView];
48
 	[self setCustomNavigationBarView];
49
 	[self setCustomNavigationBarView];
50
+	[self setCustomNavigationComponentBackground];
49
 }
51
 }
50
 
52
 
51
 -(void)viewDidAppear:(BOOL)animated {
53
 -(void)viewDidAppear:(BOOL)animated {
71
 }
73
 }
72
 
74
 
73
 - (void)setCustomNavigationTitleView {
75
 - (void)setCustomNavigationTitleView {
74
-	if (self.options.topBar.customTitleViewName) {
75
-		UIView *reactView = [_creator createRootView:self.options.topBar.customTitleViewName rootViewId:self.options.topBar.customTitleViewName];
76
+	if (self.options.topBar.title.component) {
77
+		RCTRootView *reactView = (RCTRootView*)[_creator createRootView:self.options.topBar.title.component rootViewId:self.options.topBar.title.component];
76
 		
78
 		
77
-		RNNCustomTitleView *titleView = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:nil];
79
+		RNNCustomTitleView *titleView = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:self.options.topBar.title.componentAlignment];
78
 		self.navigationItem.titleView = titleView;
80
 		self.navigationItem.titleView = titleView;
79
 	}
81
 	}
80
 }
82
 }
81
 
83
 
82
 - (void)setCustomNavigationBarView {
84
 - (void)setCustomNavigationBarView {
83
-	if (self.options.topBar.customViewName) {
84
-		UIView *reactView = [_creator createRootView:self.options.topBar.customViewName rootViewId:@"navBar"];
85
+	if (self.options.topBar.componentName) {
86
+		RCTRootView *reactView = (RCTRootView*)[_creator createRootView:self.options.topBar.componentName rootViewId:@"navBar"];
85
 		
87
 		
86
-		RNNCustomTitleView *titleView = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:nil];
88
+		RNNCustomTitleView *titleView = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
87
 		[self.navigationController.navigationBar addSubview:titleView];
89
 		[self.navigationController.navigationBar addSubview:titleView];
88
 	}
90
 	}
89
 }
91
 }
90
 
92
 
93
+- (void)setCustomNavigationComponentBackground {
94
+	if (self.options.topBar.backgroundComponentName) {
95
+		RCTRootView *reactView = (RCTRootView*)[_creator createRootView:self.options.topBar.backgroundComponentName rootViewId:@"navBarBackground"];
96
+		
97
+		RNNCustomTitleView *titleView = [[RNNCustomTitleView alloc] initWithFrame:self.navigationController.navigationBar.bounds subView:reactView alignment:@"fill"];
98
+		[self.navigationController.navigationBar insertSubview:titleView atIndex:1];
99
+	}
100
+}
101
+
91
 -(BOOL)isCustomTransitioned {
102
 -(BOOL)isCustomTransitioned {
92
 	return self.options.customTransition.animations != nil;
103
 	return self.options.customTransition.animations != nil;
93
 }
104
 }

+ 13
- 0
lib/ios/RNNTitleOptions.h View File

1
+#import "RNNOptions.h"
2
+
3
+@interface RNNTitleOptions : RNNOptions
4
+
5
+@property (nonatomic, strong) NSString* text;
6
+@property (nonatomic, strong) NSNumber* fontSize;
7
+@property (nonatomic, strong) NSNumber* color;
8
+@property (nonatomic, strong) NSString* fontFamily;
9
+@property (nonatomic, strong) NSString* component;
10
+@property (nonatomic, strong) NSString* componentAlignment;
11
+
12
+
13
+@end

+ 32
- 0
lib/ios/RNNTitleOptions.m View File

1
+#import "RNNTitleOptions.h"
2
+
3
+@implementation RNNTitleOptions
4
+
5
+- (void)applyOn:(UIViewController *)viewController {
6
+	if (self.text) {
7
+		viewController.navigationItem.title = self.text;
8
+	}
9
+	
10
+	if (self.fontFamily || self.fontSize || self.color) {
11
+		NSMutableDictionary* navigationBarTitleTextAttributes = [NSMutableDictionary new];
12
+		if (self.color) {
13
+			navigationBarTitleTextAttributes[NSForegroundColorAttributeName] = [RCTConvert UIColor:[self valueForKey:@"color"]];
14
+		}
15
+		if (self.fontFamily){
16
+			if(self.fontSize) {
17
+				navigationBarTitleTextAttributes[NSFontAttributeName] = [UIFont fontWithName:self.fontFamily size:[self.fontSize floatValue]];
18
+			} else {
19
+				navigationBarTitleTextAttributes[NSFontAttributeName] = [UIFont fontWithName:self.fontFamily size:20];
20
+			}
21
+		} else if (self.fontSize) {
22
+			navigationBarTitleTextAttributes[NSFontAttributeName] = [UIFont systemFontOfSize:[self.fontSize floatValue]];
23
+		}
24
+		viewController.navigationController.navigationBar.titleTextAttributes = navigationBarTitleTextAttributes;
25
+		if (@available(iOS 11.0, *)){
26
+			viewController.navigationController.navigationBar.largeTitleTextAttributes = navigationBarTitleTextAttributes;
27
+		}
28
+		
29
+	}
30
+}
31
+
32
+@end

+ 4
- 6
lib/ios/RNNTopBarOptions.h View File

1
 #import "RNNOptions.h"
1
 #import "RNNOptions.h"
2
+#import "RNNTitleOptions.h"
2
 
3
 
3
 @interface RNNTopBarOptions : RNNOptions
4
 @interface RNNTopBarOptions : RNNOptions
4
 
5
 
5
 @property (nonatomic, strong) NSArray* leftButtons;
6
 @property (nonatomic, strong) NSArray* leftButtons;
6
 @property (nonatomic, strong) NSArray* rightButtons;
7
 @property (nonatomic, strong) NSArray* rightButtons;
7
 @property (nonatomic, strong) NSNumber* backgroundColor;
8
 @property (nonatomic, strong) NSNumber* backgroundColor;
8
-@property (nonatomic, strong) NSNumber* textColor;
9
-@property (nonatomic, strong) NSString* title;
10
-@property (nonatomic, strong) NSString* textFontFamily;
11
 @property (nonatomic, strong) NSNumber* visible;
9
 @property (nonatomic, strong) NSNumber* visible;
12
 @property (nonatomic, strong) NSNumber* hideOnScroll;
10
 @property (nonatomic, strong) NSNumber* hideOnScroll;
13
 @property (nonatomic, strong) NSNumber* buttonColor;
11
 @property (nonatomic, strong) NSNumber* buttonColor;
14
 @property (nonatomic, strong) NSNumber* translucent;
12
 @property (nonatomic, strong) NSNumber* translucent;
15
 @property (nonatomic, strong) NSNumber* transparent;
13
 @property (nonatomic, strong) NSNumber* transparent;
16
 @property (nonatomic, strong) NSNumber* drawBehind;
14
 @property (nonatomic, strong) NSNumber* drawBehind;
17
-@property (nonatomic, strong) NSNumber* textFontSize;
18
 @property (nonatomic, strong) NSNumber* noBorder;
15
 @property (nonatomic, strong) NSNumber* noBorder;
19
 @property (nonatomic, strong) NSNumber* blur;
16
 @property (nonatomic, strong) NSNumber* blur;
20
 @property (nonatomic, strong) NSNumber* animate;
17
 @property (nonatomic, strong) NSNumber* animate;
21
 @property (nonatomic, strong) NSNumber* largeTitle;
18
 @property (nonatomic, strong) NSNumber* largeTitle;
22
 @property (nonatomic, strong) NSString* testID;
19
 @property (nonatomic, strong) NSString* testID;
20
+@property (nonatomic, strong) RNNTitleOptions* title;
23
 
21
 
24
-@property (nonatomic, strong) NSString* customTitleViewName;
25
-@property (nonatomic, strong) NSString* customViewName;
22
+@property (nonatomic, strong) NSString* componentName;
23
+@property (nonatomic, strong) NSString* backgroundComponentName;
26
 
24
 
27
 @end
25
 @end

+ 9
- 25
lib/ios/RNNTopBarOptions.m View File

13
 
13
 
14
 @implementation RNNTopBarOptions
14
 @implementation RNNTopBarOptions
15
 
15
 
16
+- (instancetype)initWithDict:(NSDictionary *)dict {
17
+	self = [super initWithDict:dict];
18
+	self.title = [RNNTitleOptions new];
19
+	return self;
20
+}
21
+
16
 - (void)applyOn:(UIViewController*)viewController {
22
 - (void)applyOn:(UIViewController*)viewController {
23
+	[self.title applyOn:viewController];
17
 	if (self.backgroundColor) {
24
 	if (self.backgroundColor) {
18
 		UIColor* backgroundColor = [RCTConvert UIColor:self.backgroundColor];
25
 		UIColor* backgroundColor = [RCTConvert UIColor:self.backgroundColor];
19
 		viewController.navigationController.navigationBar.barTintColor = backgroundColor;
26
 		viewController.navigationController.navigationBar.barTintColor = backgroundColor;
20
 	} else {
27
 	} else {
21
 		viewController.navigationController.navigationBar.barTintColor = nil;
28
 		viewController.navigationController.navigationBar.barTintColor = nil;
22
 	}
29
 	}
23
-	
24
-	if (self.title) {
25
-		viewController.navigationItem.title = self.title;
26
-	}
27
-	
30
+
28
 	if (@available(iOS 11.0, *)) {
31
 	if (@available(iOS 11.0, *)) {
29
 		if (self.largeTitle){
32
 		if (self.largeTitle){
30
 			if ([self.largeTitle boolValue]) {
33
 			if ([self.largeTitle boolValue]) {
40
 	}
43
 	}
41
 	
44
 	
42
 	
45
 	
43
-	if (self.textFontFamily || self.textFontSize || self.textColor) {
44
-		NSMutableDictionary* navigationBarTitleTextAttributes = [NSMutableDictionary new];
45
-		if (self.textColor) {
46
-			navigationBarTitleTextAttributes[NSForegroundColorAttributeName] = [RCTConvert UIColor:[self valueForKey:@"textColor"]];
47
-		}
48
-		if (self.textFontFamily){
49
-			if(self.textFontSize) {
50
-				navigationBarTitleTextAttributes[NSFontAttributeName] = [UIFont fontWithName:self.textFontFamily size:[self.textFontSize floatValue]];
51
-			} else {
52
-				navigationBarTitleTextAttributes[NSFontAttributeName] = [UIFont fontWithName:self.textFontFamily size:20];
53
-			}
54
-		} else if (self.textFontSize) {
55
-			navigationBarTitleTextAttributes[NSFontAttributeName] = [UIFont systemFontOfSize:[self.textFontSize floatValue]];
56
-		}
57
-		viewController.navigationController.navigationBar.titleTextAttributes = navigationBarTitleTextAttributes;
58
-		if (@available(iOS 11.0, *)){
59
-			viewController.navigationController.navigationBar.largeTitleTextAttributes = navigationBarTitleTextAttributes;
60
-		}
61
-		
62
-	}
46
+	
63
 	
47
 	
64
 	
48
 	
65
 	if (self.visible) {
49
 	if (self.visible) {

+ 8
- 0
lib/ios/ReactNativeNavigation.xcodeproj/project.pbxproj View File

81
 		504AFE751FFFF0540076E904 /* RNNTopTabsOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 504AFE731FFFF0540076E904 /* RNNTopTabsOptions.m */; };
81
 		504AFE751FFFF0540076E904 /* RNNTopTabsOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 504AFE731FFFF0540076E904 /* RNNTopTabsOptions.m */; };
82
 		504AFE761FFFF1E00076E904 /* RNNNavigationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = E83BAD691F27362500A9F3DD /* RNNNavigationOptions.h */; };
82
 		504AFE761FFFF1E00076E904 /* RNNNavigationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = E83BAD691F27362500A9F3DD /* RNNNavigationOptions.h */; };
83
 		504AFE771FFFF1E20076E904 /* RNNTopBarOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = A7626BFE1FC2FB6700492FB8 /* RNNTopBarOptions.h */; };
83
 		504AFE771FFFF1E20076E904 /* RNNTopBarOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = A7626BFE1FC2FB6700492FB8 /* RNNTopBarOptions.h */; };
84
+		50570B262061473D006A1B5C /* RNNTitleOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 50570B242061473D006A1B5C /* RNNTitleOptions.h */; };
85
+		50570B272061473D006A1B5C /* RNNTitleOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 50570B252061473D006A1B5C /* RNNTitleOptions.m */; };
84
 		50762D08205E96C200E3D18A /* RNNModalAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 50762D06205E96C200E3D18A /* RNNModalAnimation.h */; };
86
 		50762D08205E96C200E3D18A /* RNNModalAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 50762D06205E96C200E3D18A /* RNNModalAnimation.h */; };
85
 		50762D09205E96C200E3D18A /* RNNModalAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 50762D07205E96C200E3D18A /* RNNModalAnimation.m */; };
87
 		50762D09205E96C200E3D18A /* RNNModalAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 50762D07205E96C200E3D18A /* RNNModalAnimation.m */; };
86
 		507E7D57201DDD3000444E6C /* RNNAnimationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 507E7D55201DDD3000444E6C /* RNNAnimationOptions.h */; };
88
 		507E7D57201DDD3000444E6C /* RNNAnimationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 507E7D55201DDD3000444E6C /* RNNAnimationOptions.h */; };
268
 		504AFE631FFE53070076E904 /* RNNOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNOptions.m; sourceTree = "<group>"; };
270
 		504AFE631FFE53070076E904 /* RNNOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNOptions.m; sourceTree = "<group>"; };
269
 		504AFE721FFFF0540076E904 /* RNNTopTabsOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTopTabsOptions.h; sourceTree = "<group>"; };
271
 		504AFE721FFFF0540076E904 /* RNNTopTabsOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTopTabsOptions.h; sourceTree = "<group>"; };
270
 		504AFE731FFFF0540076E904 /* RNNTopTabsOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTopTabsOptions.m; sourceTree = "<group>"; };
272
 		504AFE731FFFF0540076E904 /* RNNTopTabsOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTopTabsOptions.m; sourceTree = "<group>"; };
273
+		50570B242061473D006A1B5C /* RNNTitleOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTitleOptions.h; sourceTree = "<group>"; };
274
+		50570B252061473D006A1B5C /* RNNTitleOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNTitleOptions.m; sourceTree = "<group>"; };
271
 		50762D06205E96C200E3D18A /* RNNModalAnimation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNModalAnimation.h; sourceTree = "<group>"; };
275
 		50762D06205E96C200E3D18A /* RNNModalAnimation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNModalAnimation.h; sourceTree = "<group>"; };
272
 		50762D07205E96C200E3D18A /* RNNModalAnimation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNModalAnimation.m; sourceTree = "<group>"; };
276
 		50762D07205E96C200E3D18A /* RNNModalAnimation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNModalAnimation.m; sourceTree = "<group>"; };
273
 		507E7D55201DDD3000444E6C /* RNNAnimationOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNAnimationOptions.h; sourceTree = "<group>"; };
277
 		507E7D55201DDD3000444E6C /* RNNAnimationOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNAnimationOptions.h; sourceTree = "<group>"; };
485
 				E83BAD6A1F27363A00A9F3DD /* RNNNavigationOptions.m */,
489
 				E83BAD6A1F27363A00A9F3DD /* RNNNavigationOptions.m */,
486
 				A7626BFE1FC2FB6700492FB8 /* RNNTopBarOptions.h */,
490
 				A7626BFE1FC2FB6700492FB8 /* RNNTopBarOptions.h */,
487
 				A7626BFC1FC2FB2C00492FB8 /* RNNTopBarOptions.m */,
491
 				A7626BFC1FC2FB2C00492FB8 /* RNNTopBarOptions.m */,
492
+				50570B242061473D006A1B5C /* RNNTitleOptions.h */,
493
+				50570B252061473D006A1B5C /* RNNTitleOptions.m */,
488
 				A7626BFF1FC578AB00492FB8 /* RNNBottomTabsOptions.h */,
494
 				A7626BFF1FC578AB00492FB8 /* RNNBottomTabsOptions.h */,
489
 				A7626C001FC5796200492FB8 /* RNNBottomTabsOptions.m */,
495
 				A7626C001FC5796200492FB8 /* RNNBottomTabsOptions.m */,
490
 				50EB933F1FE14A3E00BD8EEE /* RNNBottomTabOptions.h */,
496
 				50EB933F1FE14A3E00BD8EEE /* RNNBottomTabOptions.h */,
768
 				263905B31E4C6F440023D7D3 /* MMDrawerVisualState.h in Headers */,
774
 				263905B31E4C6F440023D7D3 /* MMDrawerVisualState.h in Headers */,
769
 				50451D092042E20600695F00 /* RNNTransitionsOptions.h in Headers */,
775
 				50451D092042E20600695F00 /* RNNTransitionsOptions.h in Headers */,
770
 				E8A5CD621F49114F00E89D0D /* RNNElement.h in Headers */,
776
 				E8A5CD621F49114F00E89D0D /* RNNElement.h in Headers */,
777
+				50570B262061473D006A1B5C /* RNNTitleOptions.h in Headers */,
771
 				504AFE741FFFF0540076E904 /* RNNTopTabsOptions.h in Headers */,
778
 				504AFE741FFFF0540076E904 /* RNNTopTabsOptions.h in Headers */,
772
 				E8E5182E1F83A48B000467AC /* RNNTransitionStateHolder.h in Headers */,
779
 				E8E5182E1F83A48B000467AC /* RNNTransitionStateHolder.h in Headers */,
773
 				507E7D57201DDD3000444E6C /* RNNAnimationOptions.h in Headers */,
780
 				507E7D57201DDD3000444E6C /* RNNAnimationOptions.h in Headers */,
902
 				261F0E6B1E6F028A00989DE2 /* RNNNavigationStackManager.m in Sources */,
909
 				261F0E6B1E6F028A00989DE2 /* RNNNavigationStackManager.m in Sources */,
903
 				5016E8F020209690009D4F7C /* RNNCustomTitleView.m in Sources */,
910
 				5016E8F020209690009D4F7C /* RNNCustomTitleView.m in Sources */,
904
 				E8DA24411F97459B00CD552B /* RNNElementFinder.m in Sources */,
911
 				E8DA24411F97459B00CD552B /* RNNElementFinder.m in Sources */,
912
+				50570B272061473D006A1B5C /* RNNTitleOptions.m in Sources */,
905
 				263905BF1E4C6F440023D7D3 /* RCCTheSideBarManagerViewController.m in Sources */,
913
 				263905BF1E4C6F440023D7D3 /* RCCTheSideBarManagerViewController.m in Sources */,
906
 				7B1126A01E2D263F00F9B03B /* RNNEventEmitter.m in Sources */,
914
 				7B1126A01E2D263F00F9B03B /* RNNEventEmitter.m in Sources */,
907
 				A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */,
915
 				A7626BFD1FC2FB2C00492FB8 /* RNNTopBarOptions.m in Sources */,

+ 1
- 1
lib/ios/ReactNativeNavigationTests/RNNCommandsHandlerTest.m View File

63
 
63
 
64
 -(void)testDynamicStylesMergeWithStaticStyles {
64
 -(void)testDynamicStylesMergeWithStaticStyles {
65
 	RNNNavigationOptions* initialOptions = [[RNNNavigationOptions alloc] init];
65
 	RNNNavigationOptions* initialOptions = [[RNNNavigationOptions alloc] init];
66
-	[initialOptions.topBar setTitle:@"the title"];
66
+	initialOptions.topBar.title.text = @"the title";
67
 	RNNRootViewController* vc = [[RNNRootViewController alloc] initWithName:@"name"
67
 	RNNRootViewController* vc = [[RNNRootViewController alloc] initWithName:@"name"
68
 																withOptions:initialOptions
68
 																withOptions:initialOptions
69
 															withComponentId:@"componentId"
69
 															withComponentId:@"componentId"

+ 2
- 2
lib/ios/ReactNativeNavigationTests/RNNNavigationOptionsTest.m View File

22
 
22
 
23
 - (void)testChangeRNNNavigationOptionsDynamically {
23
 - (void)testChangeRNNNavigationOptionsDynamically {
24
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{@"topBar": @{@"backgroundColor" : @(0xff0000ff)}}];
24
 	RNNNavigationOptions* options = [[RNNNavigationOptions alloc] initWithDict:@{@"topBar": @{@"backgroundColor" : @(0xff0000ff)}}];
25
-	NSDictionary* dynamicOptions = @{@"topBar": @{@"textColor" : @(0xffff00ff), @"title" : @"hello"}};
25
+	NSDictionary* dynamicOptions = @{@"topBar": @{@"textColor" : @(0xffff00ff), @"title" : @{@"text": @"hello"}}};
26
 	[options mergeWith:dynamicOptions];
26
 	[options mergeWith:dynamicOptions];
27
-	XCTAssertTrue([options.topBar.title isEqual:@"hello"]);
27
+	XCTAssertTrue([options.topBar.title.text isEqual:@"hello"]);
28
 }
28
 }
29
 
29
 
30
 - (void)testChangeRNNNavigationOptionsWithInvalidProperties {
30
 - (void)testChangeRNNNavigationOptionsWithInvalidProperties {

+ 12
- 12
lib/ios/ReactNativeNavigationTests/RNNRootViewControllerTest.m View File

106
 
106
 
107
 -(void)testTitle_string{
107
 -(void)testTitle_string{
108
 	NSString* title =@"some title";
108
 	NSString* title =@"some title";
109
-	self.options.topBar.title = title;
109
+	self.options.topBar.title.text = title;
110
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
110
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
111
 	
111
 	
112
 	[self.uut viewWillAppear:false];
112
 	[self.uut viewWillAppear:false];
122
 
122
 
123
 -(void)testTopBarTextColor_validColor{
123
 -(void)testTopBarTextColor_validColor{
124
 	NSNumber* inputColor = @(0xFFFF0000);
124
 	NSNumber* inputColor = @(0xFFFF0000);
125
-	self.options.topBar.textColor = inputColor;
125
+	self.options.topBar.title.color = inputColor;
126
 	__unused UINavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
126
 	__unused UINavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
127
 	[self.uut viewWillAppear:false];
127
 	[self.uut viewWillAppear:false];
128
 	UIColor* expectedColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
128
 	UIColor* expectedColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
156
 -(void)testTopBarTextFontFamily_validFont{
156
 -(void)testTopBarTextFontFamily_validFont{
157
 	NSString* inputFont = @"HelveticaNeue";
157
 	NSString* inputFont = @"HelveticaNeue";
158
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
158
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
159
-	self.options.topBar.textFontFamily = inputFont;
159
+	self.options.topBar.title.fontFamily = inputFont;
160
 	[self.uut viewWillAppear:false];
160
 	[self.uut viewWillAppear:false];
161
 	UIFont* expectedFont = [UIFont fontWithName:inputFont size:20];
161
 	UIFont* expectedFont = [UIFont fontWithName:inputFont size:20];
162
 	XCTAssertTrue([self.uut.navigationController.navigationBar.titleTextAttributes[@"NSFont"] isEqual:expectedFont]);
162
 	XCTAssertTrue([self.uut.navigationController.navigationBar.titleTextAttributes[@"NSFont"] isEqual:expectedFont]);
227
 
227
 
228
 -(void)testTopBarTextFontSize_withoutTextFontFamily_withoutTextColor {
228
 -(void)testTopBarTextFontSize_withoutTextFontFamily_withoutTextColor {
229
 	NSNumber* topBarTextFontSizeInput = @(15);
229
 	NSNumber* topBarTextFontSizeInput = @(15);
230
-	self.options.topBar.textFontSize = topBarTextFontSizeInput;
230
+	self.options.topBar.title.fontSize = topBarTextFontSizeInput;
231
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
231
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
232
 	[self.uut viewWillAppear:false];
232
 	[self.uut viewWillAppear:false];
233
 	UIFont* expectedFont = [UIFont systemFontOfSize:15];
233
 	UIFont* expectedFont = [UIFont systemFontOfSize:15];
237
 -(void)testTopBarTextFontSize_withoutTextFontFamily_withTextColor {
237
 -(void)testTopBarTextFontSize_withoutTextFontFamily_withTextColor {
238
 	NSNumber* topBarTextFontSizeInput = @(15);
238
 	NSNumber* topBarTextFontSizeInput = @(15);
239
 	NSNumber* inputColor = @(0xFFFF0000);
239
 	NSNumber* inputColor = @(0xFFFF0000);
240
-	self.options.topBar.textFontSize = topBarTextFontSizeInput;
241
-	self.options.topBar.textColor = inputColor;
240
+	self.options.topBar.title.fontSize = topBarTextFontSizeInput;
241
+	self.options.topBar.title.color = inputColor;
242
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
242
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
243
 	[self.uut viewWillAppear:false];
243
 	[self.uut viewWillAppear:false];
244
 	UIFont* expectedFont = [UIFont systemFontOfSize:15];
244
 	UIFont* expectedFont = [UIFont systemFontOfSize:15];
251
 	NSNumber* topBarTextFontSizeInput = @(15);
251
 	NSNumber* topBarTextFontSizeInput = @(15);
252
 	NSNumber* inputColor = @(0xFFFF0000);
252
 	NSNumber* inputColor = @(0xFFFF0000);
253
 	NSString* inputFont = @"HelveticaNeue";
253
 	NSString* inputFont = @"HelveticaNeue";
254
-	self.options.topBar.textFontSize = topBarTextFontSizeInput;
255
-	self.options.topBar.textColor = inputColor;
256
-	self.options.topBar.textFontFamily = inputFont;
254
+	self.options.topBar.title.fontSize = topBarTextFontSizeInput;
255
+	self.options.topBar.title.color = inputColor;
256
+	self.options.topBar.title.fontFamily = inputFont;
257
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
257
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
258
 	[self.uut viewWillAppear:false];
258
 	[self.uut viewWillAppear:false];
259
 	UIColor* expectedColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
259
 	UIColor* expectedColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
265
 -(void)testTopBarTextFontSize_withTextFontFamily_withoutTextColor {
265
 -(void)testTopBarTextFontSize_withTextFontFamily_withoutTextColor {
266
 	NSNumber* topBarTextFontSizeInput = @(15);
266
 	NSNumber* topBarTextFontSizeInput = @(15);
267
 	NSString* inputFont = @"HelveticaNeue";
267
 	NSString* inputFont = @"HelveticaNeue";
268
-	self.options.topBar.textFontSize = topBarTextFontSizeInput;
269
-	self.options.topBar.textFontFamily = inputFont;
268
+	self.options.topBar.title.fontSize = topBarTextFontSizeInput;
269
+	self.options.topBar.title.fontFamily = inputFont;
270
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
270
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
271
 	[self.uut viewWillAppear:false];
271
 	[self.uut viewWillAppear:false];
272
 	UIFont* expectedFont = [UIFont fontWithName:inputFont size:15];
272
 	UIFont* expectedFont = [UIFont fontWithName:inputFont size:15];
277
 -(void)testTopBarTextFontFamily_invalidFont{
277
 -(void)testTopBarTextFontFamily_invalidFont{
278
 	NSString* inputFont = @"HelveticaNeueeeee";
278
 	NSString* inputFont = @"HelveticaNeueeeee";
279
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
279
 	__unused RNNNavigationController* nav = [[RNNNavigationController alloc] initWithRootViewController:self.uut];
280
-	self.options.topBar.textFontFamily = inputFont;
280
+	self.options.topBar.title.fontFamily = inputFont;
281
 	//	XCTAssertThrows([self.uut viewWillAppear:false]);
281
 	//	XCTAssertThrows([self.uut viewWillAppear:false]);
282
 }
282
 }
283
 
283
 

+ 4
- 2
lib/src/commands/LayoutTreeParser.test.ts View File

124
       expect(result.children[1].children[0].children[2].children[0].type).toEqual('TopTabs');
124
       expect(result.children[1].children[0].children[2].children[0].type).toEqual('TopTabs');
125
       expect(result.children[1].children[0].children[2].children[0].children[2].type).toEqual('TopTabs');
125
       expect(result.children[1].children[0].children[2].children[0].children[2].type).toEqual('TopTabs');
126
       expect(result.children[1].children[0].children[2].children[0].children[2].children[4].type).toEqual('Stack');
126
       expect(result.children[1].children[0].children[2].children[0].children[2].children[4].type).toEqual('Stack');
127
-      expect(result.children[1].children[0].children[2].children[0].children[2].data).toEqual({ options: { topBar: { title: 'Hello1' } } });
127
+      expect(result.children[1].children[0].children[2].children[0].children[2].data).toEqual({ options: { topBar: { title: { text: 'Hello1'} } } });
128
     });
128
     });
129
   });
129
   });
130
 
130
 
163
 
163
 
164
 const options = {
164
 const options = {
165
   topBar: {
165
   topBar: {
166
-    title: 'Hello1'
166
+    title: {
167
+      text: 'Hello1'
168
+    }
167
   }
169
   }
168
 };
170
 };
169
 
171
 

+ 3
- 1
playground/src/screens/BackHandlerModalScreen.js View File

7
   static get options() {
7
   static get options() {
8
     return {
8
     return {
9
       topBar: {
9
       topBar: {
10
-        title: 'Back Handler'
10
+        title: {
11
+          text: 'Back Handler'
12
+        }
11
       }
13
       }
12
     };
14
     };
13
   }
15
   }

+ 5
- 3
playground/src/screens/BackHandlerScreen.js View File

7
   static get options() {
7
   static get options() {
8
     return {
8
     return {
9
       topBar: {
9
       topBar: {
10
-        title: 'Back Handler',
11
-        textColor: 'black',
12
-        textFontSize: 16
10
+        title: {
11
+          text: 'Back Handler',
12
+          color: 'black',
13
+          fontSize: 16
14
+        }
13
       }
15
       }
14
     };
16
     };
15
   }
17
   }

+ 1
- 1
playground/src/screens/CustomTopBar.js View File

42
   },
42
   },
43
   text: {
43
   text: {
44
     alignSelf: 'center',
44
     alignSelf: 'center',
45
-    color: Platform.OS === 'ios' ? 'black' : 'white'
45
+    color: 'black'
46
   }
46
   }
47
 });
47
 });

+ 4
- 2
playground/src/screens/CustomTransitionDestination.js View File

14
     return {
14
     return {
15
       backButtonTransition: 'custom',
15
       backButtonTransition: 'custom',
16
       topBar: {
16
       topBar: {
17
-        title: 'ye babyyyyyy',
18
-        textFontFamily: 'HelveticaNeue-Italic',
17
+        title: {
18
+          text: 'ye babyyyyyy',
19
+          fontFamily: 'HelveticaNeue-Italic'
20
+        },
19
         largeTitle: true
21
         largeTitle: true
20
       }
22
       }
21
     };
23
     };

+ 4
- 2
playground/src/screens/CustomTransitionOrigin.js View File

11
   static get options() {
11
   static get options() {
12
     return {
12
     return {
13
       topBar: {
13
       topBar: {
14
-        textFontFamily: 'HelveticaNeue-Italic',
15
-        textFontSize: 16,
14
+        title: {
15
+          fontFamily: 'HelveticaNeue-Italic',
16
+          fontSize: 16
17
+        },
16
         largeTitle: false,
18
         largeTitle: false,
17
         translucent: true
19
         translucent: true
18
       }
20
       }

+ 27
- 13
playground/src/screens/OptionsScreen.js View File

17
   static get options() {
17
   static get options() {
18
     return {
18
     return {
19
       topBar: {
19
       topBar: {
20
-        title: 'Static Title',
21
-        textColor: 'black',
20
+        title: {
21
+          text: 'Static Title',
22
+          color: 'black',
23
+          fontSize: 16,
24
+          fontFamily: 'HelveticaNeue-Italic',
25
+          largeTitle: false,
26
+        },
22
         ...Platform.select({
27
         ...Platform.select({
23
           android: { drawBehind: true },
28
           android: { drawBehind: true },
24
           ios: { drawBehind: false, }
29
           ios: { drawBehind: false, }
25
         }),
30
         }),
26
-        largeTitle: false,
27
         visible: true,
31
         visible: true,
28
-        textFontSize: 16,
29
-        textFontFamily: 'HelveticaNeue-Italic',
30
         testID: testIDs.TOP_BAR_ELEMENT,
32
         testID: testIDs.TOP_BAR_ELEMENT,
31
         rightButtons: [
33
         rightButtons: [
32
           {
34
           {
105
         <Button title='Top Bar Opaque' onPress={this.onClickTopBarOpaque} />
107
         <Button title='Top Bar Opaque' onPress={this.onClickTopBarOpaque} />
106
         <Button title='scrollView Screen' testID={testIDs.SCROLLVIEW_SCREEN_BUTTON} onPress={this.onClickScrollViewScreen} />
108
         <Button title='scrollView Screen' testID={testIDs.SCROLLVIEW_SCREEN_BUTTON} onPress={this.onClickScrollViewScreen} />
107
         <Button title='Custom Transition' testID={testIDs.CUSTOM_TRANSITION_BUTTON} onPress={this.onClickCustomTranstition} />
109
         <Button title='Custom Transition' testID={testIDs.CUSTOM_TRANSITION_BUTTON} onPress={this.onClickCustomTranstition} />
108
-        {Platform.OS === 'android' ?
109
-          <Button title='Hide fab' testID={testIDs.HIDE_FAB} onPress={this.onClickFab} />
110
-          : null}
110
+        {Platform.OS === 'android' ? <Button title='Hide fab' testID={testIDs.HIDE_FAB} onPress={this.onClickFab} /> : null}
111
         <Button title='Show overlay' testID={testIDs.SHOW_OVERLAY_BUTTON} onPress={() => this.onClickShowOverlay(true)} />
111
         <Button title='Show overlay' testID={testIDs.SHOW_OVERLAY_BUTTON} onPress={() => this.onClickShowOverlay(true)} />
112
         <Button title='Show touch through overlay' testID={testIDs.SHOW_TOUCH_THROUGH_OVERLAY_BUTTON} onPress={() => this.onClickShowOverlay(false)} />
112
         <Button title='Show touch through overlay' testID={testIDs.SHOW_TOUCH_THROUGH_OVERLAY_BUTTON} onPress={() => this.onClickShowOverlay(false)} />
113
         <Button title='Push Default Options Screen' testID={testIDs.PUSH_DEFAULT_OPTIONS_BUTTON} onPress={this.onClickPushDefaultOptionsScreen} />
113
         <Button title='Push Default Options Screen' testID={testIDs.PUSH_DEFAULT_OPTIONS_BUTTON} onPress={this.onClickPushDefaultOptionsScreen} />
114
+        <Button title='Show TopBar react view' testID={testIDs.SHOW_TOPBAR_REACT_VIEW} onPress={this.onShowTopBarReactView} />
114
         <Text style={styles.footer}>{`this.props.containerId = ${this.props.containerId}`}</Text>
115
         <Text style={styles.footer}>{`this.props.containerId = ${this.props.containerId}`}</Text>
115
       </View>
116
       </View>
116
     );
117
     );
161
   onClickDynamicOptions() {
162
   onClickDynamicOptions() {
162
     Navigation.setOptions(this.props.componentId, {
163
     Navigation.setOptions(this.props.componentId, {
163
       topBar: {
164
       topBar: {
164
-        title: 'Dynamic Title',
165
-        textColor: '#00FFFF',
166
-        largeTitle: false,
165
+        title: {
166
+          text: 'Dynamic Title',
167
+          color: '#00FFFF',
168
+          largeTitle: false,
169
+          fontSize: 20,
170
+          fontFamily: 'HelveticaNeue-CondensedBold'
171
+        },
167
         buttonColor: 'red',
172
         buttonColor: 'red',
168
-        textFontSize: 20,
169
-        textFontFamily: 'HelveticaNeue-CondensedBold'
170
       }
173
       }
171
     });
174
     });
172
   }
175
   }
256
       }
259
       }
257
     });
260
     });
258
   }
261
   }
262
+
263
+  onShowTopBarReactView = () => {
264
+    Navigation.setOptions(this.props.componentId, {
265
+      topBar: {
266
+        title: {
267
+          component: 'navigation.playground.CustomTopBar',
268
+          alignment: 'fill'
269
+        }
270
+      }
271
+    });
272
+  }
259
 }
273
 }
260
 
274
 
261
 const styles = {
275
 const styles = {

+ 3
- 1
playground/src/screens/PushedScreen.js View File

52
         },
52
         },
53
         options: {
53
         options: {
54
           topBar: {
54
           topBar: {
55
-            title: `Pushed ${this.getStackPosition() + 1}`
55
+            title: {
56
+              text: `Pushed ${this.getStackPosition() + 1}`
57
+            }
56
           }
58
           }
57
         }
59
         }
58
       }
60
       }

+ 5
- 3
playground/src/screens/ScrollViewScreen.js View File

12
   static get options() {
12
   static get options() {
13
     return {
13
     return {
14
       topBar: {
14
       topBar: {
15
-        title: 'Collapse',
15
+        title: {
16
+          text: 'Collapse',
17
+          color: 'black',
18
+          fontSize: 16
19
+        },
16
         drawBehind: true,
20
         drawBehind: true,
17
-        textColor: 'black',
18
-        textFontSize: 16,
19
         visible: true,
21
         visible: true,
20
         testID: testIDs.TOP_BAR_ELEMENT
22
         testID: testIDs.TOP_BAR_ELEMENT
21
       },
23
       },

+ 11
- 7
playground/src/screens/TopTabOptionsScreen.js View File

8
   static get options() {
8
   static get options() {
9
     return {
9
     return {
10
       topBar: {
10
       topBar: {
11
-        textColor: 'black',
12
-        textFontSize: 16,
13
-        textFontFamily: 'HelveticaNeue-Italic'
11
+        title: {
12
+          color: 'black',
13
+          fontSize: 16,
14
+          fontFamily: 'HelveticaNeue-Italic'
15
+        }
14
       }
16
       }
15
     };
17
     };
16
   }
18
   }
33
   onClickDynamicOptions() {
35
   onClickDynamicOptions() {
34
     Navigation.setOptions(this.props.componentId, {
36
     Navigation.setOptions(this.props.componentId, {
35
       topBar: {
37
       topBar: {
36
-        title: 'Dynamic Title',
37
-        textColor: '#00FFFF',
38
+        title: {
39
+          text: 'Dynamic Title',
40
+          color: '#00FFFF',
41
+          fontSize: 16,
42
+          fontFamily: 'HelveticaNeue-CondensedBold'
43
+        },
38
         largeTitle: false,
44
         largeTitle: false,
39
         buttonColor: 'red',
45
         buttonColor: 'red',
40
-        textFontSize: 20,
41
-        textFontFamily: 'HelveticaNeue-CondensedBold'
42
       }
46
       }
43
     });
47
     });
44
   }
48
   }

+ 5
- 3
playground/src/screens/TopTabScreen.js View File

8
   static get options() {
8
   static get options() {
9
     return {
9
     return {
10
       topBar: {
10
       topBar: {
11
-        textColor: 'black',
12
-        textFontSize: 16,
13
-        textFontFamily: 'HelveticaNeue-Italic'
11
+        title: {
12
+          color: 'black',
13
+          fontSize: 16,
14
+          fontFamily: 'HelveticaNeue-Italic'
15
+        }
14
       },
16
       },
15
       fab: {
17
       fab: {
16
         id: FAB,
18
         id: FAB,

+ 28
- 9
playground/src/screens/WelcomeScreen.js View File

10
   static get options() {
10
   static get options() {
11
     return {
11
     return {
12
       topBar: {
12
       topBar: {
13
-        largeTitle: false,
13
+        title: {
14
+          largeTitle: false,
15
+          title: 'My Screen'
16
+        },
14
         drawBehind: true,
17
         drawBehind: true,
15
         visible: false,
18
         visible: false,
16
         animate: false
19
         animate: false
57
                     options: {
60
                     options: {
58
                       topBar: {
61
                       topBar: {
59
                         visible: true,
62
                         visible: true,
60
-                        title: 'React Native Navigation!'
63
+                        title: {
64
+                          text: 'React Native Navigation!'
65
+                        }
61
                       }
66
                       }
62
                     }
67
                     }
63
                   }
68
                   }
216
         name: 'navigation.playground.PushedScreen',
221
         name: 'navigation.playground.PushedScreen',
217
         options: {
222
         options: {
218
           topBar: {
223
           topBar: {
219
-            title: 'pushed'
224
+            title: {
225
+              text: 'pushed'
226
+            }
220
           }
227
           }
221
         }
228
         }
222
       }
229
       }
232
         },
239
         },
233
         options: {
240
         options: {
234
           topBar: {
241
           topBar: {
235
-            title: 'pushed',
242
+            title: {
243
+              text: 'pushed'
244
+            },
236
             visible: true,
245
             visible: true,
237
             testID: testIDs.TOP_BAR_ELEMENT
246
             testID: testIDs.TOP_BAR_ELEMENT
238
           }
247
           }
299
               },
308
               },
300
               options: {
309
               options: {
301
                 topTab: {
310
                 topTab: {
302
-                  title: 'Tab 1'
311
+                  title: {
312
+                    text: 'Tab 1'
313
+                  }
303
                 },
314
                 },
304
                 topBar: {
315
                 topBar: {
305
-                  title: 'One'
316
+                  title: {
317
+                    text: 'One'
318
+                  }
306
                 }
319
                 }
307
               }
320
               }
308
             }
321
             }
320
                   titleFontFamily: 'HelveticaNeue-Italic'
333
                   titleFontFamily: 'HelveticaNeue-Italic'
321
                 },
334
                 },
322
                 topBar: {
335
                 topBar: {
323
-                  title: 'Two'
336
+                  title: {
337
+                    text: 'Two'
338
+                  }
324
                 }
339
                 }
325
               }
340
               }
326
             }
341
             }
337
                   title: 'Tab 3'
352
                   title: 'Tab 3'
338
                 },
353
                 },
339
                 topBar: {
354
                 topBar: {
340
-                  title: 'Three'
355
+                  title: {
356
+                    text: 'Three'
357
+                  }
341
                 }
358
                 }
342
               }
359
               }
343
             }
360
             }
385
     });
402
     });
386
     Navigation.setOptions('my unique id', {
403
     Navigation.setOptions('my unique id', {
387
       topBar: {
404
       topBar: {
388
-        title: 'User provided id'
405
+        title: {
406
+          text: 'User provided id'
407
+        }
389
       }
408
       }
390
     });
409
     });
391
   }
410
   }

+ 1
- 0
playground/src/testIDs.js View File

9
   PUSH_BUTTON: `PUSH_BUTTON`,
9
   PUSH_BUTTON: `PUSH_BUTTON`,
10
   PUSH_OPTIONS_BUTTON: `PUSH_OPTIONS_BUTTON`,
10
   PUSH_OPTIONS_BUTTON: `PUSH_OPTIONS_BUTTON`,
11
   PUSH_DEFAULT_OPTIONS_BUTTON: `PUSH_DEFAULT_OPTIONS_BUTTON`,
11
   PUSH_DEFAULT_OPTIONS_BUTTON: `PUSH_DEFAULT_OPTIONS_BUTTON`,
12
+  SHOW_TOPBAR_REACT_VIEW: `SHOW_TOPBAR_REACT_VIEW`,
12
   BACK_HANDLER_BUTTON: `BACK_HANDLER_BUTTON`,
13
   BACK_HANDLER_BUTTON: `BACK_HANDLER_BUTTON`,
13
   SHOW_MODAL_BUTTON: `SHOW_MODAL_BUTTON`,
14
   SHOW_MODAL_BUTTON: `SHOW_MODAL_BUTTON`,
14
   SHOW_REDBOX_BUTTON: `SHOW_REDBOX_BUTTON`,
15
   SHOW_REDBOX_BUTTON: `SHOW_REDBOX_BUTTON`,