Browse Source

V2 topbar (#1996)

* animation fix

* fix tests

* hide toolbar

* default values

* default values

* tmp commit

* tests

* animated hide

* animated hode improve

* fix topbar

* readme

* lifecycle WIP

* lifecycle alert delay hack

* test fixes

* move topbar to container

* fix tests

* refactor

* refactor WIP

* refactor fix tests

* nav options fallback to parse

* WIP

* topbar background fix
Roman Kozlov 6 years ago
parent
commit
26f36b0ba7
21 changed files with 415 additions and 129 deletions
  1. 1
    1
      README.md
  2. 108
    1
      lib/android/app/src/main/java/com/reactnativenavigation/anim/StackAnimator.java
  3. 3
    1
      lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java
  4. 45
    11
      lib/android/app/src/main/java/com/reactnativenavigation/parse/NavigationOptions.java
  5. 45
    8
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java
  6. 2
    0
      lib/android/app/src/main/java/com/reactnativenavigation/react/NavigationModule.java
  7. 21
    4
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ContainerViewController.java
  8. 2
    0
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/Navigator.java
  9. 10
    32
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java
  10. 12
    2
      lib/android/app/src/main/java/com/reactnativenavigation/views/TopBar.java
  11. 65
    0
      lib/android/app/src/main/java/com/reactnativenavigation/views/TopbarContainerView.java
  12. 23
    0
      lib/android/app/src/main/java/com/reactnativenavigation/views/TopbarContainerViewCreator.java
  13. 2
    1
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleContainerViewController.java
  14. 7
    0
      lib/android/app/src/test/java/com/reactnativenavigation/mocks/TestContainerView.java
  15. 3
    0
      lib/android/app/src/test/java/com/reactnativenavigation/parse/NavigationOptionsTest.java
  16. 0
    15
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/NavigatorTest.java
  17. 39
    26
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsApplyingTest.java
  18. 1
    0
      lib/ios/RNNNavigationOptions.h
  19. 17
    20
      lib/ios/RNNNavigationOptions.m
  20. 5
    5
      playground/src/containers/LifecycleScreen.js
  21. 4
    2
      playground/src/containers/OptionsScreen.js

+ 1
- 1
README.md View File

@@ -75,7 +75,7 @@ Note:  v1 properties with names beginning with 'navBar' are replaced in v2 with
75 75
 | topBarTextFontFamily  |  ✅     |      ✅     |     ✅        | Wix |
76 76
 | topBarBackgroundColor |  ✅     |  ✅       |     ✅         | Wix|
77 77
 | topBarButtonColor     |  ✅     |    ✅      |     [Contribute](/docs/docs/CONTRIBUTING.md)        | Wix|
78
-| topBarHidden          |   ✅    |   ✅      |     [Contribute](/docs/docs/CONTRIBUTING.md)        | Wix|
78
+| topBarHidden          |   ✅    |   ✅      |             | Wix|
79 79
 | topBarHideOnScroll    |  ✅     |  ✅    |     [Contribute](/docs/docs/CONTRIBUTING.md)        | Wix|
80 80
 | topBarTranslucent     |  ✅     |   ✅     |     [Contribute](/docs/docs/CONTRIBUTING.md)        | Wix|
81 81
 | topBarTransparent     | ✅      |   WIP @bogobogo     |     [Contribute](/docs/docs/CONTRIBUTING.md)        |

+ 108
- 1
lib/android/app/src/main/java/com/reactnativenavigation/anim/StackAnimator.java View File

@@ -3,14 +3,22 @@ package com.reactnativenavigation.anim;
3 3
 import android.animation.Animator;
4 4
 import android.animation.AnimatorSet;
5 5
 import android.animation.ObjectAnimator;
6
+import android.animation.ValueAnimator;
6 7
 import android.app.Activity;
7 8
 import android.content.Context;
8 9
 import android.support.annotation.Nullable;
9 10
 import android.util.DisplayMetrics;
11
+import android.util.Log;
10 12
 import android.view.View;
13
+import android.view.ViewGroup;
11 14
 import android.view.WindowManager;
12 15
 import android.view.animation.AccelerateInterpolator;
13 16
 import android.view.animation.DecelerateInterpolator;
17
+import android.widget.FrameLayout;
18
+import android.widget.LinearLayout;
19
+import android.widget.RelativeLayout;
20
+
21
+import com.reactnativenavigation.views.TopBar;
14 22
 
15 23
 @SuppressWarnings("ResourceType")
16 24
 public class StackAnimator {
@@ -20,7 +28,7 @@ public class StackAnimator {
20 28
 	}
21 29
 
22 30
 	private static final int DURATION = 300;
23
-	private static final int START_DELAY = 100;
31
+	private static final int DURATION_TOPBAR = 300;
24 32
 	private static final DecelerateInterpolator DECELERATE_INTERPOLATOR = new DecelerateInterpolator();
25 33
 	private static final AccelerateInterpolator ACCELERATE_INTERPOLATOR = new AccelerateInterpolator();
26 34
 	private float translationY;
@@ -109,5 +117,104 @@ public class StackAnimator {
109 117
 		return metrics.heightPixels;
110 118
 	}
111 119
 
120
+	public void animateShowTopBar(final TopBar topBar, final View container) {
121
+		ValueAnimator containerHeightAnim = ValueAnimator.ofInt(container.getMeasuredHeight(), container.getMeasuredHeight() - topBar.getMeasuredHeight());
122
+		containerHeightAnim.setInterpolator(DECELERATE_INTERPOLATOR);
123
+		containerHeightAnim.setDuration(DURATION_TOPBAR);
124
+		containerHeightAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
125
+			@Override
126
+			public void onAnimationUpdate(ValueAnimator valueAnimator) {
127
+				int val = (Integer) valueAnimator.getAnimatedValue();
128
+				LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) container.getLayoutParams();
129
+				layoutParams.height = val;
130
+				container.setLayoutParams(layoutParams);
131
+			}
132
+		});
133
+		ObjectAnimator containerTransitionAnim = ObjectAnimator.ofFloat(container, View.TRANSLATION_Y, -1 * topBar.getMeasuredHeight(), 0);
134
+		containerTransitionAnim.setInterpolator(DECELERATE_INTERPOLATOR);
135
+		containerTransitionAnim.setDuration(DURATION_TOPBAR);
136
+
137
+		ObjectAnimator topbarAnim = ObjectAnimator.ofFloat(topBar, View.TRANSLATION_Y, -1 * topBar.getHeight(), 0);
138
+		topbarAnim.setInterpolator(DECELERATE_INTERPOLATOR);
139
+		topbarAnim.setDuration(DURATION_TOPBAR);
140
+
141
+		AnimatorSet set = new AnimatorSet();
142
+		set.addListener(new Animator.AnimatorListener() {
143
+			@Override
144
+			public void onAnimationStart(Animator animation) {
145
+				topBar.setVisibility(View.VISIBLE);
146
+			}
147
+
148
+			@Override
149
+			public void onAnimationEnd(Animator animation) {
150
+				LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) container.getLayoutParams();
151
+				layoutParams.height = LinearLayout.LayoutParams.MATCH_PARENT;
152
+				container.setLayoutParams(layoutParams);
153
+			}
154
+
155
+			@Override
156
+			public void onAnimationCancel(Animator animation) {
157
+
158
+			}
159
+
160
+			@Override
161
+			public void onAnimationRepeat(Animator animation) {
162
+
163
+			}
164
+		});
165
+		set.playTogether(containerHeightAnim, containerTransitionAnim, topbarAnim);
166
+		set.start();
167
+	}
168
+
169
+	public void animateHideTopBar(final TopBar topBar, final View container) {
170
+		ValueAnimator containerHeightAnim = ValueAnimator.ofInt(container.getMeasuredHeight(), container.getMeasuredHeight() + topBar.getMeasuredHeight());
171
+		containerHeightAnim.setInterpolator(ACCELERATE_INTERPOLATOR);
172
+		containerHeightAnim.setDuration(DURATION_TOPBAR);
173
+		containerHeightAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
174
+			@Override
175
+			public void onAnimationUpdate(ValueAnimator valueAnimator) {
176
+				int val = (Integer) valueAnimator.getAnimatedValue();
177
+				LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) container.getLayoutParams();
178
+				layoutParams.height = val;
179
+				container.setLayoutParams(layoutParams);
180
+			}
181
+		});
182
+		ObjectAnimator containerTransitionAnim = ObjectAnimator.ofFloat(container, View.TRANSLATION_Y, 0, -1 * topBar.getMeasuredHeight());
183
+		containerTransitionAnim.setInterpolator(ACCELERATE_INTERPOLATOR);
184
+		containerTransitionAnim.setDuration(DURATION_TOPBAR);
185
+
186
+		ObjectAnimator topbarAnim = ObjectAnimator.ofFloat(topBar, View.TRANSLATION_Y, 0, -1 * topBar.getMeasuredHeight());
187
+		topbarAnim.setInterpolator(ACCELERATE_INTERPOLATOR);
188
+		topbarAnim.setDuration(DURATION_TOPBAR);
189
+
190
+		AnimatorSet set = new AnimatorSet();
191
+		set.addListener(new Animator.AnimatorListener() {
192
+			@Override
193
+			public void onAnimationStart(Animator animation) {
194
+			}
195
+
196
+			@Override
197
+			public void onAnimationEnd(Animator animation) {
198
+				LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) container.getLayoutParams();
199
+				layoutParams.height = LinearLayout.LayoutParams.MATCH_PARENT;
200
+				container.setLayoutParams(layoutParams);
201
+				container.setTranslationY(0);
202
+
203
+				topBar.setVisibility(View.GONE);
204
+				topBar.setTranslationY(0);
205
+			}
206
+
207
+			@Override
208
+			public void onAnimationCancel(Animator animation) {
209
+
210
+			}
211
+
212
+			@Override
213
+			public void onAnimationRepeat(Animator animation) {
112 214
 
215
+			}
216
+		});
217
+		set.playTogether(containerHeightAnim, containerTransitionAnim, topbarAnim);
218
+		set.start();
219
+	}
113 220
 }

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

