Browse Source

Add waitForRender options for setRoot animation and TopBar components

When set, the ui will become visible only after the root screen and TopBar components have been rendered.

Usage
Add the following to the root layout’s options, or to its child
```
animations: {
  setRoot: {
    waitForRender: true
  }
}
```

TopBar components (Title, background, buttons) can be synced as well by adding `waitForRender: true`, for example:
```
component: {
  name: 'navigation.playground.CustomTopBar',
  alignment: 'center',
  waitForRender: true,
}
```
Guy Carmeli 6 years ago
parent
commit
c746621c40
34 changed files with 419 additions and 243 deletions
  1. 7
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/Component.java
  2. 10
    5
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java
  3. 7
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/TopBarBackgroundOptions.java
  4. 0
    1
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/Presenter.java
  5. 13
    0
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/RenderChecker.java
  6. 95
    41
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/StackPresenter.java
  7. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/react/ReactView.java
  8. 29
    2
      lib/android/app/src/main/java/com/reactnativenavigation/utils/CollectionUtils.java
  9. 4
    0
      lib/android/app/src/main/java/com/reactnativenavigation/utils/Functions.java
  10. 11
    4
      lib/android/app/src/main/java/com/reactnativenavigation/utils/ObjectUtils.java
  11. 7
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/TitleBarButtonController.java
  12. 2
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/TitleBarReactViewController.java
  13. 3
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java
  14. 10
    5
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/navigator/Navigator.java
  15. 15
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/navigator/RootPresenter.java
  16. 12
    14
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java
  17. 1
    16
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerBuilder.java
  18. 2
    7
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/topbar/TopBarBackgroundViewController.java
  19. 4
    4
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/topbar/TopBarController.java
  20. 1
    3
      lib/android/app/src/main/java/com/reactnativenavigation/views/Component.java
  21. 5
    0
      lib/android/app/src/main/java/com/reactnativenavigation/views/Renderable.java
  22. 4
    5
      lib/android/app/src/main/java/com/reactnativenavigation/views/StackLayout.java
  23. 9
    13
      lib/android/app/src/main/java/com/reactnativenavigation/views/topbar/TopBar.java
  24. 4
    6
      lib/android/app/src/test/java/com/reactnativenavigation/TestUtils.java
  25. 58
    0
      lib/android/app/src/test/java/com/reactnativenavigation/presentation/RenderCheckerTest.java
  26. 4
    6
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsApplyingTest.java
  27. 24
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/StackPresenterTest.java
  28. 2
    5
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopBarButtonControllerTest.java
  29. 3
    5
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopBarControllerTest.java
  30. 5
    3
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/navigator/NavigatorTest.java
  31. 30
    0
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/navigator/RootPresenterTest.java
  32. 34
    13
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.java
  33. 0
    70
      lib/android/app/src/test/java/com/reactnativenavigation/views/TopBarBackgroundComponentTest.java
  34. 2
    5
      lib/android/app/src/test/java/com/reactnativenavigation/views/TopBarTest.java

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

1
 package com.reactnativenavigation.parse;
1
 package com.reactnativenavigation.parse;
2
 
2
 
3
+import com.reactnativenavigation.parse.params.Bool;
4
+import com.reactnativenavigation.parse.params.NullBool;
3
 import com.reactnativenavigation.parse.params.NullText;
5
 import com.reactnativenavigation.parse.params.NullText;
4
 import com.reactnativenavigation.parse.params.Text;
6
 import com.reactnativenavigation.parse.params.Text;
7
+import com.reactnativenavigation.parse.parsers.BoolParser;
5
 import com.reactnativenavigation.parse.parsers.TextParser;
8
 import com.reactnativenavigation.parse.parsers.TextParser;
6
 
9
 
7
 import org.json.JSONObject;
10
 import org.json.JSONObject;
14
         result.name = TextParser.parse(json, "name");
17
         result.name = TextParser.parse(json, "name");
15
         result.componentId = TextParser.parse(json, "componentId");
18
         result.componentId = TextParser.parse(json, "componentId");
16
         result.alignment = Alignment.fromString(TextParser.parse(json, "alignment").get(""));
19
         result.alignment = Alignment.fromString(TextParser.parse(json, "alignment").get(""));
20
+        result.waitForRender = BoolParser.parse(json, "waitForRender");
17
 
21
 
18
         return result;
22
         return result;
19
     }
23
     }
21
     public Text name = new NullText();
25
     public Text name = new NullText();
22
     public Text componentId = new NullText();
26
     public Text componentId = new NullText();
23
     public Alignment alignment = Alignment.Default;
27
     public Alignment alignment = Alignment.Default;
28
+    public Bool waitForRender = new NullBool();
24
 
29
 
25
     void mergeWith(Component other) {
30
     void mergeWith(Component other) {
26
         if (other.componentId.hasValue()) componentId = other.componentId;
31
         if (other.componentId.hasValue()) componentId = other.componentId;
27
         if (other.name.hasValue()) name = other.name;
32
         if (other.name.hasValue()) name = other.name;
33
+        if (other.waitForRender.hasValue()) waitForRender = other.waitForRender;
28
         if (other.alignment != Alignment.Default) alignment = other.alignment;
34
         if (other.alignment != Alignment.Default) alignment = other.alignment;
29
     }
35
     }
30
 
36
 
31
     public void mergeWithDefault(Component defaultOptions) {
37
     public void mergeWithDefault(Component defaultOptions) {
32
         if (!componentId.hasValue()) componentId = defaultOptions.componentId;
38
         if (!componentId.hasValue()) componentId = defaultOptions.componentId;
33
         if (!name.hasValue()) name = defaultOptions.name;
39
         if (!name.hasValue()) name = defaultOptions.name;
40
+        if (!waitForRender.hasValue()) waitForRender = defaultOptions.waitForRender;
34
         if (alignment == Alignment.Default) alignment = defaultOptions.alignment;
41
         if (alignment == Alignment.Default) alignment = defaultOptions.alignment;
35
     }
42
     }
36
 
43
 

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

7
 import com.reactnativenavigation.presentation.BottomTabsPresenter;
7
 import com.reactnativenavigation.presentation.BottomTabsPresenter;
8
 import com.reactnativenavigation.presentation.ComponentPresenter;
8
 import com.reactnativenavigation.presentation.ComponentPresenter;
9
 import com.reactnativenavigation.presentation.Presenter;
9
 import com.reactnativenavigation.presentation.Presenter;
10
+import com.reactnativenavigation.presentation.RenderChecker;
10
 import com.reactnativenavigation.presentation.SideMenuPresenter;
11
 import com.reactnativenavigation.presentation.SideMenuPresenter;
11
 import com.reactnativenavigation.presentation.StackPresenter;
12
 import com.reactnativenavigation.presentation.StackPresenter;
12
 import com.reactnativenavigation.react.EventEmitter;
13
 import com.reactnativenavigation.react.EventEmitter;
14
 import com.reactnativenavigation.utils.TypefaceLoader;
15
 import com.reactnativenavigation.utils.TypefaceLoader;
15
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
16
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
16
 import com.reactnativenavigation.viewcontrollers.ComponentViewController;
17
 import com.reactnativenavigation.viewcontrollers.ComponentViewController;
17
-import com.reactnativenavigation.viewcontrollers.sidemenu.SideMenuController;
18
 import com.reactnativenavigation.viewcontrollers.ViewController;
18
 import com.reactnativenavigation.viewcontrollers.ViewController;
19
 import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
19
 import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
20
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentCreator;
20
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentCreator;
21
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentViewController;
21
 import com.reactnativenavigation.viewcontrollers.externalcomponent.ExternalComponentViewController;
22
+import com.reactnativenavigation.viewcontrollers.sidemenu.SideMenuController;
22
 import com.reactnativenavigation.viewcontrollers.stack.StackControllerBuilder;
23
 import com.reactnativenavigation.viewcontrollers.stack.StackControllerBuilder;
23
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
24
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
24
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
25
 import com.reactnativenavigation.viewcontrollers.toptabs.TopTabsController;
25
 import com.reactnativenavigation.viewcontrollers.toptabs.TopTabsController;
26
 import com.reactnativenavigation.views.ComponentViewCreator;
26
 import com.reactnativenavigation.views.ComponentViewCreator;
165
         return new StackControllerBuilder(activity)
165
         return new StackControllerBuilder(activity)
166
                 .setChildren(createChildren(node.children))
166
                 .setChildren(createChildren(node.children))
167
                 .setChildRegistry(childRegistry)
167
                 .setChildRegistry(childRegistry)
168
-                .setTopBarButtonCreator(new TitleBarButtonCreator(reactInstanceManager))
169
-                .setTopBarBackgroundViewController(new TopBarBackgroundViewController(activity, new TopBarBackgroundViewCreator(reactInstanceManager)))
170
                 .setTopBarController(new TopBarController())
168
                 .setTopBarController(new TopBarController())
171
                 .setId(node.id)
169
                 .setId(node.id)
172
                 .setInitialOptions(parse(typefaceManager, node.getOptions()))
170
                 .setInitialOptions(parse(typefaceManager, node.getOptions()))
173
-                .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreator(reactInstanceManager), new TitleBarButtonCreator(reactInstanceManager), new ImageLoader(), defaultOptions))
171
+                .setStackPresenter(new StackPresenter(activity,
172
+                        new TitleBarReactViewCreator(reactInstanceManager),
173
+                        new TopBarBackgroundViewCreator(reactInstanceManager),
174
+                        new TitleBarButtonCreator(reactInstanceManager),
175
+                        new ImageLoader(),
176
+                        new RenderChecker(),
177
+                        defaultOptions
178
+                ))
174
                 .setPresenter(new Presenter(activity, defaultOptions))
179
                 .setPresenter(new Presenter(activity, defaultOptions))
175
                 .build();
180
                 .build();
176
 	}
181
 	}

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

2
 
2
 
3
 import android.graphics.Color;
3
 import android.graphics.Color;
4
 
4
 
5
+import com.reactnativenavigation.parse.params.Bool;
5
 import com.reactnativenavigation.parse.params.Colour;
6
 import com.reactnativenavigation.parse.params.Colour;
7
+import com.reactnativenavigation.parse.params.NullBool;
6
 import com.reactnativenavigation.parse.params.NullColor;
8
 import com.reactnativenavigation.parse.params.NullColor;
9
+import com.reactnativenavigation.parse.parsers.BoolParser;
7
 import com.reactnativenavigation.parse.parsers.ColorParser;
10
 import com.reactnativenavigation.parse.parsers.ColorParser;
8
 
11
 
9
 import org.json.JSONObject;
12
 import org.json.JSONObject;
15
 
18
 
16
         options.color = ColorParser.parse(json, "color");
19
         options.color = ColorParser.parse(json, "color");
17
         options.component = Component.parse(json.optJSONObject("component"));
20
         options.component = Component.parse(json.optJSONObject("component"));
21
+        options.waitForRender = BoolParser.parse(json, "waitForRender");
18
 
22
 
19
         if (options.component.hasValue()) {
23
         if (options.component.hasValue()) {
20
             options.color = new Colour(Color.TRANSPARENT);
24
             options.color = new Colour(Color.TRANSPARENT);
25
 
29
 
26
     public Colour color = new NullColor();
30
     public Colour color = new NullColor();
27
     public Component component = new Component();
31
     public Component component = new Component();
32
+    public Bool waitForRender = new NullBool();
28
 
33
 
29
     void mergeWith(final TopBarBackgroundOptions other) {
34
     void mergeWith(final TopBarBackgroundOptions other) {
30
         if (other.color.hasValue()) color = other.color;
35
         if (other.color.hasValue()) color = other.color;
36
+        if (other.waitForRender.hasValue()) waitForRender = other.waitForRender;
31
         component.mergeWith(other.component);
37
         component.mergeWith(other.component);
32
     }
38
     }
33
 
39
 
34
     void mergeWithDefault(TopBarBackgroundOptions defaultOptions) {
40
     void mergeWithDefault(TopBarBackgroundOptions defaultOptions) {
35
         if (!color.hasValue()) color = defaultOptions.color;
41
         if (!color.hasValue()) color = defaultOptions.color;
42
+        if (!waitForRender.hasValue()) waitForRender = defaultOptions.waitForRender;
36
         component.mergeWithDefault(defaultOptions.component);
43
         component.mergeWithDefault(defaultOptions.component);
37
     }
44
     }
38
 }
45
 }

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

