Browse Source

Implement statusBar drawBehind and visible option

Guy Carmeli 6 years ago
parent
commit
126f31c2fb
20 changed files with 228 additions and 50 deletions
  1. 2
    0
      lib/android/app/src/main/java/com/reactnativenavigation/NavigationActivity.java
  2. 11
    0
      lib/android/app/src/main/java/com/reactnativenavigation/parse/StatusBarOptions.java
  3. 31
    5
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java
  4. 13
    4
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ChildController.java
  5. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ComponentViewController.java
  6. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/Navigator.java
  7. 6
    2
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ParentController.java
  8. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/SideMenuController.java
  9. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java
  10. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java
  11. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java
  12. 19
    8
      lib/android/app/src/test/java/com/reactnativenavigation/BaseTest.java
  13. 9
    5
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleViewController.java
  14. 32
    0
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/NavigationActivityTest.java
  15. 24
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ParentControllerTest.java
  16. 5
    0
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ViewControllerTest.java
  17. 22
    1
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllerTest.java
  18. 5
    0
      playground/src/screens/ModalScreen.js
  19. 4
    0
      playground/src/screens/PushedScreen.js
  20. 33
    18
      playground/src/screens/WelcomeScreen.js

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

@@ -5,6 +5,7 @@ import android.os.Bundle;
5 5
 import android.support.annotation.Nullable;
6 6
 import android.support.v7.app.AppCompatActivity;
7 7
 import android.view.KeyEvent;
8
+import android.view.View;
8 9
 
9 10
 import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
10 11
 import com.reactnativenavigation.presentation.OverlayManager;
@@ -22,6 +23,7 @@ public class NavigationActivity extends AppCompatActivity implements DefaultHard
22 23
         navigator = new Navigator(this, new ChildControllersRegistry(), new OverlayManager());
23 24
         getReactGateway().onActivityCreated(this);
24 25
         getReactGateway().addReloadListener(navigator);
26
+        navigator.getView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
25 27
         setContentView(navigator.getView());
26 28
     }
27 29
 

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

@@ -2,8 +2,11 @@ package com.reactnativenavigation.parse;
2 2
 
3 3
 import android.support.annotation.Nullable;
4 4
 
5
+import com.reactnativenavigation.parse.params.Bool;
5 6
 import com.reactnativenavigation.parse.params.Color;
7
+import com.reactnativenavigation.parse.params.NullBool;
6 8
 import com.reactnativenavigation.parse.params.NullColor;
9
+import com.reactnativenavigation.parse.parsers.BoolParser;
7 10
 import com.reactnativenavigation.parse.parsers.ColorParser;
8 11
 
9 12
 import org.json.JSONObject;
@@ -41,20 +44,28 @@ public class StatusBarOptions {
41 44
 
42 45
         result.backgroundColor = ColorParser.parse(json, "backgroundColor");
43 46
         result.textColorScheme = TextColorScheme.fromString(json.optString("style"));
47
+        result.visible = BoolParser.parse(json, "visible");
48
+        result.drawBehind = BoolParser.parse(json, "drawBehind");
44 49
 
45 50
         return result;
46 51
     }
47 52
 
48 53
     public Color backgroundColor = new NullColor();
49 54
     public TextColorScheme textColorScheme = TextColorScheme.None;
55
+    public Bool visible = new NullBool();
56
+    public Bool drawBehind = new NullBool();
50 57
 
51 58
     public void mergeWith(StatusBarOptions other) {
52 59
         if (other.backgroundColor.hasValue()) backgroundColor = other.backgroundColor;
53 60
         if (other.textColorScheme.hasValue()) textColorScheme = other.textColorScheme;
61
+        if (other.visible.hasValue()) visible = other.visible;
62
+        if (other.drawBehind.hasValue()) drawBehind = other.drawBehind;
54 63
     }
55 64
 
56 65
     public void mergeWithDefault(StatusBarOptions defaultOptions) {
57 66
         if (!backgroundColor.hasValue()) backgroundColor = defaultOptions.backgroundColor;
58 67
         if (!textColorScheme.hasValue()) textColorScheme = defaultOptions.textColorScheme;
68
+        if (!visible.hasValue()) visible = defaultOptions.visible;
69
+        if (!drawBehind.hasValue()) drawBehind = defaultOptions.drawBehind;
59 70
     }
60 71
 }

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

@@ -4,11 +4,14 @@ import android.app.Activity;
4 4
 import android.graphics.Color;
5 5
 import android.os.Build;
6 6
 import android.view.View;
7
+import android.view.ViewGroup;
7 8
 
8 9
 import com.reactnativenavigation.parse.Options;