@@ -9,6 +9,7 @@ import com.reactnativenavigation.viewcontrollers.ContainerViewController;
9 9
 import com.reactnativenavigation.viewcontrollers.SideMenuController;
10 10
 import com.reactnativenavigation.viewcontrollers.StackController;
11 11
 import com.reactnativenavigation.viewcontrollers.ViewController;
12
+import com.reactnativenavigation.views.TopbarContainerViewCreator;
12 13
 
13 14
 import java.util.ArrayList;
14 15
 import java.util.List;
@@ -81,7 +82,8 @@ public class LayoutFactory {
81 82
 		String id = node.id;
82 83
 		String name = node.data.optString("name");
83 84
 		NavigationOptions navigationOptions = NavigationOptions.parse(node.data.optJSONObject("navigationOptions"));
84
-		return new ContainerViewController(activity, id, name, new ReactContainerViewCreator(reactInstanceManager), navigationOptions);
85
+		return new ContainerViewController(activity, id, name,
86
+				new TopbarContainerViewCreator(new ReactContainerViewCreator(reactInstanceManager)), navigationOptions);
85 87
 	}
86 88
 
87 89
 	private ViewController createContainerStack(LayoutNode node) {

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

@@ -1,5 +1,6 @@
1 1
 package com.reactnativenavigation.parse;
2 2
 
3
+import android.graphics.Color;
3 4
 import android.support.annotation.ColorInt;
4 5
 import android.support.annotation.NonNull;
5 6
 
@@ -7,32 +8,65 @@ import org.json.JSONObject;
7 8
 
8 9
 public class NavigationOptions {
9 10
 
11
+	private static final String NO_VALUE = "";
12
+	private static final int NO_INT_VALUE = Integer.MIN_VALUE;
13
+	private static final float NO_FLOAT_VALUE = Float.MIN_VALUE;
14
+	private static final int NO_COLOR_VALUE = Color.TRANSPARENT;
15
+
16
+	public enum BooleanOptions {
17
+		True,
18
+		False,
19
+		NoValue;
20
+
21
+		static BooleanOptions parse(String value) {
22
+			if (value != null && !value.equals("")) {
23
+				return Boolean.valueOf(value) ? True : False;
24
+			}
25
+			return NoValue;
26
+		}
27
+	}
28
+
10 29
 	@NonNull
11 30
 	public static NavigationOptions parse(JSONObject json) {
12 31
 		NavigationOptions result = new NavigationOptions();
13 32
 		if (json == null) return result;
14 33
 
15
-		result.title = json.optString("title");
16
-		result.topBarBackgroundColor = json.optInt("topBarBackgroundColor");
17
-		result.topBarTextColor = json.optInt("topBarTextColor");
18
-		result.topBarTextFontSize = (float) json.optDouble("topBarTextFontSize");
19
-		result.topBarTextFontFamily = json.optString("topBarTextFontFamily");
34
+		result.title = json.optString("title", NO_VALUE);
35
+		result.topBarBackgroundColor = json.optInt("topBarBackgroundColor", NO_COLOR_VALUE);
36
+		result.topBarTextColor = json.optInt("topBarTextColor", NO_INT_VALUE);
37
+		result.topBarTextFontSize = (float) json.optDouble("topBarTextFontSize", NO_FLOAT_VALUE);
38
+		result.topBarTextFontFamily = json.optString("topBarTextFontFamily", NO_VALUE);
39
+		result.topBarHidden = BooleanOptions.parse(json.optString("topBarHidden"));
40
+		result.animateTopBarHide = BooleanOptions.parse(json.optString("animateTopBarHide"));
20 41
 
21 42
 		return result;
22 43
 	}
23 44
 
24 45
 	public String title = "";
25
-	public int topBarBackgroundColor = 0;
46
+	@ColorInt
47
+	public int topBarBackgroundColor;
26 48
 	@ColorInt
27 49
 	public int topBarTextColor;
28 50
 	public float topBarTextFontSize;
29 51
 	public String topBarTextFontFamily;
52
+	public BooleanOptions topBarHidden = BooleanOptions.False;
53
+	public BooleanOptions animateTopBarHide = BooleanOptions.False;
30 54
 
31 55
 	public void mergeWith(final NavigationOptions other) {
32
-		title = other.title;
33
-		topBarBackgroundColor = other.topBarBackgroundColor;
34
-		topBarTextColor = other.topBarTextColor;
35
-		topBarTextFontSize = other.topBarTextFontSize;
36
-		topBarTextFontFamily = other.topBarTextFontFamily;
56
+		if (!NO_VALUE.equals(other.title)) title = other.title;
57
+		if (other.topBarBackgroundColor != NO_COLOR_VALUE)
58
+			topBarBackgroundColor = other.topBarBackgroundColor;
59
+		if (other.topBarTextColor != NO_INT_VALUE)
60
+			topBarTextColor = other.topBarTextColor;
61
+		if (other.topBarTextFontSize != NO_FLOAT_VALUE)
62
+			topBarTextFontSize = other.topBarTextFontSize;
63
+		if (!NO_VALUE.equals(other.topBarTextFontFamily))
64
+			topBarTextFontFamily = other.topBarTextFontFamily;
65
+		if (other.topBarHidden != BooleanOptions.NoValue) {
66
+			topBarHidden = other.topBarHidden;
67
+		}
68
+		if (other.animateTopBarHide != BooleanOptions.NoValue) {
69
+			animateTopBarHide = other.animateTopBarHide;
70
+		}
37 71
 	}
38 72
 }

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

@@ -1,29 +1,66 @@
1 1
 package com.reactnativenavigation.presentation;
2 2
 
3
+import android.util.Log;
4
+import android.view.View;
5
+
6
+import com.reactnativenavigation.anim.StackAnimator;
3 7
 import com.reactnativenavigation.parse.NavigationOptions;
4 8
 import com.reactnativenavigation.utils.TypefaceLoader;
5
-import com.reactnativenavigation.viewcontrollers.StackController;
6
-
7
-/**
8
- * Created by romanko on 9/14/17.
9
- */
9
+import com.reactnativenavigation.viewcontrollers.ContainerViewController;
10
+import com.reactnativenavigation.views.TopbarContainerView;
10 11
 
11 12
 public class OptionsPresenter {
12 13
 
13
-	private StackController controller;
14
+	private ContainerViewController controller;
15
+	private final StackAnimator animator;
14 16
 
15
-	public OptionsPresenter(StackController controller) {
17
+	public OptionsPresenter(ContainerViewController controller) {
16 18
 		this.controller = controller;
19
+		animator = new StackAnimator(controller.getActivity());
17 20
 	}
18 21
 
19 22
 	public void applyOptions(NavigationOptions options) {
20
-		if (controller != null) {
23
+		if (controller != null && controller.getTopBar() != null) {
21 24
 			controller.getTopBar().setTitle(options.title);
22 25
 			controller.getTopBar().setBackgroundColor(options.topBarBackgroundColor);
23 26
 			controller.getTopBar().setTitleTextColor(options.topBarTextColor);
24 27
 			controller.getTopBar().setTitleFontSize(options.topBarTextFontSize);
25 28
 			TypefaceLoader typefaceLoader = new TypefaceLoader();
26 29
 			controller.getTopBar().setTitleTypeface(typefaceLoader.getTypeFace(controller.getActivity(), options.topBarTextFontFamily));
30
+			applyTopbarHiddenOptions(options);
31
+		}
32
+	}
33
+
34
+	private void applyTopbarHiddenOptions(NavigationOptions options) {
35
+		if (options.topBarHidden == NavigationOptions.BooleanOptions.True) {
36
+			hideTopbar(options.animateTopBarHide);
37
+		}
38
+		if (options.topBarHidden == NavigationOptions.BooleanOptions.False) {
39
+			showTopbar(options.animateTopBarHide);
40
+		}
41
+	}
42
+
43
+	private void showTopbar(NavigationOptions.BooleanOptions animated) {
44
+		if (controller.getTopBar().getVisibility() == View.VISIBLE) {
45
+			return;
46
+		}
47
+		if (animated == NavigationOptions.BooleanOptions.True) {
48
+			TopbarContainerView topbarContainerView = (TopbarContainerView) controller.getContainerView();
49
+			animator.animateShowTopBar(controller.getTopBar(), topbarContainerView.getContainerView().asView());
50
+		} else {
51
+			controller.getTopBar().setVisibility(View.VISIBLE);
52
+		}
53
+	}
54
+
55
+	private void hideTopbar(NavigationOptions.BooleanOptions animated) {
56
+		if (controller.getTopBar().getVisibility() == View.GONE) {
57
+			return;
58
+		}
59
+		if (animated == NavigationOptions.BooleanOptions.True) {
60
+			TopbarContainerView topbarContainerView = (TopbarContainerView) controller.getContainerView();
61
+			animator.animateHideTopBar(controller.getTopBar(), topbarContainerView.getContainerView().asView());
62
+		} else {
63
+			controller.getTopBar().setVisibility(View.GONE);
27 64
 		}
28 65
 	}
29 66
 }

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

@@ -17,6 +17,8 @@ import com.reactnativenavigation.utils.UiThread;
17 17
 import com.reactnativenavigation.viewcontrollers.Navigator;
18 18
 import com.reactnativenavigation.viewcontrollers.ViewController;
19 19
 
20
+import org.json.JSONObject;
21
+
20 22
 public class NavigationModule extends ReactContextBaseJavaModule {
21 23
 	private static final String NAME = "RNNBridgeModule";
22 24
 	private final ReactInstanceManager reactInstanceManager;

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

@@ -2,10 +2,14 @@ package com.reactnativenavigation.viewcontrollers;
2 2
 
3 3
 import android.app.Activity;
4 4
 import android.support.annotation.NonNull;
5
+import android.util.Log;
5 6
 import android.view.View;
6 7
 
8
+import com.reactnativenavigation.anim.StackAnimator;
7 9
 import com.reactnativenavigation.parse.NavigationOptions;
8 10
 import com.reactnativenavigation.presentation.OptionsPresenter;
11
+import com.reactnativenavigation.views.TopBar;
12
+import com.reactnativenavigation.views.TopbarContainerView;
9 13
 
10 14
 public class ContainerViewController extends ViewController {
11 15
 
@@ -31,9 +35,11 @@ public class ContainerViewController extends ViewController {
31 35
 	private final String containerName;
32 36
 
33 37
 	private final ContainerViewCreator viewCreator;
34
-	private final NavigationOptions navigationOptions;
38
+	private NavigationOptions navigationOptions;
35 39
 	private ContainerView containerView;
36 40
 
41
+	private TopBar topBar;
42
+
37 43
 	public ContainerViewController(final Activity activity,
38 44
 								   final String id,
39 45
 								   final String containerName,
@@ -75,20 +81,31 @@ public class ContainerViewController extends ViewController {
75 81
 	@Override
76 82
 	protected View createView() {
77 83
 		containerView = viewCreator.create(getActivity(), getId(), containerName);
84
+		if (containerView instanceof TopbarContainerView) {
85
+			topBar = ((TopbarContainerView) containerView).getTopBar();
86
+		}
78 87
 		return containerView.asView();
79 88
 	}
80 89
 
81
-	public void mergeNavigationOptions(final NavigationOptions options) {
90
+	void mergeNavigationOptions(NavigationOptions options) {
82 91
 		navigationOptions.mergeWith(options);
83 92
 		applyOptions();
84 93
 	}
85 94
 
86
-	public NavigationOptions getNavigationOptions() {
95
+	NavigationOptions getNavigationOptions() {
87 96
 		return navigationOptions;
88 97
 	}
89 98
 
90 99
 	private void applyOptions() {
91
-		OptionsPresenter presenter = new OptionsPresenter(getParentStackController());
100
+		OptionsPresenter presenter = new OptionsPresenter(this);
92 101
 		presenter.applyOptions(navigationOptions);
93 102
 	}
103
+
104
+	public TopBar getTopBar() {
105
+		return topBar;
106
+	}
107
+
108
+	public ContainerView getContainerView() {
109
+		return containerView;
110
+	}
94 111
 }

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

@@ -8,6 +8,8 @@ import android.widget.FrameLayout;
8 8
 import com.reactnativenavigation.parse.NavigationOptions;
9 9
 import com.reactnativenavigation.utils.CompatUtils;
10 10
 
11
+import org.json.JSONObject;
12
+
11 13
 import java.util.Collection;
12 14
 import java.util.Collections;
13 15
 

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

@@ -1,30 +1,27 @@
1 1
 package com.reactnativenavigation.viewcontrollers;
2 2
 
3
-import android.animation.Animator;
4 3
 import android.app.Activity;
5 4
 import android.graphics.Color;
6
-import android.os.Handler;
7
-import android.os.Looper;
8 5
 import android.support.annotation.NonNull;
6
+import android.util.Log;
9 7
 import android.view.View;
10 8
 import android.view.ViewGroup;
11 9
 import android.widget.FrameLayout;
12 10
 import android.widget.LinearLayout;
11
+import android.widget.RelativeLayout;
13 12
 
14 13
 import com.reactnativenavigation.anim.StackAnimator;
15
-import com.reactnativenavigation.react.ReactContainerView;
16 14
 import com.reactnativenavigation.utils.CompatUtils;
17 15
 import com.reactnativenavigation.views.TopBar;
18 16
 
19 17
 import java.util.Collection;
20
-import java.util.Random;
18
+
19
+import static android.widget.RelativeLayout.BELOW;
21 20
 
22 21
 public class StackController extends ParentController {
23 22
 
24 23
 	private final IdStack<ViewController> stack = new IdStack<>();
25 24
 	private final StackAnimator animator;
26
-	private TopBar topBar;
27
-	private FrameLayout container;
28 25
 
29 26
 	public StackController(final Activity activity, String id) {
30 27
 		this(activity, id, new StackAnimator(activity));
@@ -41,16 +38,17 @@ public class StackController extends ParentController {
41 38
 		child.setParentStackController(this);
42 39
 		stack.push(child.getId(), child);
43 40
 		View enteringView = child.getView();
44
-		getContainer().addView(enteringView);
41
+		getView().addView(enteringView);
45 42
 
46 43
 		//TODO animatePush only when needed
47 44
 		if (previousTop != null) {
48 45
 			animator.animatePush(enteringView, new StackAnimator.StackAnimationListener() {
49 46
 				@Override
50 47
 				public void onAnimationEnd() {
51
-					getContainer().removeView(previousTop.getView());
48
+					getView().removeView(previousTop.getView());
52 49
 				}
53 50
 			});
51
+
54 52
 		}
55 53
 	}
56 54
 
@@ -66,13 +64,13 @@ public class StackController extends ParentController {
66 64
 
67 65
 		View enteringView = newTop.getView();
68 66
 		final View exitingView = poppedTop.getView();
69
-		getContainer().addView(enteringView, getContainer().getChildCount() - 1);
67
+		getView().addView(enteringView, getView().getChildCount() - 1);
70 68
 
71 69
 		//TODO animatePush only when needed
72 70
 		animator.animatePop(exitingView, new StackAnimator.StackAnimationListener() {
73 71
 			@Override
74 72
 			public void onAnimationEnd() {
75
-				getContainer().removeView(exitingView);
73
+				getView().removeView(exitingView);
76 74
 				poppedTop.destroy();
77 75
 			}
78 76
 		});
@@ -127,15 +125,7 @@ public class StackController extends ParentController {
127 125
 	@NonNull
128 126
 	@Override
129 127
 	protected ViewGroup createView() {
130
-		LinearLayout root = new LinearLayout(getActivity());
131
-		root.setOrientation(LinearLayout.VERTICAL);
132
-		topBar = new TopBar(getActivity());
133
-		topBar.setId(CompatUtils.generateViewId());
134
-		root.addView(topBar);
135
-		container = new FrameLayout(getActivity());
136
-		container.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
137
-		root.addView(container);
138
-		return root;
128
+		return new FrameLayout(getActivity());
139 129
 	}
140 130
 
141 131
 	@NonNull
@@ -143,16 +133,4 @@ public class StackController extends ParentController {
143 133
 	public Collection<ViewController> getChildControllers() {
144 134
 		return stack.values();
145 135
 	}
146
-
147
-	public TopBar getTopBar() {
148
-		ensureViewIsCreated();
149
-		return topBar;
150
-	}
151
-
152
-	private ViewGroup getContainer() {
153
-		if (container == null) {
154
-			getView();
155
-		}
156
-		return container;
157
-	}
158 136
 }

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

@@ -1,6 +1,7 @@
1 1
 package com.reactnativenavigation.views;
2 2
 
3 3
 import android.app.Activity;
4
+import android.content.Context;
4 5
 import android.graphics.Typeface;
5 6
 import android.support.annotation.ColorInt;
6 7
 import android.support.annotation.Nullable;
@@ -13,7 +14,7 @@ import android.widget.TextView;
13 14
 public class TopBar extends AppBarLayout {
14 15
 	private final Toolbar titleBar;
15 16
 
16
-	public TopBar(final Activity context) {
17
+	public TopBar(final Context context) {
17 18
 		super(context);
18 19
 		titleBar = new Toolbar(context);
19 20
 		addView(titleBar);
@@ -49,8 +50,13 @@ public class TopBar extends AppBarLayout {
49 50
 		return findTextView(titleBar);
50 51
 	}
51 52
 
53
+	@Override
54
+	public void setBackgroundColor(@ColorInt int color) {
55
+		titleBar.setBackgroundColor(color);
56
+	}
57
+
52 58
 	@Nullable
53
-	public TextView findTextView(ViewGroup root) {
59
+	private TextView findTextView(ViewGroup root) {
54 60
 		for (int i = 0; i < root.getChildCount(); i++) {
55 61
 			View view = root.getChildAt(i);
56 62
 			if (view instanceof TextView) {
@@ -62,4 +68,8 @@ public class TopBar extends AppBarLayout {
62 68
 		}
63 69
 		return null;
64 70
 	}
71
+
72
+	public Toolbar getTitleBar() {
73
+		return titleBar;
74
+	}
65 75
 }

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

@@ -0,0 +1,65 @@
1
+package com.reactnativenavigation.views;
2
+
3
+import android.content.Context;
4
+import android.view.View;
5
+import android.view.ViewGroup;
6
+import android.widget.LinearLayout;
7
+
8
+import com.reactnativenavigation.viewcontrollers.ContainerViewController;
9
+
10
+public class TopbarContainerView extends LinearLayout implements ContainerViewController.ContainerView {
11
+
12
+	private TopBar topBar;
13
+	private ContainerViewController.ContainerView containerView;
14
+
15
+	public TopbarContainerView(Context context, ContainerViewController.ContainerView containerView) {
16
+		super(context);
17
+		this.topBar = new TopBar(context);
18
+		this.containerView = containerView;
19
+
20
+		initViews();
21
+	}
22
+
23
+	private void initViews() {
24
+		setOrientation(LinearLayout.VERTICAL);
25
+		addView(topBar);
26
+		addView(containerView.asView());
27
+	}
28
+
29
+	public TopbarContainerView(Context context) {
30
+		super(context);
31
+	}
32
+
33
+	@Override
34
+	public boolean isReady() {
35
+		return containerView.isReady();
36
+	}
37
+
38
+	@Override
39
+	public View asView() {
40
+		return this;
41
+	}
42
+
43
+	@Override
44
+	public void destroy() {
45
+		containerView.destroy();
46
+	}
47
+
48
+	@Override
49
+	public void sendContainerStart() {
50
+		containerView.sendContainerStart();
51
+	}
52
+
53
+	@Override
54
+	public void sendContainerStop() {
55
+		containerView.sendContainerStop();
56
+	}
57
+
58
+	public TopBar getTopBar() {
59
+		return topBar;
60
+	}
61
+
62
+	public ContainerViewController.ContainerView getContainerView() {
63
+		return containerView;
64
+	}
65
+}

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

@@ -0,0 +1,23 @@
1
+package com.reactnativenavigation.views;
2
+
3
+import android.app.Activity;
4
+
5
+import com.reactnativenavigation.viewcontrollers.ContainerViewController;
6
+
7
+public class TopbarContainerViewCreator implements ContainerViewController.ContainerViewCreator {
8
+
9
+	private ContainerViewController.ContainerViewCreator creator;
10
+
11
+	public TopbarContainerViewCreator(ContainerViewController.ContainerViewCreator creator) {
12
+		this.creator = creator;
13
+	}
14
+
15
+	@Override
16
+	public ContainerViewController.ContainerView create(Activity activity, String containerId, String containerName) {
17
+		ContainerViewController.ContainerView containerView = creator.create(activity, containerId, containerName);
18
+
19
+		TopbarContainerView root = new TopbarContainerView(activity, containerView);
20
+		return root;
21
+
22
+	}
23
+}

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

@@ -4,9 +4,10 @@ import android.app.Activity;
4 4
 
5 5
 import com.reactnativenavigation.parse.NavigationOptions;
6 6
 import com.reactnativenavigation.viewcontrollers.ContainerViewController;
7
+import com.reactnativenavigation.views.TopbarContainerViewCreator;
7 8
 
8 9
 public class SimpleContainerViewController extends ContainerViewController {
9 10
 	public SimpleContainerViewController(final Activity activity, final String id) {
10
-		super(activity, id, "theContainerName", new TestContainerViewCreator(), new NavigationOptions());
11
+		super(activity, id, "theContainerName", new TopbarContainerViewCreator(new TestContainerViewCreator()), new NavigationOptions());
11 12
 	}
12 13
 }

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

@@ -2,12 +2,19 @@ package com.reactnativenavigation.mocks;
2 2
 
3 3
 import android.content.Context;
4 4
 import android.view.View;
5
+import android.view.ViewGroup;
5 6
 
6 7
 import com.reactnativenavigation.viewcontrollers.ContainerViewController;
8
+import com.reactnativenavigation.views.TopBar;
7 9
 
8 10
 public class TestContainerView extends View implements ContainerViewController.ContainerView {
11
+
12
+	private TopBar topBar;
13
+
9 14
 	public TestContainerView(final Context context) {
10 15
 		super(context);
16
+		topBar = new TopBar(context);
17
+
11 18
 	}
12 19
 
13 20
 	@Override

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

@@ -5,6 +5,7 @@ import com.reactnativenavigation.BaseTest;
5 5
 import org.json.JSONObject;
6 6
 import org.junit.Test;
7 7
 
8
+import static com.reactnativenavigation.parse.NavigationOptions.BooleanOptions.True;
8 9
 import static org.assertj.core.api.Java6Assertions.assertThat;
9 10
 
10 11
 public class NavigationOptionsTest extends BaseTest {
@@ -22,6 +23,7 @@ public class NavigationOptionsTest extends BaseTest {
22 23
 		json.put("topBarTextColor", 0xff123456);
23 24
 		json.put("topBarTextFontSize", 18);
24 25
 		json.put("topBarTextFontFamily", "HelveticaNeue-CondensedBold");
26
+		json.put("topBarHidden", true);
25 27
 
26 28
 		NavigationOptions result = NavigationOptions.parse(json);
27 29
 		assertThat(result.title).isEqualTo("the title");
@@ -29,6 +31,7 @@ public class NavigationOptionsTest extends BaseTest {
29 31
 		assertThat(result.topBarTextColor).isEqualTo(0xff123456);
30 32
 		assertThat(result.topBarTextFontSize).isEqualTo(18);
31 33
 		assertThat(result.topBarTextFontFamily).isEqualTo("HelveticaNeue-CondensedBold");
34
+		assertThat(result.topBarHidden).isEqualTo(True);
32 35
 	}
33 36
 
34 37
 	@Test

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

@@ -207,21 +207,6 @@ public class NavigatorTest extends BaseTest {
207 207
 		uut.setOptions("some unknown child id", new NavigationOptions());
208 208
 	}
209 209
 
210
-	@Test
211
-	public void setOptions_ActuallyAffectsTheTitleView() throws Exception {
212
-		ContainerViewController containerVc = new SimpleContainerViewController(activity, "theId");
213
-		StackController stackController = new StackController(activity, "stackId", new TestStackAnimator());
214
-		stackController.push(containerVc);
215
-		uut.setRoot(stackController);
216
-		assertThat(stackController.getTopBar().getTitle()).isEmpty();
217
-
218
-		NavigationOptions opts = new NavigationOptions();
219
-		opts.title = "the new title";
220
-		uut.setOptions("theId", opts);
221
-
222
-		assertThat(stackController.getTopBar().getTitle()).isEqualTo("the new title");
223
-	}
224
-
225 210
 	@NonNull
226 211
 	private BottomTabsController newTabs() {
227 212
 		return new BottomTabsController(activity, "tabsController");

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

@@ -3,11 +3,14 @@ package com.reactnativenavigation.viewcontrollers;
3 3
 import android.app.Activity;
4 4
 import android.graphics.Color;
5 5
 import android.graphics.drawable.ColorDrawable;
6
+import android.view.View;
6 7
 
7 8
 import com.reactnativenavigation.BaseTest;
8 9
 import com.reactnativenavigation.mocks.TestContainerView;
9 10
 import com.reactnativenavigation.parse.NavigationOptions;
11
+import com.reactnativenavigation.views.TopbarContainerViewCreator;
10 12
 
13
+import org.json.JSONObject;
11 14
 import org.junit.Test;
12 15
 
13 16
 import static org.assertj.core.api.Java6Assertions.assertThat;
@@ -28,12 +31,13 @@ public class OptionsApplyingTest extends BaseTest {
28 31
 		activity = newActivity();
29 32
 		initialNavigationOptions = new NavigationOptions();
30 33
 		view = spy(new TestContainerView(activity));
31
-		uut = new ContainerViewController(activity, "containerId1", "containerName", new ContainerViewController.ContainerViewCreator() {
32
-			@Override
33
-			public ContainerViewController.ContainerView create(final Activity activity1, final String containerId, final String containerName) {
34
-				return view;
35
-			}
36
-		}, initialNavigationOptions);
34
+		uut = new ContainerViewController(activity, "containerId1", "containerName",
35
+				new TopbarContainerViewCreator(new ContainerViewController.ContainerViewCreator() {
36
+					@Override
37
+					public ContainerViewController.ContainerView create(final Activity activity1, final String containerId, final String containerName) {
38
+						return view;
39
+					}
40
+				}), initialNavigationOptions);
37 41
 	}
38 42
 
39 43
 	@Test
@@ -49,10 +53,10 @@ public class OptionsApplyingTest extends BaseTest {
49 53
 		initialNavigationOptions.title = "the title";
50 54
 		StackController stackController = new StackController(activity, "stackId");
51 55
 		stackController.push(uut);
52
-		assertThat(stackController.getTopBar().getTitle()).isEmpty();
56
+		assertThat(uut.getTopBar().getTitle()).isEmpty();
53 57
 
54 58
 		uut.onViewAppeared();
55
-		assertThat(stackController.getTopBar().getTitle()).isEqualTo("the title");
59
+		assertThat(uut.getTopBar().getTitle()).isEqualTo("the title");
56 60
 	}
57 61
 
58 62
 	@Test
@@ -67,63 +71,72 @@ public class OptionsApplyingTest extends BaseTest {
67 71
 
68 72
 	@Test
69 73
 	public void reappliesOptionsOnMerge() throws Exception {
70
-		StackController stackController = new StackController(activity, "stackId");
71
-		stackController.push(uut);
72
-		assertThat(stackController.getTopBar().getTitle()).isEmpty();
74
+		uut.onViewAppeared();
75
+		assertThat(uut.getTopBar().getTitle()).isEmpty();
73 76
 
74 77
 		NavigationOptions opts = new NavigationOptions();
75 78
 		opts.title = "the new title";
76 79
 		uut.mergeNavigationOptions(opts);
77 80
 
78
-		assertThat(stackController.getTopBar().getTitle()).isEqualTo("the new title");
81
+		assertThat(uut.getTopBar().getTitle()).isEqualTo("the new title");
79 82
 	}
80 83
 
81 84
 	@Test
82 85
 	public void appliesTopBackBackgroundColor() throws Exception {
83
-		StackController stackController = new StackController(activity, "stackId");
84
-		stackController.push(uut);
85
-		assertThat(((ColorDrawable) stackController.getTopBar().getBackground()).getColor()).isNotEqualTo(Color.RED);
86
+		uut.onViewAppeared();
87
+		//TODO: FIX TEST
88
+		assertThat(((ColorDrawable) uut.getTopBar().getTitleBar().getBackground()).getColor()).isNotEqualTo(Color.RED);
86 89
 
87 90
 		NavigationOptions opts = new NavigationOptions();
88 91
 		opts.topBarBackgroundColor = Color.RED;
89 92
 		uut.mergeNavigationOptions(opts);
90 93
 
91
-		assertThat(((ColorDrawable) stackController.getTopBar().getBackground()).getColor()).isEqualTo(Color.RED);
94
+		assertThat(((ColorDrawable) uut.getTopBar().getTitleBar().getBackground()).getColor()).isEqualTo(Color.RED);
92 95
 	}
93 96
 
94 97
 	@Test
95 98
 	public void appliesTopBarTextColor() throws Exception {
96 99
 		assertThat(uut.getNavigationOptions()).isSameAs(initialNavigationOptions);
97 100
 		initialNavigationOptions.title = "the title";
98
-		StackController stackController = new StackController(activity, "stackId");
99
-		stackController.push(uut);
100 101
 		uut.onViewAppeared();
101
-		assertThat(stackController.getTopBar().getTitleTextView().getCurrentTextColor()).isNotEqualTo(Color.RED);
102
+		assertThat(uut.getTopBar().getTitleTextView().getCurrentTextColor()).isNotEqualTo(Color.RED);
102 103
 
103 104
 		NavigationOptions opts = new NavigationOptions();
104 105
 		opts.title = "the title";
105 106
 		opts.topBarTextColor = Color.RED;
106 107
 		uut.mergeNavigationOptions(opts);
107 108
 
108
-		assertThat(stackController.getTopBar().getTitleTextView()).isNotEqualTo(null);
109
-		assertThat(stackController.getTopBar().getTitleTextView().getCurrentTextColor()).isEqualTo(Color.RED);
109
+		assertThat(uut.getTopBar().getTitleTextView()).isNotEqualTo(null);
110
+		assertThat(uut.getTopBar().getTitleTextView().getCurrentTextColor()).isEqualTo(Color.RED);
110 111
 	}
111 112
 
112 113
 	@Test
113 114
 	public void appliesTopBarTextSize() throws Exception {
114 115
 		assertThat(uut.getNavigationOptions()).isSameAs(initialNavigationOptions);
115 116
 		initialNavigationOptions.title = "the title";
116
-		StackController stackController = new StackController(activity, "stackId");
117
-		stackController.push(uut);
118 117
 		uut.onViewAppeared();
119
-		assertThat(stackController.getTopBar().getTitleTextView().getTextSize()).isNotEqualTo(18);
118
+		assertThat(uut.getTopBar().getTitleTextView().getTextSize()).isNotEqualTo(18);
120 119
 
121 120
 		NavigationOptions opts = new NavigationOptions();
122 121
 		opts.title = "the title";
123 122
 		opts.topBarTextFontSize = 18;
124 123
 		uut.mergeNavigationOptions(opts);
125 124
 
126
-		assertThat(stackController.getTopBar().getTitleTextView()).isNotEqualTo(null);
127
-		assertThat(stackController.getTopBar().getTitleTextView().getTextSize()).isEqualTo(18);
125
+		assertThat(uut.getTopBar().getTitleTextView()).isNotEqualTo(null);
126
+		assertThat(uut.getTopBar().getTitleTextView().getTextSize()).isEqualTo(18);
127
+	}
128
+
129
+	@Test
130
+	public void appliesTopBarHidden() throws Exception {
131
+		assertThat(uut.getNavigationOptions()).isSameAs(initialNavigationOptions);
132
+		initialNavigationOptions.title = "the title";
133
+		uut.onViewAppeared();
134
+		assertThat(uut.getTopBar().getVisibility()).isNotEqualTo(View.GONE);
135
+
136
+		NavigationOptions opts = new NavigationOptions();
137
+		opts.topBarHidden = NavigationOptions.BooleanOptions.True;
138
+		uut.mergeNavigationOptions(opts);
139
+
140
+		assertThat(uut.getTopBar().getVisibility()).isEqualTo(View.GONE);
128 141
 	}
129 142
 }

+ 1
- 0
lib/ios/RNNNavigationOptions.h View File

@@ -26,6 +26,7 @@ extern const NSInteger BLUR_TOPBAR_TAG;
26 26
 @property (nonatomic, strong) NSNumber* statusBarHideWithTopBar;
27 27
 @property (nonatomic, strong) NSNumber* tabBarHidden;
28 28
 @property (nonatomic, strong) NSNumber* topBarBlur;
29
+@property (nonatomic, strong) NSNumber* animateTopBarHide;
29 30
 
30 31
 
31 32
 - (UIInterfaceOrientationMask)supportedOrientations;

+ 17
- 20
lib/ios/RNNNavigationOptions.m View File

@@ -32,6 +32,7 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
32 32
 	self.topBarNoBorder = [navigationOptions objectForKey:@"topBarNoBorder"];
33 33
 	self.tabBarHidden = [navigationOptions objectForKey:@"tabBarHidden"];
34 34
 	self.topBarBlur = [navigationOptions objectForKey:@"topBarBlur"];
35
+	self.animateTopBarHide = [navigationOptions objectForKey:@"animateTopBarHide"];
35 36
 
36 37
 	return self;
37 38
 }
@@ -49,11 +50,11 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
49 50
 	} else {
50 51
 		viewController.navigationController.navigationBar.barTintColor = nil;
51 52
 	}
52
-	
53
+
53 54
 	if (self.title) {
54 55
 		viewController.navigationItem.title = self.title;
55 56
 	}
56
-	
57
+
57 58
 	if (self.topBarTextFontFamily || self.topBarTextColor || self.topBarTextFontSize){
58 59
 		NSMutableDictionary* navigationBarTitleTextAttributes = [NSMutableDictionary new];
59 60
 		if (self.topBarTextColor) {
@@ -70,20 +71,16 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
70 71
 		}
71 72
 		viewController.navigationController.navigationBar.titleTextAttributes = navigationBarTitleTextAttributes;
72 73
 	}
73
-	
74
+
74 75
 	if (self.screenBackgroundColor) {
75 76
 		UIColor* screenColor = [RCTConvert UIColor:self.screenBackgroundColor];
76 77
 		viewController.view.backgroundColor = screenColor;
77 78
 	}
78
-	
79
+
79 80
 	if (self.topBarHidden){
80
-		if ([self.topBarHidden boolValue]) {
81
-			[viewController.navigationController setNavigationBarHidden:YES animated:YES];
82
-		} else {
83
-			[viewController.navigationController setNavigationBarHidden:NO animated:YES];
84
-		}
81
+		[viewController.navigationController setNavigationBarHidden:[self.topBarHidden boolValue] animated:[self.animateTopBarHide boolValue]];
85 82
 	}
86
-	
83
+
87 84
 	if (self.topBarHideOnScroll) {
88 85
 		BOOL topBarHideOnScrollBool = [self.topBarHideOnScroll boolValue];
89 86
 		if (topBarHideOnScrollBool) {
@@ -92,14 +89,14 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
92 89
 			viewController.navigationController.hidesBarsOnSwipe = NO;
93 90
 		}
94 91
 	}
95
-	
92
+
96 93
 	if (self.topBarButtonColor) {
97 94
 		UIColor* buttonColor = [RCTConvert UIColor:self.topBarButtonColor];
98 95
 		viewController.navigationController.navigationBar.tintColor = buttonColor;
99 96
 	} else {
100 97
 		viewController.navigationController.navigationBar.tintColor = nil;
101 98
 	}
102
-	
99
+
103 100
 	if (self.tabBadge) {
104 101
 		NSString *badge = [RCTConvert NSString:self.tabBadge];
105 102
 		if (viewController.navigationController) {
@@ -108,7 +105,7 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
108 105
 			viewController.tabBarItem.badgeValue = badge;
109 106
 		}
110 107
 	}
111
-	
108
+
112 109
 	if (self.topBarTranslucent) {
113 110
 		if ([self.topBarTranslucent boolValue]) {
114 111
 			viewController.navigationController.navigationBar.translucent = YES;
@@ -116,7 +113,7 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
116 113
 			viewController.navigationController.navigationBar.translucent = NO;
117 114
 		}
118 115
 	}
119
-	
116
+
120 117
 	if (self.topBarNoBorder) {
121 118
 		if ([self.topBarNoBorder boolValue]) {
122 119
 			viewController.navigationController.navigationBar
@@ -126,7 +123,7 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
126 123
 			.shadowImage = nil;
127 124
 		}
128 125
 	}
129
-	
126
+
130 127
 	if (self.statusBarBlur) {
131 128
 		UIView* curBlurView = [viewController.view viewWithTag:BLUR_STATUS_TAG];
132 129
 		if ([self.statusBarBlur boolValue]) {
@@ -142,11 +139,11 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
142 139
 			}
143 140
 		}
144 141
 	}
145
-	
142
+
146 143
 	if (self.topBarBlur && [self.topBarBlur boolValue]) {
147
-		
144
+
148 145
 		if (![viewController.navigationController.navigationBar viewWithTag:BLUR_TOPBAR_TAG]) {
149
-			
146
+
150 147
 			[viewController.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
151 148
 			viewController.navigationController.navigationBar.shadowImage = [UIImage new];
152 149
 			UIVisualEffectView *blur = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
@@ -157,7 +154,7 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
157 154
 			[viewController.navigationController.navigationBar insertSubview:blur atIndex:0];
158 155
 			[viewController.navigationController.navigationBar sendSubviewToBack:blur];
159 156
 		}
160
-		
157
+
161 158
 	} else {
162 159
 		UIView *blur = [viewController.navigationController.navigationBar viewWithTag:BLUR_TOPBAR_TAG];
163 160
 		if (blur) {
@@ -190,7 +187,7 @@ const NSInteger BLUR_TOPBAR_TAG = 78264802;
190 187
 			}
191 188
 		}
192 189
 	}
193
-	
190
+
194 191
 	return supportedOrientationsMask;
195 192
 }
196 193
 

+ 5
- 5
playground/src/containers/LifecycleScreen.js View File

@@ -19,7 +19,9 @@ class LifecycleScreen extends Component {
19 19
   }
20 20
 
21 21
   didDisappear() {
22
-    alert('didDisappear'); // eslint-disable-line no-alert
22
+    setTimeout(() => {
23
+      alert('didDisappear'); // eslint-disable-line no-alert
24
+    }, 1000);
23 25
   }
24 26
 
25 27
   componentWillUnmount() {
@@ -35,16 +37,14 @@ class LifecycleScreen extends Component {
35 37
       <View style={styles.root}>
36 38
         <Text style={styles.h1}>{`Lifecycle Screen`}</Text>
37 39
         <Text style={styles.h1}>{this.state.text}</Text>
38
-        <Button title="Push to test didDisappear" onPress={this.onClickPush} />
40
+        <Button title="Push to test didDisappear" onPress={this.onClickPush}/>
39 41
         <Text style={styles.footer}>{`this.props.containerId = ${this.props.containerId}`}</Text>
40 42
       </View>
41 43
     );
42 44
   }
43 45
 
44 46
   onClickPush() {
45
-    Navigation.push(this.props.containerId, {
46
-      name: 'navigation.playground.TextScreen'
47
-    });
47
+    Navigation.push(this.props.containerId, { name: 'navigation.playground.TextScreen' });
48 48
   }
49 49
 }
50 50
 module.exports = LifecycleScreen;

+ 4
- 2
playground/src/containers/OptionsScreen.js View File

@@ -100,13 +100,15 @@ class OptionsScreen extends Component {
100 100
 
101 101
   onClickShowTopBar() {
102 102
     Navigation.setOptions(this.props.containerId, {
103
-      topBarHidden: false
103
+      topBarHidden: false,
104
+      animateTopBarHide: true
104 105
     });
105 106
   }
106 107
 
107 108
   onClickHideTopBar() {
108 109
     Navigation.setOptions(this.props.containerId, {
109
-      topBarHidden: true
110
+      topBarHidden: true,
111
+      animateTopBarHide: true
110 112
     });
111 113
   }
112 114
 }