154
             }
154
             }
155
         }
155
         }
156
     }
156
     }
157
-
158
 }
157
 }

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

1
+package com.reactnativenavigation.presentation;
2
+
3
+import com.reactnativenavigation.viewcontrollers.ViewController;
4
+
5
+import java.util.Collection;
6
+
7
+import static com.reactnativenavigation.utils.CollectionUtils.reduce;
8
+
9
+public class RenderChecker {
10
+    public boolean areRendered(Collection<ViewController> components) {
11
+        return reduce(components, true, ViewController::isRendered);
12
+    }
13
+}

+ 95
- 41
lib/android/app/src/main/java/com/reactnativenavigation/presentation/StackPresenter.java View File

9
 import android.view.View;
9
 import android.view.View;
10
 import android.view.ViewGroup.LayoutParams;
10
 import android.view.ViewGroup.LayoutParams;
11
 import android.view.ViewGroup.MarginLayoutParams;
11
 import android.view.ViewGroup.MarginLayoutParams;
12
+import android.widget.FrameLayout;
13
+import android.widget.RelativeLayout;
12
 
14
 
13
 import com.reactnativenavigation.parse.Alignment;
15
 import com.reactnativenavigation.parse.Alignment;
14
 import com.reactnativenavigation.parse.AnimationsOptions;
16
 import com.reactnativenavigation.parse.AnimationsOptions;
22
 import com.reactnativenavigation.parse.params.Colour;
24
 import com.reactnativenavigation.parse.params.Colour;
23
 import com.reactnativenavigation.utils.ButtonPresenter;
25
 import com.reactnativenavigation.utils.ButtonPresenter;
24
 import com.reactnativenavigation.utils.ImageLoader;
26
 import com.reactnativenavigation.utils.ImageLoader;
27
+import com.reactnativenavigation.utils.ObjectUtils;
25
 import com.reactnativenavigation.utils.UiUtils;
28
 import com.reactnativenavigation.utils.UiUtils;
26
 import com.reactnativenavigation.viewcontrollers.IReactView;
29
 import com.reactnativenavigation.viewcontrollers.IReactView;
27
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
30
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
28
 import com.reactnativenavigation.viewcontrollers.TitleBarButtonController;
31
 import com.reactnativenavigation.viewcontrollers.TitleBarButtonController;
29
 import com.reactnativenavigation.viewcontrollers.TitleBarReactViewController;
32
 import com.reactnativenavigation.viewcontrollers.TitleBarReactViewController;
33
+import com.reactnativenavigation.viewcontrollers.ViewController;
30
 import com.reactnativenavigation.viewcontrollers.button.NavigationIconResolver;
34
 import com.reactnativenavigation.viewcontrollers.button.NavigationIconResolver;
35
+import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
31
 import com.reactnativenavigation.views.Component;
36
 import com.reactnativenavigation.views.Component;
32
 import com.reactnativenavigation.views.titlebar.TitleBarReactViewCreator;
37
 import com.reactnativenavigation.views.titlebar.TitleBarReactViewCreator;
33
 import com.reactnativenavigation.views.topbar.TopBar;
38
 import com.reactnativenavigation.views.topbar.TopBar;
39
+import com.reactnativenavigation.views.topbar.TopBarBackgroundViewCreator;
34
 
40
 
35
 import java.util.ArrayList;
41
 import java.util.ArrayList;
36
 import java.util.Collections;
42
 import java.util.Collections;
39
 import java.util.List;
45
 import java.util.List;
40
 import java.util.Map;
46
 import java.util.Map;
41
 
47
 
48
+import static com.reactnativenavigation.utils.CollectionUtils.filter;
42
 import static com.reactnativenavigation.utils.CollectionUtils.forEach;
49
 import static com.reactnativenavigation.utils.CollectionUtils.forEach;
43
 import static com.reactnativenavigation.utils.CollectionUtils.keyBy;
50
 import static com.reactnativenavigation.utils.CollectionUtils.keyBy;
44
 import static com.reactnativenavigation.utils.CollectionUtils.merge;
51
 import static com.reactnativenavigation.utils.CollectionUtils.merge;
52
+import static com.reactnativenavigation.utils.ObjectUtils.perform;
45
 
53
 