9 10
 import com.reactnativenavigation.parse.OrientationOptions;
10 11
 import com.reactnativenavigation.parse.StatusBarOptions;
11 12
 import com.reactnativenavigation.parse.StatusBarOptions.TextColorScheme;
13
+import com.reactnativenavigation.parse.params.Bool;
14
+import com.reactnativenavigation.utils.UiUtils;
12 15
 
13 16
 @SuppressWarnings("FieldCanBeLocal")
14 17
 public class OptionsPresenter {
@@ -22,7 +25,11 @@ public class OptionsPresenter {
22 25
     public void present(View view, Options options) {
23 26
         applyOrientation(options.orientationOptions);
24 27
         applyViewOptions(view, options);
25
-        applyStatusBarOptions(options.statusBar);
28
+        applyStatusBarOptions(view, options.statusBar);
29
+    }
30
+
31
+    public void applyRootOptions(View view, Options options) {
32
+        setDrawBehindStatusBar(view, options.statusBar);
26 33
     }
27 34
 
28 35
     private void applyOrientation(OrientationOptions options) {
@@ -35,15 +42,28 @@ public class OptionsPresenter {
35 42
         }
36 43
     }
37 44
 
38
-    public void onViewBroughtToFront(Options options) {
39
-        applyStatusBarOptions(options.statusBar);
45
+    public void onViewBroughtToFront(View view, Options options) {
46
+        applyStatusBarOptions(view, options.statusBar);
47
+    }
48
+
49
+    private void applyStatusBarOptions(View view, StatusBarOptions statusBar) {
50
+        setStatusBarBackgroundColor(statusBar);
51
+        setTextColorScheme(statusBar.textColorScheme);
52
+        setStatusBarVisible(view, statusBar.visible, statusBar.drawBehind);
40 53
     }
41 54
 
42
-    private void applyStatusBarOptions(StatusBarOptions statusBar) {
55
+    private void setStatusBarVisible(View view, Bool visible, Bool drawBehind) {
56
+        if (visible.isFalse()) {
57
+            view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_FULLSCREEN);
58
+        } else if (drawBehind.isTrue()) {
59
+            view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
60
+        }
61
+    }
62
+
63
+    private void setStatusBarBackgroundColor(StatusBarOptions statusBar) {
43 64
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
44 65
             activity.getWindow().setStatusBarColor(statusBar.backgroundColor.get(Color.BLACK));
45 66
         }
46
-        setTextColorScheme(statusBar.textColorScheme);
47 67
     }
48 68
 
49 69
     private void setTextColorScheme(TextColorScheme scheme) {
@@ -64,4 +84,10 @@ public class OptionsPresenter {
64 84
         flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
65 85
         view.setSystemUiVisibility(flags);
66 86
     }
87
+
88
+    private void setDrawBehindStatusBar(View view, StatusBarOptions statusBar) {
89
+        ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).topMargin = statusBar.drawBehind.isFalseOrUndefined() ?
90
+                UiUtils.getStatusBarHeight(activity) :
91
+                0;
92
+    }
67 93
 }

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

@@ -7,16 +7,16 @@ import com.reactnativenavigation.parse.Options;
7 7
 import com.reactnativenavigation.presentation.OptionsPresenter;
8 8
 
9 9
 public abstract class ChildController<T extends ViewGroup> extends ViewController<T>  {
10
-    private final OptionsPresenter presenter;
10
+    final OptionsPresenter presenter;
11 11
     private final ChildControllersRegistry childRegistry;
12 12
 
13 13
     public ChildControllersRegistry getChildRegistry() {
14 14
         return childRegistry;
15 15
     }
16 16
 
17
-    public ChildController(Activity activity, ChildControllersRegistry childRegistry, String id, Options initialOptions) {
17
+    public ChildController(Activity activity, ChildControllersRegistry childRegistry, String id, OptionsPresenter presenter, Options initialOptions) {
18 18
         super(activity, id, initialOptions);
19
-        presenter = new OptionsPresenter(activity);
19
+        this.presenter = presenter;
20 20
         this.childRegistry = childRegistry;
21 21
     }
22 22
 
@@ -33,12 +33,21 @@ public abstract class ChildController<T extends ViewGroup> extends ViewControlle
33 33
     }
34 34
 
35 35
     public void onViewBroughtToFront() {
36
-        presenter.onViewBroughtToFront(options);
36
+        presenter.onViewBroughtToFront(getView(), options);
37 37
     }
38 38
 
39 39
     @Override
40 40
     public void applyOptions(Options options) {
41 41
         super.applyOptions(options);
42 42
         presenter.present(getView(), options);
43
+        if (isRoot()) {
44
+            presenter.applyRootOptions(getView(), options);
45
+        }
46
+    }
47
+
48
+    protected boolean isRoot() {
49
+        return getParentController() == null &&
50
+               !(this instanceof Navigator) &&
51
+                getView().getParent() != null;
43 52
     }
44 53
 }

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

@@ -4,6 +4,7 @@ import android.app.Activity;
4 4
 import android.support.annotation.NonNull;
5 5
 
6 6
 import com.reactnativenavigation.parse.Options;
7
+import com.reactnativenavigation.presentation.OptionsPresenter;
7 8
 import com.reactnativenavigation.views.ComponentLayout;
8 9
 import com.reactnativenavigation.views.ReactComponent;
9 10
 
@@ -19,7 +20,7 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
19 20
                                    final String componentName,
20 21
                                    final ReactViewCreator viewCreator,
21 22
                                    final Options initialOptions) {
22
-        super(activity, childRegistry, id, initialOptions);
23
+        super(activity, childRegistry, id, new OptionsPresenter(activity), initialOptions);
23 24
         this.componentName = componentName;
24 25
         this.viewCreator = viewCreator;
25 26
     }

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

@@ -11,6 +11,7 @@ import android.widget.FrameLayout;
11 11
 import com.reactnativenavigation.anim.ModalAnimator;
12 12
 import com.reactnativenavigation.anim.NavigationAnimator;
13 13
 import com.reactnativenavigation.parse.Options;
14
+import com.reactnativenavigation.presentation.OptionsPresenter;
14 15
 import com.reactnativenavigation.presentation.OverlayManager;
15 16
 import com.reactnativenavigation.react.JsDevReloadHandler;
16 17
 import com.reactnativenavigation.utils.CommandListener;
@@ -41,7 +42,7 @@ public class Navigator extends ParentController implements JsDevReloadHandler.Re
41 42
     }
42 43
 
43 44
     public Navigator(final Activity activity, ChildControllersRegistry childRegistry, OverlayManager overlayManager) {
44
-        super(activity, childRegistry,"navigator" + CompatUtils.generateViewId(), new Options());
45
+        super(activity, childRegistry,"navigator" + CompatUtils.generateViewId(), new OptionsPresenter(activity), new Options());
45 46
         modalStack = new ModalStack(new ModalPresenter(new ModalAnimator(activity)));
46 47
         this.overlayManager = overlayManager;
47 48
     }

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

@@ -8,14 +8,15 @@ import android.support.v4.view.ViewPager;
8 8
 import android.view.ViewGroup;
9 9
 
10 10
 import com.reactnativenavigation.parse.Options;
11
+import com.reactnativenavigation.presentation.OptionsPresenter;
11 12
 import com.reactnativenavigation.views.Component;
12 13
 
13 14
 import java.util.Collection;
14 15
 