46
 public class StackPresenter {
54
 public class StackPresenter {
47
     private static final int DEFAULT_TITLE_COLOR = Color.BLACK;
55
     private static final int DEFAULT_TITLE_COLOR = Color.BLACK;
56
     private final TitleBarReactViewCreator titleViewCreator;
64
     private final TitleBarReactViewCreator titleViewCreator;
57
     private TitleBarButtonController.OnClickListener onClickListener;
65
     private TitleBarButtonController.OnClickListener onClickListener;
58
     private final ImageLoader imageLoader;
66
     private final ImageLoader imageLoader;
67
+    private final RenderChecker renderChecker;
68
+    private final TopBarBackgroundViewCreator topBarBackgroundViewCreator;
59
     private final ReactViewCreator buttonCreator;
69
     private final ReactViewCreator buttonCreator;
60
     private Options defaultOptions;
70
     private Options defaultOptions;
61
-    private Map<Component, TitleBarReactViewController> titleComponentViewControllers = new HashMap<>();
62
-    private Map<Component, Map<String, TitleBarButtonController>> componentRightButtons = new HashMap<>();
63
-    private Map<Component, Map<String, TitleBarButtonController>> componentLeftButtons = new HashMap<>();
64
-
65
-    public StackPresenter(Activity activity, TitleBarReactViewCreator titleViewCreator, ReactViewCreator buttonCreator, ImageLoader imageLoader, Options defaultOptions) {
71
+    private Map<Component, TitleBarReactViewController> titleControllers = new HashMap();
72
+    private Map<Component, TopBarBackgroundViewController> backgroundControllers = new HashMap();
73
+    private Map<Component, Map<String, TitleBarButtonController>> componentRightButtons = new HashMap();
74
+    private Map<Component, Map<String, TitleBarButtonController>> componentLeftButtons = new HashMap();
75
+
76
+    public StackPresenter(Activity activity,
77
+                          TitleBarReactViewCreator titleViewCreator,
78
+                          TopBarBackgroundViewCreator topBarBackgroundViewCreator,
79
+                          ReactViewCreator buttonCreator,
80
+                          ImageLoader imageLoader,
81
+                          RenderChecker renderChecker,
82
+                          Options defaultOptions) {
66
         this.activity = activity;
83
         this.activity = activity;
67
         this.titleViewCreator = titleViewCreator;
84
         this.titleViewCreator = titleViewCreator;
85
+        this.topBarBackgroundViewCreator = topBarBackgroundViewCreator;
68
         this.buttonCreator = buttonCreator;
86
         this.buttonCreator = buttonCreator;
69
         this.imageLoader = imageLoader;
87
         this.imageLoader = imageLoader;
88
+        this.renderChecker = renderChecker;
70
         this.defaultOptions = defaultOptions;
89
         this.defaultOptions = defaultOptions;
71
         defaultTitleFontSize = UiUtils.dpToSp(activity, 18);
90
         defaultTitleFontSize = UiUtils.dpToSp(activity, 18);
72
         defaultSubtitleFontSize = UiUtils.dpToSp(activity, 14);
91
         defaultSubtitleFontSize = UiUtils.dpToSp(activity, 14);
84
         return defaultOptions;
103
         return defaultOptions;
85
     }
104
     }
86
 
105
 
87
-    public List<TitleBarButtonController> getComponentButtons(Component child) {
88
-        return merge(getRightButtons(child), getLeftButtons(child), Collections.EMPTY_LIST);
89
-    }
90
-
91
-    public List<TitleBarButtonController> getComponentButtons(Component child, List<TitleBarButtonController> defaultValue) {
92
-        return merge(getRightButtons(child), getLeftButtons(child), defaultValue);
93
-    }
94
-
95
-    private List<TitleBarButtonController> getRightButtons(Component child) {
96
-        return componentRightButtons.containsKey(child) ? new ArrayList<>(componentRightButtons.get(child).values()) : null;
97
-    }
98
-
99
-    private List<TitleBarButtonController> getLeftButtons(Component child) {
100
-        return componentLeftButtons.containsKey(child) ? new ArrayList<>(componentLeftButtons.get(child).values()) : null;
101
-    }
102
-
103
     public void bindView(TopBar topBar) {
106
     public void bindView(TopBar topBar) {
104
         this.topBar = topBar;
107
         this.topBar = topBar;
105
     }
108
     }
106
 
109
 
110
+    public boolean isRendered(Component component) {
111
+        ArrayList<ViewController> controllers = new ArrayList<>(perform(componentRightButtons.get(component), new ArrayList<>(), Map::values));
112
+        controllers.add(backgroundControllers.get(component));
113
+        controllers.add(titleControllers.get(component));
114
+        return renderChecker.areRendered(filter(controllers, ObjectUtils::notNull));
115
+    }
116
+
107
     public void applyLayoutParamsOptions(Options options, View view) {
117
     public void applyLayoutParamsOptions(Options options, View view) {
108
         Options withDefault = options.copy().withDefaultOptions(defaultOptions);
118
         Options withDefault = options.copy().withDefaultOptions(defaultOptions);
109
         if (view instanceof Component) {
119
         if (view instanceof Component) {
143
     }
153
     }
144
 
154
 
145
     public void onChildDestroyed(Component child) {
155
     public void onChildDestroyed(Component child) {
146
-        TitleBarReactViewController removed = titleComponentViewControllers.remove(child);
147
-        if (removed != null) {
148
-            removed.destroy();
149
-        }
156
+        perform(titleControllers.remove(child), TitleBarReactViewController::destroy);
157
+        perform(backgroundControllers.remove(child), TopBarBackgroundViewController::destroy);
150
         destroyButtons(componentRightButtons.get(child));
158
         destroyButtons(componentRightButtons.get(child));
151
         destroyButtons(componentLeftButtons.get(child));
159
         destroyButtons(componentLeftButtons.get(child));
152
         componentRightButtons.remove(child);
160
         componentRightButtons.remove(child);
153
         componentLeftButtons.remove(child);
161
         componentLeftButtons.remove(child);
154
     }
162
     }
155
 
163
 
156
-    private void destroyButtons(Map<String, TitleBarButtonController> buttons) {
157
-        if (buttons != null) {
158
-            for (TitleBarButtonController button : buttons.values()) {
159
-                button.destroy();
160
-            }
161
-        }
164
+    private void destroyButtons(@Nullable Map<String, TitleBarButtonController> buttons) {
165
+        if (buttons != null) forEach(buttons.values(), ViewController::destroy);
162
     }
166
     }
163
 
167
 
164
     private void applyTopBarOptions(TopBarOptions options, AnimationsOptions animationOptions, Component component, Options componentOptions) {
168
     private void applyTopBarOptions(TopBarOptions options, AnimationsOptions animationOptions, Component component, Options componentOptions) {
172
         topBar.setTitle(options.title.text.get(""));
176
         topBar.setTitle(options.title.text.get(""));
173
 
177
 
174
         if (options.title.component.hasValue()) {
178
         if (options.title.component.hasValue()) {
175
-            if (titleComponentViewControllers.containsKey(component)) {
176
-                topBar.setTitleComponent(titleComponentViewControllers.get(component).getView());
179
+            if (titleControllers.containsKey(component)) {
180
+                topBar.setTitleComponent(titleControllers.get(component).getView());
177
             } else {
181
             } else {
178
                 TitleBarReactViewController controller = new TitleBarReactViewController(activity, titleViewCreator);
182
                 TitleBarReactViewController controller = new TitleBarReactViewController(activity, titleViewCreator);
179
-                titleComponentViewControllers.put(component, controller);
183
+                controller.setWaitForRender(options.title.component.waitForRender);
184
+                titleControllers.put(component, controller);
180
                 controller.setComponent(options.title.component);
185
                 controller.setComponent(options.title.component);
181
                 controller.getView().setLayoutParams(getComponentLayoutParams(options.title.component));
186
                 controller.getView().setLayoutParams(getComponentLayoutParams(options.title.component));
182
                 topBar.setTitleComponent(controller.getView());
187
                 topBar.setTitleComponent(controller.getView());
198
         topBar.setBorderColor(options.borderColor.get(DEFAULT_BORDER_COLOR));
203
         topBar.setBorderColor(options.borderColor.get(DEFAULT_BORDER_COLOR));
199
 
204
 
200
         topBar.setBackgroundColor(options.background.color.get(Color.WHITE));
205
         topBar.setBackgroundColor(options.background.color.get(Color.WHITE));
201
-        topBar.setBackgroundComponent(options.background.component);
206
+
207
+        if (options.background.component.hasValue()) {
208
+            if (backgroundControllers.containsKey(component)) {
209
+                topBar.setBackgroundComponent(backgroundControllers.get(component).getView());
210
+            } else {
211
+                TopBarBackgroundViewController controller = new TopBarBackgroundViewController(activity, topBarBackgroundViewCreator);
212
+                controller.setWaitForRender(options.background.waitForRender);
213
+                backgroundControllers.put(component, controller);
214
+                controller.setComponent(options.background.component);
215
+                controller.getView().setLayoutParams(new RelativeLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
216
+                topBar.setBackgroundComponent(controller.getView());
217
+            }
218
+        }
219
+
202
         if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
220
         if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
203
         applyTopBarVisibility(options, animationOptions, componentOptions);
221
         applyTopBarVisibility(options, animationOptions, componentOptions);
204
         if (options.drawBehind.isTrue() && !componentOptions.layout.topMargin.hasValue()) {
222
         if (options.drawBehind.isTrue() && !componentOptions.layout.topMargin.hasValue()) {
278
     }
296
     }
279
 
297
 
280
     private TitleBarButtonController createButtonController(Button button) {
298
     private TitleBarButtonController createButtonController(Button button) {
281
-        return new TitleBarButtonController(activity,
299
+        TitleBarButtonController controller = new TitleBarButtonController(activity,
282
                 new NavigationIconResolver(activity, imageLoader),
300
                 new NavigationIconResolver(activity, imageLoader),
283
                 imageLoader,
301
                 imageLoader,
284
                 new ButtonPresenter(topBar.getTitleBar(), button),
302
                 new ButtonPresenter(topBar.getTitleBar(), button),
286
                 buttonCreator,
304
                 buttonCreator,
287
                 onClickListener
305
                 onClickListener
288
         );
306
         );
307
+        controller.setWaitForRender(button.component.waitForRender);
308
+        return controller;
289
     }
309
     }
290
 
310
 
291
     private void applyTopTabsOptions(TopTabsOptions options) {
311
     private void applyTopTabsOptions(TopTabsOptions options) {
371
         if (options.title.text.hasValue()) topBar.setTitle(options.title.text.get());
391
         if (options.title.text.hasValue()) topBar.setTitle(options.title.text.get());
372
 
392
 
373
         if (options.title.component.hasValue()) {
393
         if (options.title.component.hasValue()) {
374
-            if (titleComponentViewControllers.containsKey(component)) {
375
-                topBar.setTitleComponent(titleComponentViewControllers.get(component).getView());
394
+            if (titleControllers.containsKey(component)) {
395
+                topBar.setTitleComponent(titleControllers.get(component).getView());
376
             } else {
396
             } else {
377
                 TitleBarReactViewController controller = new TitleBarReactViewController(activity, titleViewCreator);
397
                 TitleBarReactViewController controller = new TitleBarReactViewController(activity, titleViewCreator);
378
-                titleComponentViewControllers.put(component, controller);
398
+                titleControllers.put(component, controller);
379
                 controller.setComponent(options.title.component);
399
                 controller.setComponent(options.title.component);
380
                 controller.getView().setLayoutParams(getComponentLayoutParams(options.title.component));
400
                 controller.getView().setLayoutParams(getComponentLayoutParams(options.title.component));
381
                 topBar.setTitleComponent(controller.getView());
401
                 topBar.setTitleComponent(controller.getView());
392
         if (options.subtitle.fontFamily != null) topBar.setSubtitleFontFamily(options.subtitle.fontFamily);
412
         if (options.subtitle.fontFamily != null) topBar.setSubtitleFontFamily(options.subtitle.fontFamily);
393
 
413
 
394
         if (options.background.color.hasValue()) topBar.setBackgroundColor(options.background.color.get());
414
         if (options.background.color.hasValue()) topBar.setBackgroundColor(options.background.color.get());
395
-        if (options.background.component.hasValue()) topBar.setBackgroundComponent(options.background.component);
415
+
416
+        if (options.background.component.hasValue()) {
417
+            if (backgroundControllers.containsKey(component)) {
418
+                topBar.setBackgroundComponent(backgroundControllers.get(component).getView());
419
+            } else {
420
+                TopBarBackgroundViewController controller = new TopBarBackgroundViewController(activity, topBarBackgroundViewCreator);
421
+                backgroundControllers.put(component, controller);
422
+                controller.setComponent(options.background.component);
423
+                controller.getView().setLayoutParams(new RelativeLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));
424
+                topBar.setBackgroundComponent(controller.getView());
425
+            }
426
+        }
396
 
427
 
397
         if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
428
         if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
398
 
429
 
441
 
472
 
442
     @RestrictTo(RestrictTo.Scope.TESTS)
473
     @RestrictTo(RestrictTo.Scope.TESTS)
443
     public Map<Component, TitleBarReactViewController> getTitleComponents() {
474
     public Map<Component, TitleBarReactViewController> getTitleComponents() {
444
-        return titleComponentViewControllers;
475
+        return titleControllers;
476
+    }
477
+
478
+    @RestrictTo(RestrictTo.Scope.TESTS)
479
+    public Map<Component, TopBarBackgroundViewController> getBackgroundComponents() {
480
+        return backgroundControllers;
481
+    }
482
+
483
+    @RestrictTo(RestrictTo.Scope.TESTS)
484
+    public List<TitleBarButtonController> getComponentButtons(Component child) {
485
+        return merge(getRightButtons(child), getLeftButtons(child), Collections.EMPTY_LIST);
486
+    }
487
+
488
+    @RestrictTo(RestrictTo.Scope.TESTS)
489
+    public List<TitleBarButtonController> getComponentButtons(Component child, List<TitleBarButtonController> defaultValue) {
490
+        return merge(getRightButtons(child), getLeftButtons(child), defaultValue);
491
+    }
492
+
493
+    private List<TitleBarButtonController> getRightButtons(Component child) {
494
+        return componentRightButtons.containsKey(child) ? new ArrayList<>(componentRightButtons.get(child).values()) : null;
495
+    }
496
+
497
+    private List<TitleBarButtonController> getLeftButtons(Component child) {
498
+        return componentLeftButtons.containsKey(child) ? new ArrayList<>(componentLeftButtons.get(child).values()) : null;
445
     }
499
     }
446
 }
500
 }

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

14
 import com.facebook.react.uimanager.events.EventDispatcher;
14
 import com.facebook.react.uimanager.events.EventDispatcher;
15
 import com.reactnativenavigation.interfaces.ScrollEventListener;
15
 import com.reactnativenavigation.interfaces.ScrollEventListener;
16
 import com.reactnativenavigation.viewcontrollers.IReactView;
16
 import com.reactnativenavigation.viewcontrollers.IReactView;
17
+import com.reactnativenavigation.views.Renderable;
17
 import com.reactnativenavigation.views.element.Element;
18
 import com.reactnativenavigation.views.element.Element;
18
 
19
 
19
 import java.util.ArrayList;
20
 import java.util.ArrayList;
20
 import java.util.List;
21
 import java.util.List;
21
 
22
 
22
 @SuppressLint("ViewConstructor")
23
 @SuppressLint("ViewConstructor")
23
-public class ReactView extends ReactRootView implements IReactView {
24
+public class ReactView extends ReactRootView implements IReactView, Renderable {
24
 
25
 
25
 	private final ReactInstanceManager reactInstanceManager;
26
 	private final ReactInstanceManager reactInstanceManager;
26
 	private final String componentId;
27
 	private final String componentId;

+ 29
- 2
lib/android/app/src/main/java/com/reactnativenavigation/utils/CollectionUtils.java View File

63
 
63
 
64
     public static <T> List<T> merge(@Nullable Collection<T> a, @Nullable Collection<T> b) {
64
     public static <T> List<T> merge(@Nullable Collection<T> a, @Nullable Collection<T> b) {
65
         if (a == null && b == null) return null;
65
         if (a == null && b == null) return null;
66
-        List<T> result = new ArrayList<>(get(a));
66
+        List<T> result = new ArrayList(get(a));
67
         result.addAll(get(b));
67
         result.addAll(get(b));
68
         return result;
68
         return result;
69
     }
69
     }
91
         return items.remove(items.size() - 1);
91
         return items.remove(items.size() - 1);
92
     }
92
     }
93
 
93
 
94
-    private static @NonNull <T> Collection<T> get(@Nullable Collection<T> t) {
94
+    public interface Reducer<S, T> {
95
+        S reduce(T item, S currentValue);
96
+    }
97
+
98
+    public static <S, T> S reduce(Collection<T> items, S initialValue, Reducer<S, T> reducer) {
99
+        S currentValue = initialValue;
100
+        for (T item : items) {
101
+            currentValue = reducer.reduce(item, currentValue);
102
+        }
103
+        return currentValue;
104
+    }
105
+
106
+    public static <T> Boolean reduce(@Nullable Collection<T> items, boolean initialValue, Functions.FuncR1<T, Boolean> reducer) {
107
+        boolean currentValue = initialValue;
108
+        if (CollectionUtils.isNullOrEmpty(items)) return currentValue;
109
+        for (T item : items) {
110
+            currentValue &= reducer.run(item);
111
+            if (!currentValue) return false;
112
+        }
113
+        return currentValue;
114
+    }
115
+
116
+    public static @NonNull <T> Collection<T> get(@Nullable Collection<T> t) {
95
         return t == null ? Collections.EMPTY_LIST : t;
117
         return t == null ? Collections.EMPTY_LIST : t;
96
     }
118
     }
119
+
120
+    public static @NonNull <T> Collection<T> get(@Nullable Map<?, T> t) {
121
+        return t == null ? Collections.EMPTY_LIST : t.values();
122
+    }
123
+
97
 }
124
 }

+ 4
- 0
lib/android/app/src/main/java/com/reactnativenavigation/utils/Functions.java View File

12
     public interface Func1<T> {
12
     public interface Func1<T> {
13
         void run(T param);
13
         void run(T param);
14
     }
14
     }
15
+
16
+    public interface FuncR1<T, S> {
17
+        S run(T param);
18
+    }
15
 }
19
 }

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

2
 
2
 
3
 import android.support.annotation.Nullable;
3
 import android.support.annotation.Nullable;
4
 
4
 
5
+import com.reactnativenavigation.utils.Functions.Func1;
6
+import com.reactnativenavigation.utils.Functions.FuncR1;
7
+
5
 public class ObjectUtils {
8
 public class ObjectUtils {
6
-    public interface Action<T> {
7
-        void performOn(T obj);
9
+    public static <T> void perform(@Nullable T obj, Func1<T> action) {
10
+        if (obj != null) action.run(obj);
11
+    }
12
+
13
+    public static <T, S> S perform(@Nullable T obj, S defaultValue, FuncR1<T, S> action) {
14
+        return obj == null ? defaultValue : action.run(obj);
8
     }
15
     }
9
 
16
 
10
-    public static <T> void perform(@Nullable T obj, Action<T> action) {
11
-        if (obj != null) action.performOn(obj);
17
+    public static boolean notNull(Object o) {
18
+        return o != null;
12
     }
19
     }
13
 }
20
 }

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

69
     @SuppressLint("MissingSuperCall")
69
     @SuppressLint("MissingSuperCall")
70
     @Override
70
     @Override
71
     public void onViewAppeared() {
71
     public void onViewAppeared() {
72
-        view.sendComponentStart();
72
+        getView().sendComponentStart();
73
     }
73
     }
74
 
74
 
75
     @SuppressLint("MissingSuperCall")
75
     @SuppressLint("MissingSuperCall")
76
     @Override
76
     @Override
77
     public void onViewDisappear() {
77
     public void onViewDisappear() {
78
-        view.sendComponentStop();
78
+        getView().sendComponentStop();
79
+    }
80
+
81
+    @Override
82
+    public boolean isRendered() {
83
+        return !button.component.componentId.hasValue() || super.isRendered();
79
     }
84
     }
80
 
85
 
81
     @Override
86
     @Override

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

22
     public void onViewAppeared() {
22
     public void onViewAppeared() {
23
         super.onViewAppeared();
23
         super.onViewAppeared();
24
         runOnPreDraw(view -> view.setLayoutParams(view.getLayoutParams()));
24
         runOnPreDraw(view -> view.setLayoutParams(view.getLayoutParams()));
25
-        view.sendComponentStart();
25
+        getView().sendComponentStart();
26
     }
26
     }
27
 
27
 
28
     @Override
28
     @Override
29
     public void onViewDisappear() {
29
     public void onViewDisappear() {
30
-        view.sendComponentStop();
30
+        getView().sendComponentStop();
31
         super.onViewDisappear();
31
         super.onViewDisappear();
32
     }
32
     }
33
 
33
 

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

22
 import com.reactnativenavigation.utils.UiUtils;
22
 import com.reactnativenavigation.utils.UiUtils;
23
 import com.reactnativenavigation.viewcontrollers.stack.StackController;
23
 import com.reactnativenavigation.viewcontrollers.stack.StackController;
24
 import com.reactnativenavigation.views.Component;
24
 import com.reactnativenavigation.views.Component;
25
+import com.reactnativenavigation.views.Renderable;
25
 import com.reactnativenavigation.views.element.Element;
26
 import com.reactnativenavigation.views.element.Element;
26
 
27
 
27
 import java.util.Collections;
28
 import java.util.Collections;
286
     public boolean isRendered() {
287
     public boolean isRendered() {
287
         return view != null && (
288
         return view != null && (
288
                 waitForRender.isFalseOrUndefined() ||
289
                 waitForRender.isFalseOrUndefined() ||
289
-                !(view instanceof Component) ||
290
-                ((Component) view).isRendered()
290
+                !(view instanceof Renderable) ||
291
+                ((Renderable) view).isRendered()
291
         );
292
         );
292
     }
293
     }
293
 
294
 

+ 10
- 5
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/navigator/Navigator.java View File

12
 import com.reactnativenavigation.presentation.Presenter;
12
 import com.reactnativenavigation.presentation.Presenter;
13
 import com.reactnativenavigation.react.EventEmitter;
13
 import com.reactnativenavigation.react.EventEmitter;
14
 import com.reactnativenavigation.utils.CommandListener;
14
 import com.reactnativenavigation.utils.CommandListener;
15
+import com.reactnativenavigation.utils.CommandListenerAdapter;
15
 import com.reactnativenavigation.utils.CompatUtils;
16
 import com.reactnativenavigation.utils.CompatUtils;
16
 import com.reactnativenavigation.utils.Functions.Func1;
17
 import com.reactnativenavigation.utils.Functions.Func1;
17
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
18
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
126
 
127
 
127
     public void setRoot(final ViewController viewController, CommandListener commandListener) {
128
     public void setRoot(final ViewController viewController, CommandListener commandListener) {
128
         destroyRoot();
129
         destroyRoot();
129
-        if (isRootNotCreated()) {
130
-            removePreviousContentView();
131
-            getView();
132
-        }
130
+        final boolean removeSplashView = isRootNotCreated();
131
+        if (isRootNotCreated()) getView();
133
         root = viewController;
132
         root = viewController;
134
-        rootPresenter.setRoot(root, defaultOptions, commandListener);
133
+        rootPresenter.setRoot(root, defaultOptions, new CommandListenerAdapter(commandListener) {
134
+            @Override
135
+            public void onSuccess(String childId) {
136
+                if (removeSplashView) removePreviousContentView();
137
+                super.onSuccess(childId);
138
+            }
139
+        });
135
     }
140
     }
136
 
141
 
137
     private void removePreviousContentView() {
142
     private void removePreviousContentView() {

+ 15
- 2
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/navigator/RootPresenter.java View File

13
     private NavigationAnimator animator;
13
     private NavigationAnimator animator;
14
     private FrameLayout rootLayout;
14
     private FrameLayout rootLayout;
15
 
15
 
16
-    public void setRootContainer(FrameLayout rootLayout) {
16
+    void setRootContainer(FrameLayout rootLayout) {
17
         this.rootLayout = rootLayout;
17
         this.rootLayout = rootLayout;
18
     }
18
     }
19
 
19
 
25
         this.animator = animator;
25
         this.animator = animator;
26
     }
26
     }
27
 
27
 
28
-    public void setRoot(ViewController root, Options defaultOptions, CommandListener listener) {
28
+    void setRoot(ViewController root, Options defaultOptions, CommandListener listener) {
29
         rootLayout.addView(root.getView());
29
         rootLayout.addView(root.getView());
30
         Options options = root.resolveCurrentOptions(defaultOptions);
30
         Options options = root.resolveCurrentOptions(defaultOptions);
31
+        root.setWaitForRender(options.animations.setRoot.waitForRender);
32
+        if (options.animations.setRoot.waitForRender.isTrue()) {
33
+            root.getView().setAlpha(0);
34
+            root.setOnAppearedListener(() -> {
35
+                root.getView().setAlpha(1);
36
+                animateSetRootAndReportSuccess(root, listener, options);
37
+            });
38
+        } else {
39
+            animateSetRootAndReportSuccess(root, listener, options);
40
+        }
41
+    }
42
+
43
+    private void animateSetRootAndReportSuccess(ViewController root, CommandListener listener, Options options) {
31
         if (options.animations.setRoot.hasAnimation()) {
44
         if (options.animations.setRoot.hasAnimation()) {
32
             animator.setRoot(root.getView(), options.animations.setRoot, () -> listener.onSuccess(root.getId()));
45
             animator.setRoot(root.getView(), options.animations.setRoot, () -> listener.onSuccess(root.getId()));
33
         } else {
46
         } else {

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

21
 import com.reactnativenavigation.viewcontrollers.IdStack;
21
 import com.reactnativenavigation.viewcontrollers.IdStack;
22
 import com.reactnativenavigation.viewcontrollers.ParentController;
22
 import com.reactnativenavigation.viewcontrollers.ParentController;
23
 import com.reactnativenavigation.viewcontrollers.ViewController;
23
 import com.reactnativenavigation.viewcontrollers.ViewController;
24
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
25
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
24
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
26
 import com.reactnativenavigation.views.Component;
25
 import com.reactnativenavigation.views.Component;
27
 import com.reactnativenavigation.views.ReactComponent;
26
 import com.reactnativenavigation.views.ReactComponent;
38
 
37
 
39
     private final IdStack<ViewController> stack = new IdStack<>();
38
     private final IdStack<ViewController> stack = new IdStack<>();
40
     private final NavigationAnimator animator;
39
     private final NavigationAnimator animator;
41
-    private TopBarBackgroundViewController topBarBackgroundViewController;
42
     private TopBarController topBarController;
40
     private TopBarController topBarController;
43
     private BackButtonHelper backButtonHelper;
41
     private BackButtonHelper backButtonHelper;
44
     private final StackPresenter presenter;
42
     private final StackPresenter presenter;
45
 
43
 
46
-    public StackController(Activity activity, List<ViewController> children, ChildControllersRegistry childRegistry, TopBarBackgroundViewController topBarBackgroundViewController, TopBarController topBarController, NavigationAnimator animator, String id, Options initialOptions, BackButtonHelper backButtonHelper, StackPresenter stackPresenter, Presenter presenter) {
44
+    public StackController(Activity activity, List<ViewController> children, ChildControllersRegistry childRegistry, TopBarController topBarController, NavigationAnimator animator, String id, Options initialOptions, BackButtonHelper backButtonHelper, StackPresenter stackPresenter, Presenter presenter) {
47
         super(activity, childRegistry, id, presenter, initialOptions);
45
         super(activity, childRegistry, id, presenter, initialOptions);
48
         this.topBarController = topBarController;
46
         this.topBarController = topBarController;
49
-        this.topBarBackgroundViewController = topBarBackgroundViewController;
50
         this.animator = animator;
47
         this.animator = animator;
51
         this.backButtonHelper = backButtonHelper;
48
         this.backButtonHelper = backButtonHelper;
52
         this.presenter = stackPresenter;
49
         this.presenter = stackPresenter;
58
         }
55
         }
59
     }
56
     }
60
 
57
 
58
+    @Override
59
+    public boolean isRendered() {
60
+        if (isEmpty()) return false;
61
+        ViewGroup currentChild = getCurrentChild().getView();
62
+        if (currentChild instanceof Component) {
63
+            return super.isRendered() && presenter.isRendered((Component) currentChild);
64
+        }
65
+        return super.isRendered();
66
+    }
67
+
61
     @Override
68
     @Override
62
     public void setDefaultOptions(Options defaultOptions) {
69
     public void setDefaultOptions(Options defaultOptions) {
63
         super.setDefaultOptions(defaultOptions);
70
         super.setDefaultOptions(defaultOptions);
303
         pop(mergeOptions, listener);
310
         pop(mergeOptions, listener);
304
     }
311
     }
305
 
312
 
306
-    private void removeAndDestroyController(ViewController controller) {
307
-        stack.remove(controller.getId());
308
-        controller.destroy();
309
-    }
310
-
311
     ViewController peek() {
313
     ViewController peek() {
312
         return stack.peek();
314
         return stack.peek();
313
     }
315
     }
337
     @NonNull
339
     @NonNull
338
     @Override
340
     @Override
339
     protected StackLayout createView() {
341
     protected StackLayout createView() {
340
-        StackLayout stackLayout = new StackLayout(getActivity(),
341
-                topBarBackgroundViewController,
342
-                topBarController,
343
-                getId()
344
-        );
342
+        StackLayout stackLayout = new StackLayout(getActivity(), topBarController, getId());
345
         presenter.bindView(topBarController.getView());
343
         presenter.bindView(topBarController.getView());
346
         addInitialChild(stackLayout);
344
         addInitialChild(stackLayout);
347
         return stackLayout;
345
         return stackLayout;

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

7
 import com.reactnativenavigation.presentation.Presenter;
7
 import com.reactnativenavigation.presentation.Presenter;
8
 import com.reactnativenavigation.presentation.StackPresenter;
8
 import com.reactnativenavigation.presentation.StackPresenter;
9
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
9
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
10
-import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
11
 import com.reactnativenavigation.viewcontrollers.ViewController;
10
 import com.reactnativenavigation.viewcontrollers.ViewController;
12
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
13
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
11
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
14
 import com.reactnativenavigation.views.element.ElementTransitionManager;
12
 import com.reactnativenavigation.views.element.ElementTransitionManager;
15
 
13
 
19
 public class StackControllerBuilder {
17
 public class StackControllerBuilder {
20
     private Activity activity;
18
     private Activity activity;
21
     private ChildControllersRegistry childRegistry;
19
     private ChildControllersRegistry childRegistry;
22
-    private ReactViewCreator topBarButtonCreator;
23
-    private TopBarBackgroundViewController topBarBackgroundViewController;
24
     private TopBarController topBarController;
20
     private TopBarController topBarController;
25
     private String id;
21
     private String id;
26
     private Options initialOptions = new Options();
22
     private Options initialOptions = new Options();
56
         return this;
52
         return this;
57
     }
53
     }
58
 
54
 
59
-    public StackControllerBuilder setTopBarButtonCreator(ReactViewCreator topBarButtonCreator) {
60
-        this.topBarButtonCreator = topBarButtonCreator;
61
-        return this;
62
-    }
63
-
64
-    public StackControllerBuilder setTopBarBackgroundViewController(TopBarBackgroundViewController topBarBackgroundViewController) {
65
-        this.topBarBackgroundViewController = topBarBackgroundViewController;
66
-        return this;
67
-    }
68
-
69
     public StackControllerBuilder setTopBarController(TopBarController topBarController) {
55
     public StackControllerBuilder setTopBarController(TopBarController topBarController) {
70
         this.topBarController = topBarController;
56
         this.topBarController = topBarController;
71
         return this;
57
         return this;
86
         return this;
72
         return this;
87
     }
73
     }
88
 
74
 
89
-    public StackControllerBuilder setBackButtonHelper(BackButtonHelper backButtonHelper) {
75
+    StackControllerBuilder setBackButtonHelper(BackButtonHelper backButtonHelper) {
90
         this.backButtonHelper = backButtonHelper;
76
         this.backButtonHelper = backButtonHelper;
91
         return this;
77
         return this;
92
     }
78
     }
95
         return new StackController(activity,
81
         return new StackController(activity,
96
                 children,
82
                 children,
97
                 childRegistry,
83
                 childRegistry,
98
-                topBarBackgroundViewController,
99
                 topBarController,
84
                 topBarController,
100
                 animator,
85
                 animator,
101
                 id,
86
                 id,

+ 2
- 7
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/topbar/TopBarBackgroundViewController.java View File

20
         this.viewCreator = viewCreator;
20
         this.viewCreator = viewCreator;
21
     }
21
     }
22
 
22
 
23
-    public TopBarBackgroundViewController(TopBarBackgroundViewController controller) {
24
-        super(controller.getActivity(), controller.getId(), new YellowBoxDelegate(), controller.options);
25
-        this.viewCreator = controller.viewCreator;
26
-    }
27
-
28
     @Override
23
     @Override
29
     protected TopBarBackgroundView createView() {
24
     protected TopBarBackgroundView createView() {
30
         return viewCreator.create(getActivity(), component.componentId.get(), component.name.get());
25
         return viewCreator.create(getActivity(), component.componentId.get(), component.name.get());
33
     @Override
28
     @Override
34
     public void onViewAppeared() {
29
     public void onViewAppeared() {
35
         super.onViewAppeared();
30
         super.onViewAppeared();
36
-        view.sendComponentStart();
31
+        getView().sendComponentStart();
37
     }
32
     }
38
 
33
 
39
     @Override
34
     @Override
40
     public void onViewDisappear() {
35
     public void onViewDisappear() {
41
-        view.sendComponentStop();
36
+        getView().sendComponentStop();
42
         super.onViewDisappear();
37
         super.onViewDisappear();
43
     }
38
     }
44
 
39
 

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

12
 public class TopBarController {
12
 public class TopBarController {
13
     private TopBar topBar;
13
     private TopBar topBar;
14
 
14
 
15
-    public View createView(Context context, TopBarBackgroundViewController topBarBackgroundViewController, StackLayout stackLayout) {
15
+    public View createView(Context context, StackLayout stackLayout) {
16
         if (topBar == null) {
16
         if (topBar == null) {
17
-            topBar = createTopBar(context, topBarBackgroundViewController, stackLayout);
17
+            topBar = createTopBar(context, stackLayout);
18
             topBar.setId(CompatUtils.generateViewId());
18
             topBar.setId(CompatUtils.generateViewId());
19
         }
19
         }
20
         return topBar;
20
         return topBar;
21
     }
21
     }
22
 
22
 
23
-    protected TopBar createTopBar(Context context, TopBarBackgroundViewController topBarBackgroundViewController, StackLayout stackLayout) {
24
-        return new TopBar(context, topBarBackgroundViewController, stackLayout);
23
+    protected TopBar createTopBar(Context context, StackLayout stackLayout) {
24
+        return new TopBar(context, stackLayout);
25
     }
25
     }
26
 
26
 
27
     public void clear() {
27
     public void clear() {

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

2
 
2
 
3
 import com.reactnativenavigation.views.topbar.TopBar;
3
 import com.reactnativenavigation.views.topbar.TopBar;
4
 
4
 
5
-public interface Component {
5
+public interface Component extends Renderable {
6
     void drawBehindTopBar();
6
     void drawBehindTopBar();
7
 
7
 
8
     void drawBelowTopBar(TopBar topBar);
8
     void drawBelowTopBar(TopBar topBar);
9
-
10
-    boolean isRendered();
11
 }
9
 }

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

1
+package com.reactnativenavigation.views;
2
+
3
+public interface Renderable {
4
+    boolean isRendered();
5
+}

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

5
 import android.widget.RelativeLayout;
5
 import android.widget.RelativeLayout;
6
 
6
 
7
 import com.reactnativenavigation.utils.UiUtils;
7
 import com.reactnativenavigation.utils.UiUtils;
8
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
9
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
8
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
10
 import com.reactnativenavigation.views.topbar.TopBar;
9
 import com.reactnativenavigation.views.topbar.TopBar;
11
 
10
 
15
 public class StackLayout extends RelativeLayout implements Component {
14
 public class StackLayout extends RelativeLayout implements Component {
16
     private String stackId;
15
     private String stackId;
17
 
16
 
18
-    public StackLayout(Context context, TopBarBackgroundViewController topBarBackgroundViewController, TopBarController topBarController, String stackId) {
17
+    public StackLayout(Context context, TopBarController topBarController, String stackId) {
19
         super(context);
18
         super(context);
20
         this.stackId = stackId;
19
         this.stackId = stackId;
21
-        createLayout(topBarBackgroundViewController, topBarController);
20
+        createLayout(topBarController);
22
         setContentDescription("StackLayout");
21
         setContentDescription("StackLayout");
23
     }
22
     }
24
 
23
 
25
-    private void createLayout(TopBarBackgroundViewController topBarBackgroundViewController, TopBarController topBarController) {
26
-        addView(topBarController.createView(getContext(), topBarBackgroundViewController, this),
24
+    private void createLayout(TopBarController topBarController) {
25
+        addView(topBarController.createView(getContext(), this),
27
                 MATCH_PARENT,
26
                 MATCH_PARENT,
28
                 UiUtils.getTopBarHeight(getContext())
27
                 UiUtils.getTopBarHeight(getContext())
29
         );
28
         );

+ 9
- 13
lib/android/app/src/main/java/com/reactnativenavigation/views/topbar/TopBar.java View File

27
 import com.reactnativenavigation.interfaces.ScrollEventListener;
27
 import com.reactnativenavigation.interfaces.ScrollEventListener;
28
 import com.reactnativenavigation.parse.Alignment;
28
 import com.reactnativenavigation.parse.Alignment;
29
 import com.reactnativenavigation.parse.AnimationOptions;
29
 import com.reactnativenavigation.parse.AnimationOptions;
30
-import com.reactnativenavigation.parse.Component;
31
 import com.reactnativenavigation.parse.params.Colour;
30
 import com.reactnativenavigation.parse.params.Colour;
32
 import com.reactnativenavigation.parse.params.Number;
31
 import com.reactnativenavigation.parse.params.Number;
33
 import com.reactnativenavigation.utils.CompatUtils;
32
 import com.reactnativenavigation.utils.CompatUtils;
34
 import com.reactnativenavigation.utils.UiUtils;
33
 import com.reactnativenavigation.utils.UiUtils;
35
 import com.reactnativenavigation.viewcontrollers.TitleBarButtonController;
34
 import com.reactnativenavigation.viewcontrollers.TitleBarButtonController;
36
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
37
 import com.reactnativenavigation.views.StackLayout;
35
 import com.reactnativenavigation.views.StackLayout;
38
 import com.reactnativenavigation.views.titlebar.TitleBar;
36
 import com.reactnativenavigation.views.titlebar.TitleBar;
39
 import com.reactnativenavigation.views.toptabs.TopTabs;
37
 import com.reactnativenavigation.views.toptabs.TopTabs;
50
     private TopBarAnimator animator;
48
     private TopBarAnimator animator;
51
     private TopTabs topTabs;
49
     private TopTabs topTabs;
52
     private FrameLayout root;
50
     private FrameLayout root;
53
-    private TopBarBackgroundViewController topBarBackgroundViewController;
54
     private View border;
51
     private View border;
52
+    private View component;
55
 
53
 
56
-    public TopBar(final Context context, TopBarBackgroundViewController topBarBackgroundViewController, StackLayout parentView) {
54
+    public TopBar(final Context context, StackLayout parentView) {
57
         super(context);
55
         super(context);
58
         context.setTheme(R.style.TopBar);
56
         context.setTheme(R.style.TopBar);
59
         collapsingBehavior = new TopBarCollapseBehavior(this);
57
         collapsingBehavior = new TopBarCollapseBehavior(this);
60
-        this.topBarBackgroundViewController = topBarBackgroundViewController;
61
         topTabs = new TopTabs(getContext());
58
         topTabs = new TopTabs(getContext());
62
         animator = new TopBarAnimator(this, parentView.getStackId());
59
         animator = new TopBarAnimator(this, parentView.getStackId());
63
         createLayout();
60
         createLayout();
175
         titleBar.setComponent(component);
172
         titleBar.setComponent(component);
176
     }
173
     }
177
 
174
 
178
-    public void setBackgroundComponent(Component component) {
179
-        if (component.hasValue()) {
180
-            topBarBackgroundViewController.setComponent(component);
181
-            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
182
-            root.addView(topBarBackgroundViewController.getView(), 0, lp);
183
-        }
175
+    public void setBackgroundComponent(View component) {
176
+        this.component = component;
177
+        root.addView(component, 0);
184
     }
178
     }
185
 
179
 
186
     public void setTopTabFontFamily(int tabIndex, Typeface fontFamily) {
180
     public void setTopTabFontFamily(int tabIndex, Typeface fontFamily) {
272
     }
266
     }
273
 
267
 
274
     public void clear() {
268
     public void clear() {
275
-        topBarBackgroundViewController.destroy();
276
-        topBarBackgroundViewController = new TopBarBackgroundViewController(topBarBackgroundViewController);
269
+        if (component != null) {
270
+            root.removeView(component);
271
+            component = null;
272
+        }
277
         titleBar.clear();
273
         titleBar.clear();
278
     }
274
     }
279
 
275
 

+ 4
- 6
lib/android/app/src/test/java/com/reactnativenavigation/TestUtils.java View File

8
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
8
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
9
 import com.reactnativenavigation.parse.Options;
9
 import com.reactnativenavigation.parse.Options;
10
 import com.reactnativenavigation.parse.params.Bool;
10
 import com.reactnativenavigation.parse.params.Bool;
11
+import com.reactnativenavigation.presentation.RenderChecker;
11
 import com.reactnativenavigation.presentation.StackPresenter;
12
 import com.reactnativenavigation.presentation.StackPresenter;
12
 import com.reactnativenavigation.utils.ImageLoader;
13
 import com.reactnativenavigation.utils.ImageLoader;
13
 import com.reactnativenavigation.utils.UiUtils;
14
 import com.reactnativenavigation.utils.UiUtils;
14
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
15
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
15
 import com.reactnativenavigation.viewcontrollers.ViewController;
16
 import com.reactnativenavigation.viewcontrollers.ViewController;
16
 import com.reactnativenavigation.viewcontrollers.stack.StackControllerBuilder;
17
 import com.reactnativenavigation.viewcontrollers.stack.StackControllerBuilder;
17
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
18
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
18
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
19
 import com.reactnativenavigation.views.StackLayout;
19
 import com.reactnativenavigation.views.StackLayout;
20
 import com.reactnativenavigation.views.topbar.TopBar;
20
 import com.reactnativenavigation.views.topbar.TopBar;
24
         return new StackControllerBuilder(activity)
24
         return new StackControllerBuilder(activity)
25
                 .setId("stack")
25
                 .setId("stack")
26
                 .setChildRegistry(new ChildControllersRegistry())
26
                 .setChildRegistry(new ChildControllersRegistry())
27
-                .setTopBarButtonCreator(new TopBarButtonCreatorMock())
28
-                .setTopBarBackgroundViewController(new TopBarBackgroundViewController(activity, new TopBarBackgroundViewCreatorMock()))
29
                 .setTopBarController(new TopBarController() {
27
                 .setTopBarController(new TopBarController() {
30
                     @Override
28
                     @Override
31
-                    protected TopBar createTopBar(Context context, TopBarBackgroundViewController topBarBackgroundViewController, StackLayout stackLayout) {
32
-                        TopBar topBar = super.createTopBar(context, topBarBackgroundViewController, stackLayout);
29
+                    protected TopBar createTopBar(Context context, StackLayout stackLayout) {
30
+                        TopBar topBar = super.createTopBar(context, stackLayout);
33
                         topBar.layout(0, 0, 1000, UiUtils.getTopBarHeight(context));
31
                         topBar.layout(0, 0, 1000, UiUtils.getTopBarHeight(context));
34
                         return topBar;
32
                         return topBar;
35
                     }
33
                     }
36
                 })
34
                 })
37
-                .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarButtonCreatorMock(), new ImageLoader(), new Options())                )
35
+                .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), new ImageLoader(), new RenderChecker(), new Options()))
38
                 .setInitialOptions(new Options());
36
                 .setInitialOptions(new Options());
39
     }
37
     }
40
 
38
 

+ 58
- 0
lib/android/app/src/test/java/com/reactnativenavigation/presentation/RenderCheckerTest.java View File

1
+package com.reactnativenavigation.presentation;
2
+
3
+import com.reactnativenavigation.BaseTest;
4
+import com.reactnativenavigation.viewcontrollers.ViewController;
5
+
6
+import org.junit.Test;
7
+import org.mockito.Mockito;
8
+
9
+import java.util.Arrays;
10
+import java.util.Collection;
11
+
12
+import static com.reactnativenavigation.utils.CollectionUtils.forEach;
13
+import static org.assertj.core.api.Java6Assertions.assertThat;
14
+import static org.mockito.Mockito.verify;
15
+import static org.mockito.Mockito.when;
16
+
17
+public class RenderCheckerTest extends BaseTest {
18
+    private RenderChecker uut;
19
+
20
+    @Override
21
+    public void beforeEach() {
22
+        uut = new RenderChecker();
23
+    }
24
+
25
+    @Test
26
+    public void areRendered() {
27
+        Collection<ViewController> items = Arrays.asList(
28
+                renderedComponent(),
29
+                renderedComponent(),
30
+                renderedComponent()
31
+        );
32
+        assertThat(uut.areRendered(items)).isTrue();
33
+        forEach(items, i -> verify(i).isRendered());
34
+    }
35
+
36
+    @Test
37
+    public void areRendered_reduce() {
38
+        Collection<ViewController> items = Arrays.asList(
39
+                renderedComponent(),
40
+                notRenderedComponent(),
41
+                renderedComponent()
42
+        );
43
+        assertThat(uut.areRendered(items)).isFalse();
44
+
45
+    }
46
+
47
+    private ViewController renderedComponent() {
48
+        ViewController mock = Mockito.mock(ViewController.class);
49
+        when(mock.isRendered()).then(__ -> true);
50
+        return mock;
51
+    }
52
+
53
+    private ViewController notRenderedComponent() {
54
+        ViewController mock = Mockito.mock(ViewController.class);
55
+        when(mock.isRendered()).then(__ -> false);
56
+        return mock;
57
+    }
58
+}

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

21
 import com.reactnativenavigation.parse.params.Text;
21
 import com.reactnativenavigation.parse.params.Text;
22
 import com.reactnativenavigation.presentation.ComponentPresenter;
22
 import com.reactnativenavigation.presentation.ComponentPresenter;
23
 import com.reactnativenavigation.presentation.Presenter;
23
 import com.reactnativenavigation.presentation.Presenter;
24
+import com.reactnativenavigation.presentation.RenderChecker;
24
 import com.reactnativenavigation.presentation.StackPresenter;
25
 import com.reactnativenavigation.presentation.StackPresenter;
25
 import com.reactnativenavigation.utils.CommandListenerAdapter;
26
 import com.reactnativenavigation.utils.CommandListenerAdapter;
26
 import com.reactnativenavigation.utils.ImageLoader;
27
 import com.reactnativenavigation.utils.ImageLoader;
27
 import com.reactnativenavigation.viewcontrollers.stack.StackController;
28
 import com.reactnativenavigation.viewcontrollers.stack.StackController;
28
 import com.reactnativenavigation.viewcontrollers.stack.StackControllerBuilder;
29
 import com.reactnativenavigation.viewcontrollers.stack.StackControllerBuilder;
29
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
30
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
30
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
31
 import com.reactnativenavigation.views.StackLayout;
31
 import com.reactnativenavigation.views.StackLayout;
32
 import com.reactnativenavigation.views.topbar.TopBar;
32
 import com.reactnativenavigation.views.topbar.TopBar;
72
         };
72
         };
73
         TopBarController topBarController = new TopBarController() {
73
         TopBarController topBarController = new TopBarController() {
74
             @Override
74
             @Override
75
-            protected TopBar createTopBar(Context context, TopBarBackgroundViewController topBarBackgroundViewController, StackLayout stackLayout) {
76
-                topBar = spy(super.createTopBar(context, topBarBackgroundViewController, stackLayout));
75
+            protected TopBar createTopBar(Context context, StackLayout stackLayout) {
76
+                topBar = spy(super.createTopBar(context, stackLayout));
77
                 return topBar;
77
                 return topBar;
78
             }
78
             }
79
         };
79
         };
102
         uut.options.topBar.title.text = new Text("the title");
102
         uut.options.topBar.title.text = new Text("the title");
103
         StackController stackController =
103
         StackController stackController =
104
                 new StackControllerBuilder(activity)
104
                 new StackControllerBuilder(activity)
105
-                        .setTopBarButtonCreator(new TopBarButtonCreatorMock())
106
-                        .setTopBarBackgroundViewController(new TopBarBackgroundViewController(activity, new TopBarBackgroundViewCreatorMock()))
107
                         .setTopBarController(new TopBarController())
105
                         .setTopBarController(new TopBarController())
108
                         .setId("stackId")
106
                         .setId("stackId")
109
                         .setInitialOptions(new Options())
107
                         .setInitialOptions(new Options())
110
-                        .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarButtonCreatorMock(), new ImageLoader(), new Options()))
108
+                        .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), new ImageLoader(), new RenderChecker(), new Options()))
111
                         .build();
109
                         .build();
112
         stackController.ensureViewIsCreated();
110
         stackController.ensureViewIsCreated();
113
         stackController.push(uut, new CommandListenerAdapter());
111
         stackController.push(uut, new CommandListenerAdapter());

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

13
 import com.reactnativenavigation.mocks.TestComponentLayout;
13
 import com.reactnativenavigation.mocks.TestComponentLayout;
14
 import com.reactnativenavigation.mocks.TestReactView;
14
 import com.reactnativenavigation.mocks.TestReactView;
15
 import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
15
 import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
16
+import com.reactnativenavigation.mocks.TopBarBackgroundViewCreatorMock;
16
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
17
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
17
 import com.reactnativenavigation.parse.Alignment;
18
 import com.reactnativenavigation.parse.Alignment;
18
 import com.reactnativenavigation.parse.Component;
19
 import com.reactnativenavigation.parse.Component;
26
 import com.reactnativenavigation.parse.params.Fraction;
27
 import com.reactnativenavigation.parse.params.Fraction;
27
 import com.reactnativenavigation.parse.params.Number;
28
 import com.reactnativenavigation.parse.params.Number;
28
 import com.reactnativenavigation.parse.params.Text;
29
 import com.reactnativenavigation.parse.params.Text;
30
+import com.reactnativenavigation.presentation.RenderChecker;
29
 import com.reactnativenavigation.presentation.StackPresenter;
31
 import com.reactnativenavigation.presentation.StackPresenter;
30
 import com.reactnativenavigation.utils.TitleBarHelper;
32
 import com.reactnativenavigation.utils.TitleBarHelper;
31
 import com.reactnativenavigation.views.titlebar.TitleBarReactView;
33
 import com.reactnativenavigation.views.titlebar.TitleBarReactView;
36
 import org.mockito.ArgumentCaptor;
38
 import org.mockito.ArgumentCaptor;
37
 
39
 
38
 import java.util.ArrayList;
40
 import java.util.ArrayList;
41
+import java.util.Collection;
39
 import java.util.Collections;
42
 import java.util.Collections;
40
 import java.util.List;
43
 import java.util.List;
41
 
44
 
59
     private TestComponentLayout otherChild;
62
     private TestComponentLayout otherChild;
60
     private Activity activity;
63
     private Activity activity;
61
     private TopBar topBar;
64
     private TopBar topBar;
65
+    private RenderChecker renderChecker;
62
 
66
 
63
     private Button textBtn1 = TitleBarHelper.textualButton("btn1");
67
     private Button textBtn1 = TitleBarHelper.textualButton("btn1");
64
     private Button textBtn2 = TitleBarHelper.textualButton("btn2");
68
     private Button textBtn2 = TitleBarHelper.textualButton("btn2");
82
                 return spy(super.create(activity, componentId, componentName));
86
                 return spy(super.create(activity, componentId, componentName));
83
             }
87
             }
84
         };
88
         };
85
-        uut = spy(new StackPresenter(activity, titleViewCreator, new TopBarButtonCreatorMock(), ImageLoaderMock.mock(), new Options()));
89
+        renderChecker = spy(new RenderChecker());
90
+        uut = spy(new StackPresenter(activity, titleViewCreator, new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), ImageLoaderMock.mock(), renderChecker, new Options()));
86
         topBar = mockTopBar();
91
         topBar = mockTopBar();
87
         uut.bindView(topBar);
92
         uut.bindView(topBar);
88
         uut.setButtonOnClickListener(onClickListener);
93
         uut.setButtonOnClickListener(onClickListener);
90
         otherChild = new TestComponentLayout(activity, new TestReactView(activity));
95
         otherChild = new TestComponentLayout(activity, new TestReactView(activity));
91
     }
96
     }
92
 
97
 
98
+    @Test
99
+    public void isRendered() {
100
+        Options o1 = new Options();
101
+        o1.topBar.title.component = component(Alignment.Default);
102
+        o1.topBar.background.component = component(Alignment.Default);
103
+        o1.topBar.buttons.right = new ArrayList(Collections.singletonList(componentBtn1));
104
+        uut.applyChildOptions(o1, child);
105
+
106
+        uut.isRendered(child);
107
+        ArgumentCaptor<Collection<ViewController>> controllers = ArgumentCaptor.forClass(Collection.class);
108
+        verify(renderChecker).areRendered(controllers.capture());
109
+        ArrayList<ViewController> items = new ArrayList(controllers.getValue());
110
+        assertThat(items.contains(uut.getComponentButtons(child).get(0))).isTrue();
111
+        assertThat(items.contains(uut.getTitleComponents().get(child))).isTrue();
112
+        assertThat(items.contains(uut.getBackgroundComponents().get(child))).isTrue();
113
+        assertThat(items.size()).isEqualTo(3);
114
+    }
115
+
93
     @Test
116
     @Test
94
     public void applyChildOptions_setTitleComponent() {
117
     public void applyChildOptions_setTitleComponent() {
95
         Options options = new Options();
118
         Options options = new Options();

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

30
 import static org.mockito.Mockito.times;
30
 import static org.mockito.Mockito.times;
31
 import static org.mockito.Mockito.verify;
31
 import static org.mockito.Mockito.verify;
32
 
32
 
33
+@SuppressWarnings("MagicNumber")
33
 public class TopBarButtonControllerTest extends BaseTest {
34
 public class TopBarButtonControllerTest extends BaseTest {
34
 
35
 
35
     private TitleBarButtonController uut;
36
     private TitleBarButtonController uut;
43
         final Activity activity = newActivity();
44
         final Activity activity = newActivity();
44
 
45
 
45
         TopBarButtonCreatorMock buttonCreatorMock = new TopBarButtonCreatorMock();
46
         TopBarButtonCreatorMock buttonCreatorMock = new TopBarButtonCreatorMock();
46
-        stackController = spy(
47
-                TestUtils.newStackController(activity)
48
-                        .setTopBarButtonCreator(buttonCreatorMock)
49
-                        .build()
50
-        );
47
+        stackController = spy(TestUtils.newStackController(activity).build());
51
         stackController.getView().layout(0, 0, 1080, 1920);
48
         stackController.getView().layout(0, 0, 1080, 1920);
52
         stackController.getTopBar().layout(0, 0, 1080, 200);
49
         stackController.getTopBar().layout(0, 0, 1080, 200);
53
         getTitleBar().layout(0, 0, 1080, 200);
50
         getTitleBar().layout(0, 0, 1080, 200);

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

5
 import android.support.annotation.NonNull;
5
 import android.support.annotation.NonNull;
6
 
6
 
7
 import com.reactnativenavigation.BaseTest;
7
 import com.reactnativenavigation.BaseTest;
8
-import com.reactnativenavigation.mocks.TopBarBackgroundViewCreatorMock;
9
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
10
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
8
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
11
 import com.reactnativenavigation.views.StackLayout;
9
 import com.reactnativenavigation.views.StackLayout;
12
 import com.reactnativenavigation.views.titlebar.TitleBar;
10
 import com.reactnativenavigation.views.titlebar.TitleBar;
34
         uut = new TopBarController() {
32
         uut = new TopBarController() {
35
             @NonNull
33
             @NonNull
36
             @Override
34
             @Override
37
-            protected TopBar createTopBar(Context context, TopBarBackgroundViewController topBarBackgroundViewController, StackLayout stackLayout) {
38
-                return new TopBar(context, topBarBackgroundViewController, stackLayout) {
35
+            protected TopBar createTopBar(Context context, StackLayout stackLayout) {
36
+                return new TopBar(context, stackLayout) {
39
                     @Override
37
                     @Override
40
                     protected TitleBar createTitleBar(Context context) {
38
                     protected TitleBar createTitleBar(Context context) {
41
                         titleBar[0] = spy(super.createTitleBar(context));
39
                         titleBar[0] = spy(super.createTitleBar(context));
45
             }
43
             }
46
         };
44
         };
47
         Activity activity = newActivity();
45
         Activity activity = newActivity();
48
-        uut.createView(activity, new TopBarBackgroundViewController(activity, new TopBarBackgroundViewCreatorMock()), Mockito.mock(StackLayout.class));
46
+        uut.createView(activity, Mockito.mock(StackLayout.class));
49
         uut.clear();
47
         uut.clear();
50
         verify(titleBar[0], times(1)).clear();
48
         verify(titleBar[0], times(1)).clear();
51
     }
49
     }

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

34
 import com.reactnativenavigation.views.BottomTabs;
34
 import com.reactnativenavigation.views.BottomTabs;
35
 
35
 
36
 import org.junit.Test;
36
 import org.junit.Test;
37
+import org.mockito.ArgumentCaptor;
37
 import org.mockito.Mockito;
38
 import org.mockito.Mockito;
38
 import org.robolectric.android.controller.ActivityController;
39
 import org.robolectric.android.controller.ActivityController;
39
 import org.robolectric.annotation.Config;
40
 import org.robolectric.annotation.Config;
44
 
45
 
45
 import static org.assertj.core.api.Java6Assertions.assertThat;
46
 import static org.assertj.core.api.Java6Assertions.assertThat;
46
 import static org.mockito.ArgumentMatchers.any;
47
 import static org.mockito.ArgumentMatchers.any;
48
+import static org.mockito.ArgumentMatchers.eq;
47
 import static org.mockito.Mockito.spy;
49
 import static org.mockito.Mockito.spy;
48
 import static org.mockito.Mockito.times;
50
 import static org.mockito.Mockito.times;
49
 import static org.mockito.Mockito.verify;
51
 import static org.mockito.Mockito.verify;
131
     public void setRoot_delegatesToRootPresenter() {
133
     public void setRoot_delegatesToRootPresenter() {
132
         CommandListenerAdapter listener = new CommandListenerAdapter();
134
         CommandListenerAdapter listener = new CommandListenerAdapter();
133
         uut.setRoot(child1, listener);
135
         uut.setRoot(child1, listener);
134
-        verify(rootPresenter).setRoot(child1, uut.getDefaultOptions(), listener);
136
+        ArgumentCaptor<CommandListenerAdapter> captor = ArgumentCaptor.forClass(CommandListenerAdapter.class);
137
+        verify(rootPresenter).setRoot(eq(child1), eq(uut.getDefaultOptions()), captor.capture());
138
+        assertThat(captor.getValue().getListener()).isEqualTo(listener);
135
     }
139
     }
136
 
140
 
137
     @Test
141
     @Test
138
     public void setRoot_clearsSplashLayout() {
142
     public void setRoot_clearsSplashLayout() {
139
-        disableModalAnimations(child1);
140
-
141
         FrameLayout content = activity.findViewById(android.R.id.content);
143
         FrameLayout content = activity.findViewById(android.R.id.content);
142
         assertThat(content.getChildCount()).isEqualTo(4); // 3 frame layouts and the default splash layout
144
         assertThat(content.getChildCount()).isEqualTo(4); // 3 frame layouts and the default splash layout
143
 
145
 

+ 30
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/navigator/RootPresenterTest.java View File

10
 import com.reactnativenavigation.mocks.SimpleViewController;
10
 import com.reactnativenavigation.mocks.SimpleViewController;
11
 import com.reactnativenavigation.parse.AnimationOptions;
11
 import com.reactnativenavigation.parse.AnimationOptions;
12
 import com.reactnativenavigation.parse.Options;
12
 import com.reactnativenavigation.parse.Options;
13
+import com.reactnativenavigation.parse.params.Bool;
13
 import com.reactnativenavigation.utils.CommandListenerAdapter;
14
 import com.reactnativenavigation.utils.CommandListenerAdapter;
14
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
15
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
15
 import com.reactnativenavigation.viewcontrollers.ViewController;
16
 import com.reactnativenavigation.viewcontrollers.ViewController;
16
 import com.reactnativenavigation.views.element.ElementTransitionManager;
17
 import com.reactnativenavigation.views.element.ElementTransitionManager;
17
 
18
 
18
 import org.junit.Test;
19
 import org.junit.Test;
20
+import org.mockito.ArgumentCaptor;
19
 
21
 
20
 import static org.assertj.core.api.Java6Assertions.assertThat;
22
 import static org.assertj.core.api.Java6Assertions.assertThat;
21
 import static org.mockito.ArgumentMatchers.any;
23
 import static org.mockito.ArgumentMatchers.any;
85
         verify(listener).onSuccess(spy.getId());
87
         verify(listener).onSuccess(spy.getId());
86
     }
88
     }
87
 
89
 
90
+    @Test
91
+    public void setRoot_waitForRenderIsSet() {
92
+        root.options.animations.setRoot.waitForRender = new Bool(true);
93
+        ViewController spy = spy(root);
94
+
95
+        uut.setRoot(spy, defaultOptions, new CommandListenerAdapter());
96
+
97
+        ArgumentCaptor<Bool> captor = ArgumentCaptor.forClass(Bool.class);
98
+        verify(spy).setWaitForRender(captor.capture());
99
+        assertThat(captor.getValue().get()).isTrue();
100
+    }
101
+
102
+    @Test
103
+    public void setRoot_waitForRender() {
104
+        root.options.animations.setRoot.waitForRender = new Bool(true);
105
+
106
+        ViewController spy = spy(root);
107
+        CommandListenerAdapter listener = spy(new CommandListenerAdapter());
108
+        uut.setRoot(spy, defaultOptions, listener);
109
+        verify(spy).setOnAppearedListener(any());
110
+        assertThat(spy.getView().getAlpha()).isZero();
111
+        verifyZeroInteractions(listener);
112
+
113
+        spy.onViewAppeared();
114
+        assertThat(spy.getView().getAlpha()).isOne();
115
+        verify(listener).onSuccess(spy.getId());
116
+    }
117
+
88
     @NonNull
118
     @NonNull
89
     private NavigationAnimator createAnimator(Activity activity) {
119
     private NavigationAnimator createAnimator(Activity activity) {
90
         return new NavigationAnimator(activity, mock(ElementTransitionManager.class)) {
120
         return new NavigationAnimator(activity, mock(ElementTransitionManager.class)) {

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

20
 import com.reactnativenavigation.parse.Options;
20
 import com.reactnativenavigation.parse.Options;
21
 import com.reactnativenavigation.parse.params.Bool;
21
 import com.reactnativenavigation.parse.params.Bool;
22
 import com.reactnativenavigation.parse.params.Text;
22
 import com.reactnativenavigation.parse.params.Text;
23
+import com.reactnativenavigation.presentation.RenderChecker;
23
 import com.reactnativenavigation.presentation.StackPresenter;
24
 import com.reactnativenavigation.presentation.StackPresenter;
24
 import com.reactnativenavigation.utils.CommandListenerAdapter;
25
 import com.reactnativenavigation.utils.CommandListenerAdapter;
25
 import com.reactnativenavigation.utils.ImageLoader;
26
 import com.reactnativenavigation.utils.ImageLoader;
30
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
31
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
31
 import com.reactnativenavigation.viewcontrollers.ParentController;
32
 import com.reactnativenavigation.viewcontrollers.ParentController;
32
 import com.reactnativenavigation.viewcontrollers.ViewController;
33
 import com.reactnativenavigation.viewcontrollers.ViewController;
33
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
34
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
34
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
35
 import com.reactnativenavigation.views.Component;
35
 import com.reactnativenavigation.views.Component;
36
 import com.reactnativenavigation.views.ReactComponent;
36
 import com.reactnativenavigation.views.ReactComponent;
74
     private TopBarController topBarController;
74
     private TopBarController topBarController;
75
     private StackPresenter presenter;
75
     private StackPresenter presenter;
76
     private BackButtonHelper backButtonHelper;
76
     private BackButtonHelper backButtonHelper;
77
+    private RenderChecker renderChecker;
77
 
78
 
78
     @Override
79
     @Override
79
     public void beforeEach() {
80
     public void beforeEach() {
82
         activity = newActivity();
83
         activity = newActivity();
83
         animator = spy(new NavigationAnimator(activity, Mockito.mock(ElementTransitionManager.class)));
84
         animator = spy(new NavigationAnimator(activity, Mockito.mock(ElementTransitionManager.class)));
84
         childRegistry = new ChildControllersRegistry();
85
         childRegistry = new ChildControllersRegistry();
85
-        presenter = spy(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarButtonCreatorMock(), ImageLoaderMock.mock(), new Options()));
86
+        renderChecker = spy(new RenderChecker());
87
+        presenter = spy(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), ImageLoaderMock.mock(), renderChecker, new Options()));
86
         child1 = spy(new SimpleViewController(activity, childRegistry, "child1", new Options()));
88
         child1 = spy(new SimpleViewController(activity, childRegistry, "child1", new Options()));
87
         child2 = spy(new SimpleViewController(activity, childRegistry, "child2", new Options()));
89
         child2 = spy(new SimpleViewController(activity, childRegistry, "child2", new Options()));
88
         child3 = spy(new SimpleViewController(activity, childRegistry, "child3", new Options()));
90
         child3 = spy(new SimpleViewController(activity, childRegistry, "child3", new Options()));
129
         assertContainsOnlyId(child1.getId(), child2.getId(), child3.getId());
131
         assertContainsOnlyId(child1.getId(), child2.getId(), child3.getId());
130
     }
132
     }
131
 
133
 
134
+    @Test
135
+    public void isRendered_falseIfStackIsEmpty() {
136
+        assertThat(uut.size()).isZero();
137
+        assertThat(uut.isRendered()).isFalse();
138
+    }
139
+
140
+    @Test
141
+    public void isRendered() {
142
+        disablePushAnimation(child1);
143
+
144
+        uut.push(child1, new CommandListenerAdapter());
145
+        verify(presenter).isRendered((Component) child1.getView());
146
+        verify(renderChecker).areRendered(any());
147
+        assertThat(uut.isRendered()).isTrue();
148
+
149
+        child1.setWaitForRender(new Bool(true));
150
+        assertThat(uut.isRendered()).isFalse();
151
+
152
+        child1.getView().addView(new View(activity));
153
+        assertThat(uut.isRendered()).isTrue();
154
+
155
+        Mockito.when(presenter.isRendered((Component) child1.getView())).then(ignored -> false);
156
+        assertThat(uut.isRendered()).isFalse();
157
+    }
158
+
132
     @Test
159
     @Test
133
     public void push() {
160
     public void push() {
134
         assertThat(uut.isEmpty()).isTrue();
161
         assertThat(uut.isEmpty()).isTrue();
285
     @Test
312
     @Test
286
     public void pop_layoutHandlesChildWillDisappear() {
313
     public void pop_layoutHandlesChildWillDisappear() {
287
         uut = new StackControllerBuilder(activity)
314
         uut = new StackControllerBuilder(activity)
288
-                        .setTopBarButtonCreator(new TopBarButtonCreatorMock())
289
-                        .setTopBarBackgroundViewController(new TopBarBackgroundViewController(activity, new TopBarBackgroundViewCreatorMock()))
290
                         .setTopBarController(new TopBarController())
315
                         .setTopBarController(new TopBarController())
291
                         .setId("uut")
316
                         .setId("uut")
292
                         .setInitialOptions(new Options())
317
                         .setInitialOptions(new Options())
293
-                        .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarButtonCreatorMock(), new ImageLoader(), new Options()))
318
+                        .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), new TopBarButtonCreatorMock(), new ImageLoader(), new RenderChecker(), new Options()))
294
                         .build();
319
                         .build();
295
         uut.ensureViewIsCreated();
320
         uut.ensureViewIsCreated();
296
         uut.push(child1, new CommandListenerAdapter());
321
         uut.push(child1, new CommandListenerAdapter());
854
     @Test
879
     @Test
855
     public void mergeChildOptions_updatesViewWithNewOptions() {
880
     public void mergeChildOptions_updatesViewWithNewOptions() {
856
         StackController uut = spy(new StackControllerBuilder(activity)
881
         StackController uut = spy(new StackControllerBuilder(activity)
857
-                        .setTopBarButtonCreator(new TopBarButtonCreatorMock())
858
-                        .setTopBarBackgroundViewController(new TopBarBackgroundViewController(activity, new TopBarBackgroundViewCreatorMock()))
859
                         .setTopBarController(new TopBarController())
882
                         .setTopBarController(new TopBarController())
860
                         .setId("stack")
883
                         .setId("stack")
861
                         .setInitialOptions(new Options())
884
                         .setInitialOptions(new Options())
862
-                        .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarButtonCreatorMock(), new ImageLoader(), new Options()))
885
+                        .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), new TitleBarReactViewCreatorMock(), ImageLoaderMock.mock(), new RenderChecker(), Options.EMPTY))
863
                         .build());
886
                         .build());
864
         Options optionsToMerge = new Options();
887
         Options optionsToMerge = new Options();
865
         Component component = mock(Component.class);
888
         Component component = mock(Component.class);
871
     @Test
894
     @Test
872
     public void mergeChildOptions_updatesParentControllerWithNewOptions() {
895
     public void mergeChildOptions_updatesParentControllerWithNewOptions() {
873
         StackController uut = new StackControllerBuilder(activity)
896
         StackController uut = new StackControllerBuilder(activity)
874
-                        .setTopBarButtonCreator(new TopBarButtonCreatorMock())
875
-                        .setTopBarBackgroundViewController(new TopBarBackgroundViewController(activity, new TopBarBackgroundViewCreatorMock()))
876
                         .setTopBarController(new TopBarController())
897
                         .setTopBarController(new TopBarController())
877
                         .setId("stack")
898
                         .setId("stack")
878
                         .setInitialOptions(new Options())
899
                         .setInitialOptions(new Options())
879
-                        .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarButtonCreatorMock(), new ImageLoader(), new Options()))
900
+                        .setStackPresenter(new StackPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), new TitleBarReactViewCreatorMock(), ImageLoaderMock.mock(), new RenderChecker(), Options.EMPTY))
880
                         .build();
901
                         .build();
881
         ParentController parentController = Mockito.mock(ParentController.class);
902
         ParentController parentController = Mockito.mock(ParentController.class);
882
         uut.setParentController(parentController);
903
         uut.setParentController(parentController);
1006
     private void createTopBarController() {
1027
     private void createTopBarController() {
1007
         topBarController = spy(new TopBarController() {
1028
         topBarController = spy(new TopBarController() {
1008
             @Override
1029
             @Override
1009
-            protected TopBar createTopBar(Context context, TopBarBackgroundViewController topBarBackgroundViewController, StackLayout stackLayout) {
1010
-                TopBar spy = spy(super.createTopBar(context, topBarBackgroundViewController, stackLayout));
1030
+            protected TopBar createTopBar(Context context, StackLayout stackLayout) {
1031
+                TopBar spy = spy(super.createTopBar(context, stackLayout));
1011
                 spy.layout(0, 0, 1000, UiUtils.getTopBarHeight(activity));
1032
                 spy.layout(0, 0, 1000, UiUtils.getTopBarHeight(activity));
1012
                 return spy;
1033
                 return spy;
1013
             }
1034
             }

+ 0
- 70
lib/android/app/src/test/java/com/reactnativenavigation/views/TopBarBackgroundComponentTest.java View File

1
-package com.reactnativenavigation.views;
2
-
3
-import android.app.Activity;
4
-import android.view.View;
5
-import android.view.ViewGroup;
6
-
7
-import com.reactnativenavigation.BaseTest;
8
-import com.reactnativenavigation.R;
9
-import com.reactnativenavigation.mocks.TopBarBackgroundViewCreatorMock;
10
-import com.reactnativenavigation.parse.Component;
11
-import com.reactnativenavigation.parse.params.Text;
12
-import com.reactnativenavigation.utils.ViewUtils;
13
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
14
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
15
-import com.reactnativenavigation.views.topbar.TopBar;
16
-import com.reactnativenavigation.views.topbar.TopBarBackgroundView;
17
-
18
-import org.junit.Test;
19
-
20
-import static org.assertj.core.api.Java6Assertions.assertThat;
21
-import static org.mockito.Mockito.spy;
22
-import static org.mockito.Mockito.times;
23
-import static org.mockito.Mockito.verify;
24
-
25
-public class TopBarBackgroundComponentTest extends BaseTest {
26
-    private TopBar uut;
27
-    private TopBarBackgroundViewController topBarBackgroundViewController;
28
-
29
-    @SuppressWarnings("Convert2Lambda")
30
-    @Override
31
-    public void beforeEach() {
32
-        Activity activity = newActivity();
33
-        topBarBackgroundViewController = spy(new TopBarBackgroundViewController(activity, new TopBarBackgroundViewCreatorMock()));
34
-        StackLayout parent = new StackLayout(activity, topBarBackgroundViewController, new TopBarController(), null);
35
-        uut = new TopBar(activity, topBarBackgroundViewController, parent);
36
-        parent.addView(uut);
37
-    }
38
-
39
-    @Test
40
-    public void setBackgroundComponent() {
41
-        uut.getLayoutParams().height = 100;
42
-        Component component = new Component();
43
-        component.name = new Text("someComponent");
44
-        component.componentId = new Text("id");
45
-        uut.setBackgroundComponent(component);
46
-        TopBarBackgroundView background = (TopBarBackgroundView) ViewUtils.findChildrenByClassRecursive(uut, TopBarBackgroundView.class).get(0);
47
-        assertThat(background).isNotNull();
48
-        assertThat(background.getLayoutParams().width).isEqualTo(ViewGroup.LayoutParams.MATCH_PARENT);
49
-        assertThat(background.getLayoutParams().height).isEqualTo(ViewGroup.LayoutParams.MATCH_PARENT);
50
-    }
51
-
52
-    @Test
53
-    public void setBackgroundComponent_doesNotSetIfNoComponentIsDefined() {
54
-        Component component = new Component();
55
-        component.name = new Text("someComponent");
56
-        component.componentId = new Text("id");
57
-        uut.setBackgroundComponent(component);
58
-        assertThat((View) uut.findViewById(R.id.topBarBackgroundComponent)).isNull();
59
-    }
60
-
61
-    @Test
62
-    public void clear_componentIsDestroyed() {
63
-        Component component = new Component();
64
-        component.name = new Text("someComponent");
65
-        component.componentId = new Text("id");
66
-        uut.setBackgroundComponent(component);
67
-        uut.clear();
68
-        verify(topBarBackgroundViewController, times(1)).destroy();
69
-    }
70
-}

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

4
 
4
 
5
 import com.reactnativenavigation.BaseTest;
5
 import com.reactnativenavigation.BaseTest;
6
 import com.reactnativenavigation.anim.TopBarAnimator;
6
 import com.reactnativenavigation.anim.TopBarAnimator;
7
-import com.reactnativenavigation.mocks.TopBarBackgroundViewCreatorMock;
8
 import com.reactnativenavigation.parse.AnimationOptions;
7
 import com.reactnativenavigation.parse.AnimationOptions;
9
-import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
10
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
8
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
11
 import com.reactnativenavigation.views.topbar.TopBar;
9
 import com.reactnativenavigation.views.topbar.TopBar;
12
 
10
 
28
     @Override
26
     @Override
29
     public void beforeEach() {
27
     public void beforeEach() {
30
         Activity activity = newActivity();
28
         Activity activity = newActivity();
31
-        TopBarBackgroundViewController topBarBackgroundViewController = new TopBarBackgroundViewController(activity, new TopBarBackgroundViewCreatorMock());
32
-        StackLayout parent = new StackLayout(activity, topBarBackgroundViewController, new TopBarController(), null);
33
-        uut = new TopBar(activity, topBarBackgroundViewController, parent);
29
+        StackLayout parent = new StackLayout(activity, new TopBarController(), null);
30
+        uut = new TopBar(activity, parent);
34
         animator = spy(new TopBarAnimator(uut));
31
         animator = spy(new TopBarAnimator(uut));
35
         uut.setAnimator(animator);
32
         uut.setAnimator(animator);
36
         parent.addView(uut);
33
         parent.addView(uut);