15 16
 public abstract class ParentController<T extends ViewGroup> extends ChildController {
16 17
 
17
-	public ParentController(Activity activity, ChildControllersRegistry childRegistry, String id, Options initialOptions) {
18
-		super(activity, childRegistry, id, initialOptions);
18
+	public ParentController(Activity activity, ChildControllersRegistry childRegistry, String id, OptionsPresenter presenter, Options initialOptions) {
19
+		super(activity, childRegistry, id, presenter, initialOptions);
19 20
 	}
20 21
 
21 22
 	@NonNull
@@ -59,6 +60,9 @@ public abstract class ParentController<T extends ViewGroup> extends ChildControl
59 60
     @CallSuper
60 61
     public void applyChildOptions(Options options, Component child) {
61 62
         this.options = this.options.mergeWith(options);
63
+        if (isRoot()) {
64
+            presenter.applyRootOptions(getView(), options);
65
+        }
62 66
     }
63 67
 
64 68
     @CallSuper

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

@@ -8,6 +8,7 @@ import android.view.Gravity;
8 8
 import android.view.View;
9 9
 
10 10
 import com.reactnativenavigation.parse.Options;
11
+import com.reactnativenavigation.presentation.OptionsPresenter;
11 12
 import com.reactnativenavigation.presentation.SideMenuOptionsPresenter;
12 13
 import com.reactnativenavigation.views.Component;
13 14
 
@@ -23,7 +24,7 @@ public class SideMenuController extends ParentController<DrawerLayout> {
23 24
 	private ViewController rightController;
24 25
 
25 26
 	public SideMenuController(Activity activity, ChildControllersRegistry childRegistry, String id, Options initialOptions) {
26
-		super(activity, childRegistry, id, initialOptions);
27
+		super(activity, childRegistry, id, new OptionsPresenter(activity), initialOptions);
27 28
 	}
28 29
 
29 30
 	@NonNull

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

@@ -8,6 +8,7 @@ import android.support.v4.view.ViewPager;
8 8
 import com.reactnativenavigation.anim.NavigationAnimator;
9 9
 import com.reactnativenavigation.parse.Options;
10 10
 import com.reactnativenavigation.parse.params.Button;
11
+import com.reactnativenavigation.presentation.OptionsPresenter;
11 12
 import com.reactnativenavigation.react.Constants;
12 13
 import com.reactnativenavigation.utils.CommandListener;
13 14
 import com.reactnativenavigation.utils.CommandListenerAdapter;
@@ -36,7 +37,7 @@ public class StackController extends ParentController<StackLayout> {
36 37
     private TopBarController topBarController;
37 38
 
38 39
     public StackController(Activity activity, ChildControllersRegistry childRegistry, ReactViewCreator topBarButtonCreator, TitleBarReactViewCreator titleBarReactViewCreator, TopBarBackgroundViewController topBarBackgroundViewController, TopBarController topBarController, NavigationAnimator animator, String id, Options initialOptions) {
39
-        super(activity, childRegistry, id, initialOptions);
40
+        super(activity, childRegistry, id, new OptionsPresenter(activity), initialOptions);
40 41
         this.topBarController = topBarController;
41 42
         this.topBarButtonCreator = topBarButtonCreator;
42 43
         this.titleBarReactViewCreator = titleBarReactViewCreator;

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

@@ -12,6 +12,7 @@ import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
12 12
 import com.reactnativenavigation.parse.BottomTabOptions;
13 13
 import com.reactnativenavigation.parse.Options;
14 14
 import com.reactnativenavigation.presentation.BottomTabsOptionsPresenter;
15
+import com.reactnativenavigation.presentation.OptionsPresenter;
15 16
 import com.reactnativenavigation.react.EventEmitter;
16 17
 import com.reactnativenavigation.utils.CommandListener;
17 18
 import com.reactnativenavigation.utils.ImageLoader;
@@ -40,7 +41,7 @@ public class BottomTabsController extends ParentController implements AHBottomNa
40 41
     private final BottomTabFinder bottomTabFinder = new BottomTabFinder();
41 42
 
42 43
     public BottomTabsController(Activity activity, List<ViewController> tabs, ChildControllersRegistry childRegistry, EventEmitter eventEmitter, ImageLoader imageLoader, String id, Options initialOptions) {
43
-		super(activity, childRegistry, id, initialOptions);
44
+		super(activity, childRegistry, id, new OptionsPresenter(activity), initialOptions);
44 45
         this.tabs = tabs;
45 46
         this.eventEmitter = eventEmitter;
46 47
         this.imageLoader = imageLoader;

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

@@ -5,6 +5,7 @@ import android.support.annotation.NonNull;
5 5
 import android.view.View;
6 6
 
7 7
 import com.reactnativenavigation.parse.Options;
8
+import com.reactnativenavigation.presentation.OptionsPresenter;
8 9
 import com.reactnativenavigation.utils.Task;
9 10
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
10 11
 import com.reactnativenavigation.viewcontrollers.ParentController;
@@ -23,7 +24,7 @@ public class TopTabsController extends ParentController<TopTabsViewPager> {
23 24
     private TopTabsLayoutCreator viewCreator;
24 25
 
25 26
     public TopTabsController(Activity activity, ChildControllersRegistry childRegistry, String id, List<ViewController> tabs, TopTabsLayoutCreator viewCreator, Options options) {
26
-        super(activity, childRegistry, id, options);
27
+        super(activity, childRegistry, id, new OptionsPresenter(activity), options);
27 28
         this.viewCreator = viewCreator;
28 29
         this.tabs = tabs;
29 30
         for (ViewController tab : tabs) {

+ 19
- 8
lib/android/app/src/test/java/com/reactnativenavigation/BaseTest.java View File

@@ -1,20 +1,25 @@
1 1
 package com.reactnativenavigation;
2 2
 
3
-import android.app.*;
4
-import android.support.v7.app.*;
5
-import android.view.*;
3
+import android.app.Activity;
4
+import android.content.Context;
5
+import android.support.v7.app.AppCompatActivity;
6
+import android.view.View;
7
+import android.view.ViewGroup;
8
+import android.widget.FrameLayout;
6 9
 
7 10
 import com.reactnativenavigation.parse.params.Bool;
8 11
 import com.reactnativenavigation.utils.ViewUtils;
9 12
 import com.reactnativenavigation.viewcontrollers.ViewController;
10 13
 
11
-import org.junit.*;
12
-import org.junit.runner.*;
13
-import org.robolectric.*;
14
+import org.junit.After;
15
+import org.junit.Before;
16
+import org.junit.runner.RunWith;
17
+import org.robolectric.Robolectric;
18
+import org.robolectric.RobolectricTestRunner;
14 19
 import org.robolectric.android.controller.ActivityController;
15
-import org.robolectric.annotation.*;
20
+import org.robolectric.annotation.Config;
16 21
 
17
-import static org.assertj.core.api.Java6Assertions.*;
22
+import static org.assertj.core.api.Java6Assertions.assertThat;
18 23
 
19 24
 @RunWith(RobolectricTestRunner.class)
20 25
 @Config(sdk = 27, application = TestApplication.class)
@@ -74,4 +79,10 @@ public abstract class BaseTest {
74 79
     protected void dispatchOnGlobalLayout(View view) {
75 80
         view.getViewTreeObserver().dispatchOnGlobalLayout();
76 81
     }
82
+
83
+    protected void addToParent(Context context, ViewController... controllers) {
84
+        for (ViewController controller : controllers) {
85
+            new FrameLayout(context).addView(controller.getView());
86
+        }
87
+    }
77 88
 }

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

@@ -9,22 +9,26 @@ import android.widget.FrameLayout;
9 9
 
10 10
 import com.reactnativenavigation.interfaces.ScrollEventListener;
11 11
 import com.reactnativenavigation.parse.Options;
12
+import com.reactnativenavigation.presentation.OptionsPresenter;
12 13
 import com.reactnativenavigation.viewcontrollers.ChildController;
13 14
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
14
-import com.reactnativenavigation.views.Component;
15 15
 import com.reactnativenavigation.views.ReactComponent;
16 16
 import com.reactnativenavigation.views.topbar.TopBar;
17 17
 
18
-public class SimpleViewController extends ChildController<FrameLayout> {
18
+public class SimpleViewController extends ChildController<SimpleViewController.SimpleView> {
19 19
 
20 20
     private SimpleView simpleView;
21 21
 
22 22
     public SimpleViewController(Activity activity, ChildControllersRegistry childRegistry, String id, Options options) {
23
-        super(activity, childRegistry, id, options);
23
+        this(activity, childRegistry, id, new OptionsPresenter(activity), options);
24
+    }
25
+
26
+    public SimpleViewController(Activity activity, ChildControllersRegistry childRegistry, String id, OptionsPresenter presenter, Options options) {
27
+        super(activity, childRegistry, id, presenter, options);
24 28
     }
25 29
 
26 30
     @Override
27
-    protected FrameLayout createView() {
31
+    protected SimpleView createView() {
28 32
         simpleView = new SimpleView(getActivity());
29 33
         return simpleView;
30 34
     }
@@ -41,7 +45,7 @@ public class SimpleViewController extends ChildController<FrameLayout> {
41 45
 
42 46
     @Override
43 47
     public void mergeOptions(Options options) {
44
-        applyOnParentController(parentController -> parentController.mergeChildOptions(options, (Component) view));
48
+        applyOnParentController(parentController -> parentController.mergeChildOptions(options, view));
45 49
         super.mergeOptions(options);
46 50
     }
47 51
 

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

@@ -0,0 +1,32 @@
1
+package com.reactnativenavigation.viewcontrollers;
2
+
3
+import android.view.View;
4
+
5
+import com.reactnativenavigation.BaseTest;
6
+import com.reactnativenavigation.NavigationActivity;
7
+import com.reactnativenavigation.TestActivity;
8
+
9
+import org.junit.Test;
10
+import org.robolectric.android.controller.ActivityController;
11
+
12
+import static org.assertj.core.api.Java6Assertions.assertThat;
13
+
14
+public class NavigationActivityTest extends BaseTest {
15
+    private ActivityController<? extends NavigationActivity> controller;
16
+    private NavigationActivity uut;
17
+
18
+    @Override
19
+    public void beforeEach() {
20
+        controller = newActivityController(TestActivity.class);
21
+        uut = controller.get();
22
+    }
23
+
24
+    @Test
25
+    public void onCreate_setSystemUiVisibility() {
26
+        controller.setup();
27
+        assertThat(uut
28
+                .getNavigator()
29
+                .getView()
30
+                .getSystemUiVisibility()).isEqualTo(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
31
+    }
32
+}

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

@@ -12,6 +12,7 @@ import com.reactnativenavigation.mocks.TopBarBackgroundViewCreatorMock;
12 12
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
13 13
 import com.reactnativenavigation.parse.Options;
14 14
 import com.reactnativenavigation.parse.params.Text;
15
+import com.reactnativenavigation.presentation.OptionsPresenter;
15 16
 import com.reactnativenavigation.utils.CommandListenerAdapter;
16 17
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
17 18
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
@@ -19,6 +20,7 @@ import com.reactnativenavigation.views.ReactComponent;
19 20
 
20 21
 import org.junit.Test;
21 22
 import org.mockito.ArgumentCaptor;
23
+import org.mockito.Mockito;
22 24
 
23 25
 import java.util.ArrayList;
24 26
 import java.util.Collection;
@@ -36,6 +38,7 @@ public class ParentControllerTest extends BaseTest {
36 38
     private ChildControllersRegistry childRegistry;
37 39
     private List<ViewController> children;
38 40
     private ParentController uut;
41
+    private OptionsPresenter presenter;
39 42
 
40 43
     @Override
41 44
     public void beforeEach() {
@@ -45,7 +48,8 @@ public class ParentControllerTest extends BaseTest {
45 48
         children = new ArrayList<>();
46 49
         Options initialOptions = new Options();
47 50
         initialOptions.topBar.title.text = new Text(INITIAL_TITLE);
48
-        uut = spy(new ParentController(activity, childRegistry, "uut", initialOptions) {
51
+        presenter = spy(new OptionsPresenter(activity));
52
+        uut = spy(new ParentController(activity, childRegistry, "uut", presenter, initialOptions) {
49 53
 
50 54
             @NonNull
51 55
             @Override
@@ -156,6 +160,25 @@ public class ParentControllerTest extends BaseTest {
156 160
         assertThat(uut.initialOptions.topBar.title.text.get()).isEqualTo(INITIAL_TITLE);
157 161
     }
158 162
 
163
+    @Test
164
+    public void applyChildOptions_appliesRootOptionsIfRoot() {
165
+        addToParent(activity, uut);
166
+
167
+        Options options = new Options();
168
+        SimpleViewController child1 = spy(new SimpleViewController(activity, childRegistry, "child1", options));
169
+        uut.applyChildOptions(options, child1.getView());
170
+        verify(presenter, times(1)).applyRootOptions(uut.getView(), options);
171
+    }
172
+
173
+    @Test
174
+    public void applyChildOptions_doesNotApplyRootOptionsIfHasParent() {
175
+        Options options = new Options();
176
+        uut.setParentController(Mockito.mock(ParentController.class));
177
+        SimpleViewController child1 = spy(new SimpleViewController(activity, childRegistry, "child1", options));
178
+        uut.applyChildOptions(options, child1.getView());
179
+        verify(presenter, times(0)).applyRootOptions(uut.getView(), options);
180
+    }
181
+
159 182
     private StackController createStack() {
160 183
         return new StackControllerBuilder(activity)
161 184
                 .setTopBarButtonCreator(new TopBarButtonCreatorMock())

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

@@ -18,6 +18,7 @@ import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
18 18
 
19 19
 import org.assertj.android.api.Assertions;
20 20
 import org.junit.Test;
21
+import org.mockito.Mockito;
21 22
 import org.robolectric.Shadows;
22 23
 
23 24
 import java.lang.reflect.Field;
@@ -40,6 +41,7 @@ public class ViewControllerTest extends BaseTest {
40 41
         activity = newActivity();
41 42
         childRegistry = new ChildControllersRegistry();
42 43
         uut = new SimpleViewController(activity, childRegistry, "uut", new Options());
44
+        uut.setParentController(Mockito.mock(ParentController.class));
43 45
     }
44 46
 
45 47
     @Test
@@ -71,6 +73,9 @@ public class ViewControllerTest extends BaseTest {
71 73
 
72 74
     @Test
73 75
     public void holdsAReferenceToStackControllerOrNull() {
76
+        //noinspection ConstantConditions
77
+        uut.setParentController(null);
78
+
74 79
         assertThat(uut.getParentController()).isNull();
75 80
         StackController nav = new StackControllerBuilder(activity)
76 81
                 .setTopBarButtonCreator(new TopBarButtonCreatorMock())

+ 22
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllerTest.java View File

@@ -3,10 +3,13 @@ package com.reactnativenavigation.viewcontrollers.child;
3 3
 import com.reactnativenavigation.BaseTest;
4 4
 import com.reactnativenavigation.mocks.SimpleViewController;
5 5
 import com.reactnativenavigation.parse.Options;
6
+import com.reactnativenavigation.presentation.OptionsPresenter;
6 7
 import com.reactnativenavigation.viewcontrollers.ChildController;
7 8
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
9
+import com.reactnativenavigation.viewcontrollers.ParentController;
8 10
 
9 11
 import org.junit.Test;
12
+import org.mockito.Mockito;
10 13
 
11 14
 import static org.mockito.Mockito.spy;
12 15
 import static org.mockito.Mockito.times;
@@ -16,11 +19,13 @@ public class ChildControllerTest extends BaseTest {
16 19
 
17 20
     private ChildController uut;
18 21
     private ChildControllersRegistry childRegistry;
22
+    private OptionsPresenter presenter;
19 23
 
20 24
     @Override
21 25
     public void beforeEach() {
22 26
         childRegistry = spy(new ChildControllersRegistry());
23
-        uut = new SimpleViewController(newActivity(), childRegistry, "childId", new Options());
27
+        presenter = Mockito.mock(OptionsPresenter.class);
28
+        uut = new SimpleViewController(newActivity(), childRegistry, "childId", presenter, new Options());
24 29
     }
25 30
 
26 31
     @Test
@@ -36,4 +41,20 @@ public class ChildControllerTest extends BaseTest {
36 41
         uut.onViewDisappear();
37 42
         verify(childRegistry, times(1)).onViewDisappear(uut);
38 43
     }
44
+
45
+    @Test
46
+    public void applyOptions_applyRootOptionsIfRoot() {
47
+        addToParent(newActivity(), uut);
48
+        Options options = new Options();
49
+        uut.applyOptions(options);
50
+        verify(presenter, times(1)).applyRootOptions(uut.getView(), options);
51
+    }
52
+
53
+    @Test
54
+    public void applyOptions_doesNotApplyRootOptionsIfHasParent() {
55
+        Options options = new Options();
56
+        uut.setParentController(Mockito.mock(ParentController.class));
57
+        uut.applyOptions(options);
58
+        verify(presenter, times(0)).applyRootOptions(uut.getView(), options);
59
+    }
39 60
 }

+ 5
- 0
playground/src/screens/ModalScreen.js View File

@@ -11,6 +11,11 @@ const testIDs = require('../testIDs');
11 11
 class ModalScreen extends Component {
12 12
   static get options() {
13 13
     return {
14
+      statusBar: {
15
+        visible: false,
16
+        drawBehind: true,
17
+        backgroundColor: 'transparent'
18
+      },
14 19
       orientation: ['portrait']
15 20
     };
16 21
   }

+ 4
- 0
playground/src/screens/PushedScreen.js View File

@@ -11,6 +11,10 @@ const testIDs = require('../testIDs');
11 11
 class PushedScreen extends Component {
12 12
   static get options() {
13 13
     return {
14
+      _statusBar: {
15
+        visible: false,
16
+        drawBehind: true
17
+      },
14 18
       topBar: {
15 19
         testID: testIDs.TOP_BAR_ELEMENT
16 20
       }

+ 33
- 18
playground/src/screens/WelcomeScreen.js View File

@@ -9,6 +9,11 @@ const { Navigation } = require('react-native-navigation');
9 9
 class WelcomeScreen extends Component {
10 10
   static get options() {
11 11
     return {
12
+      _statusBar: {
13
+        backgroundColor: 'transparent',
14
+        style: 'dark',
15
+        drawBehind: true
16
+      },
12 17
       topBar: {
13 18
         title: {
14 19
           largeTitle: false,
@@ -23,23 +28,27 @@ class WelcomeScreen extends Component {
23 28
 
24 29
   render() {
25 30
     return (
26
-      <View style={styles.root} key={'root'}>
27
-        <Text testID={testIDs.WELCOME_SCREEN_HEADER} style={styles.h1}>{`React Native Navigation!`}</Text>
28
-        <Button title='Switch to tab based app' testID={testIDs.TAB_BASED_APP_BUTTON} onPress={this.onClickSwitchToTabs} />
29
-        <Button title='Switch to app with side menus' testID={testIDs.TAB_BASED_APP_SIDE_BUTTON} onPress={this.onClickSwitchToSideMenus} />
30
-        <Button title='Push Lifecycle Screen' testID={testIDs.PUSH_LIFECYCLE_BUTTON} onPress={this.onClickLifecycleScreen} />
31
-        <Button title='Static Lifecycle Events' testID={testIDs.PUSH_STATIC_LIFECYCLE_BUTTON} onPress={this.onClickShowStaticLifecycleOverlay} />
32
-        <Button title='Push' testID={testIDs.PUSH_BUTTON} onPress={this.onClickPush} />
33
-        <Button title='Push Options Screen' testID={testIDs.PUSH_OPTIONS_BUTTON} onPress={this.onClickPushOptionsScreen} />
34
-        <Button title='Push External Component' testID={testIDs.PUSH_EXTERNAL_COMPONENT_BUTTON} onPress={this.onClickPushExternalComponent} />
35
-        {Platform.OS === 'android' && <Button title='Push Top Tabs screen' testID={testIDs.PUSH_TOP_TABS_BUTTON} onPress={this.onClickPushTopTabsScreen} />}
36
-        {Platform.OS === 'android' && <Button title='Back Handler' testID={testIDs.BACK_HANDLER_BUTTON} onPress={this.onClickBackHandler} />}
37
-        <Button title='Show Modal' testID={testIDs.SHOW_MODAL_BUTTON} onPress={this.onClickShowModal} />
38
-        <Button title='Show Redbox' testID={testIDs.SHOW_REDBOX_BUTTON} onPress={this.onClickShowRedbox} />
39
-        <Button title='Orientation' testID={testIDs.ORIENTATION_BUTTON} onPress={this.onClickPushOrientationMenuScreen} />
40
-        <Button title='Provided Id' testID={testIDs.PROVIDED_ID} onPress={this.onClickProvidedId} />
41
-        <Button title='Complex Layout' testID={testIDs.COMPLEX_LAYOUT_BUTTON} onPress={this.onClickComplexLayout} />
42
-        <Text style={styles.footer}>{`this.props.componentId = ${this.props.componentId}`}</Text>
31
+      <View style={styles.bar}>
32
+        <View style={{ width: 2, height: 2, borderRadius: 1, backgroundColor: 'red', alignSelf: 'center' }} />
33
+        <View style={styles.root} key={'root'}>
34
+          <Text testID={testIDs.WELCOME_SCREEN_HEADER} style={styles.h1}>{`React Native Navigation!`}</Text>
35
+          <Button title='Switch to tab based app' testID={testIDs.TAB_BASED_APP_BUTTON} onPress={this.onClickSwitchToTabs} />
36
+          <Button title='Switch to app with side menus' testID={testIDs.TAB_BASED_APP_SIDE_BUTTON} onPress={this.onClickSwitchToSideMenus} />
37
+          <Button title='Push Lifecycle Screen' testID={testIDs.PUSH_LIFECYCLE_BUTTON} onPress={this.onClickLifecycleScreen} />
38
+          <Button title='Static Lifecycle Events' testID={testIDs.PUSH_STATIC_LIFECYCLE_BUTTON} onPress={this.onClickShowStaticLifecycleOverlay} />
39
+          <Button title='Push' testID={testIDs.PUSH_BUTTON} onPress={this.onClickPush} />
40
+          <Button title='Push Options Screen' testID={testIDs.PUSH_OPTIONS_BUTTON} onPress={this.onClickPushOptionsScreen} />
41
+          <Button title='Push External Component' testID={testIDs.PUSH_EXTERNAL_COMPONENT_BUTTON} onPress={this.onClickPushExternalComponent} />
42
+          {Platform.OS === 'android' && <Button title='Push Top Tabs screen' testID={testIDs.PUSH_TOP_TABS_BUTTON} onPress={this.onClickPushTopTabsScreen} />}
43
+          {Platform.OS === 'android' && <Button title='Back Handler' testID={testIDs.BACK_HANDLER_BUTTON} onPress={this.onClickBackHandler} />}
44
+          <Button title='Show Modal' testID={testIDs.SHOW_MODAL_BUTTON} onPress={this.onClickShowModal} />
45
+          <Button title='Show Redbox' testID={testIDs.SHOW_REDBOX_BUTTON} onPress={this.onClickShowRedbox} />
46
+          <Button title='Orientation' testID={testIDs.ORIENTATION_BUTTON} onPress={this.onClickPushOrientationMenuScreen} />
47
+          <Button title='Provided Id' testID={testIDs.PROVIDED_ID} onPress={this.onClickProvidedId} />
48
+          <Button title='Complex Layout' testID={testIDs.COMPLEX_LAYOUT_BUTTON} onPress={this.onClickComplexLayout} />
49
+          <Text style={styles.footer}>{`this.props.componentId = ${this.props.componentId}`}</Text>
50
+        </View>
51
+        <View style={{ width: 2, height: 2, borderRadius: 1, backgroundColor: 'red', alignSelf: 'center' }} />
43 52
       </View>
44 53
     );
45 54
   }
@@ -447,7 +456,13 @@ const styles = {
447 456
     flexGrow: 1,
448 457
     justifyContent: 'center',
449 458
     alignItems: 'center',
450
-    backgroundColor: 'white'
459
+    backgroundColor: '#e8e8e8',
460
+  },
461
+  bar: {
462
+    flex: 1,
463
+    flexDirection: 'column',
464
+    backgroundColor: '#e8e8e8',
465
+    justifyContent: 'space-between'
451 466
   },
452 467
   h1: {
453 468
     fontSize: 24,