瀏覽代碼

Fix TopBar visibility and merge options issues

This commit started with a small fix to a TopBar visibility issue detailed in #3971 which unveiled
a few issues with how options are resolved and merged.

TopBar visibility
The initial TopBar visibility issue was a result of hide animators now being cancelled when pushing another screen.
Another issue was that if the TopBar was not measured (Initial stack child was shown with `TopBar.visible = false`),
the start value passed to the Y translation was 0. This commit makes sure the TopBar show animation starts after the TopBar is measured.

Options issues
When resolving current issues in ParentControllers, the options of the current child were wrongfully taken into account.
This commit changes options resolve logic so that initial options (and options dynamically merged to them via mergeOptions call) are merged.
Guy Carmeli 6 年之前
父節點
當前提交
cbcdda075f
共有 16 個檔案被更改,包括 108 行新增75 行删除
  1. 12
    6
      lib/android/app/src/main/java/com/reactnativenavigation/anim/TopBarAnimator.java
  2. 14
    1
      lib/android/app/src/main/java/com/reactnativenavigation/presentation/StackOptionsPresenter.java
  3. 16
    0
      lib/android/app/src/main/java/com/reactnativenavigation/utils/UiUtils.java
  4. 8
    0
      lib/android/app/src/main/java/com/reactnativenavigation/utils/ViewUtils.java
  5. 3
    4
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ParentController.java
  6. 3
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java
  7. 3
    1
      lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java
  8. 2
    1
      lib/android/app/src/main/java/com/reactnativenavigation/views/topbar/TopBar.java
  9. 3
    3
      lib/android/app/src/main/java/com/reactnativenavigation/views/toptabs/TopTabs.java
  10. 6
    0
      lib/android/app/src/test/java/com/reactnativenavigation/TestUtils.java
  11. 16
    16
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/BottomTabsControllerTest.java
  12. 3
    9
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ParentControllerTest.java
  13. 3
    5
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/StackOptionsPresenterTest.java
  14. 10
    24
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsViewControllerTest.java
  15. 5
    3
      lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.java
  16. 1
    1
      playground/src/app.js

+ 12
- 6
lib/android/app/src/main/java/com/reactnativenavigation/anim/TopBarAnimator.java 查看文件

@@ -12,6 +12,7 @@ import android.view.animation.DecelerateInterpolator;
12 12
 import android.view.animation.LinearInterpolator;
13 13
 
14 14
 import com.reactnativenavigation.parse.AnimationOptions;
15
+import com.reactnativenavigation.utils.UiUtils;
15 16
 import com.reactnativenavigation.views.topbar.TopBar;
16 17
 
17 18
 import javax.annotation.Nullable;
@@ -41,12 +42,15 @@ public class TopBarAnimator {
41 42
     }
42 43
 
43 44
     public void show(AnimationOptions options) {
44
-        if (options.hasValue() && (!options.id.hasValue() || options.id.get().equals(stackId))) {
45
-            showAnimator = options.getAnimation(topBar);
46
-        } else {
47
-            showAnimator = getDefaultShowAnimator(-1 * topBar.getMeasuredHeight(), DECELERATE, DURATION);
48
-        }
49
-        show();
45
+        topBar.setVisibility(View.VISIBLE);
46
+        UiUtils.runOnMeasured(topBar, () -> {
47
+            if (options.hasValue() && (!options.id.hasValue() || options.id.get().equals(stackId))) {
48
+                showAnimator = options.getAnimation(topBar);
49
+            } else {
50
+                showAnimator = getDefaultShowAnimator(-1 * topBar.getHeight(), DECELERATE, DURATION);
51
+            }
52
+            show();
53
+        });
50 54
     }
51 55
 
52 56
     public void show(float startTranslation) {
@@ -62,6 +66,7 @@ public class TopBarAnimator {
62 66
             }
63 67
         });
64 68
         topBar.resetAnimationOptions();
69
+        if (isAnimatingHide()) hideAnimator.cancel();
65 70
         showAnimator.start();
66 71
     }
67 72
 
@@ -96,6 +101,7 @@ public class TopBarAnimator {
96 101
                 onAnimationEnd.run();
97 102
             }
98 103
         });
104
+        if (isAnimatingShow()) showAnimator.cancel();
99 105
         hideAnimator.start();
100 106
     }
101 107
 

+ 14
- 1
lib/android/app/src/main/java/com/reactnativenavigation/presentation/StackOptionsPresenter.java 查看文件

@@ -113,7 +113,11 @@ public class StackOptionsPresenter {
113 113
                 ((Component) view).drawBelowTopBar(topBar);
114 114
             }
115 115
         }
116
-        applyTopBarVisibility(withDefault.topBar, withDefault.animations, options);
116
+    }
117
+
118
+    public void applyInitialChildLayoutOptions(Options options) {
119
+        Options withDefault = options.copy().withDefaultOptions(defaultOptions);
120
+        setInitialTopBarVisibility(withDefault.topBar);
117 121
     }
118 122
 
119 123
     public void applyChildOptions(Options options, Component child) {
@@ -203,6 +207,15 @@ public class StackOptionsPresenter {
203 207
         }
204 208
     }
205 209
 
210
+    private void setInitialTopBarVisibility(TopBarOptions options) {
211
+        if (options.visible.isFalse()) {
212
+            topBar.hide();
213
+        }
214
+        if (options.visible.isTrueOrUndefined()) {
215
+            topBar.show();
216
+        }
217
+    }
218
+
206 219
     private void applyTopBarVisibility(TopBarOptions options, AnimationsOptions animationOptions, Options componentOptions) {
207 220
         if (options.visible.isFalse()) {
208 221
             if (options.animate.isTrueOrUndefined() && componentOptions.animations.push.enable.isTrueOrUndefined()) {

+ 16
- 0
lib/android/app/src/main/java/com/reactnativenavigation/utils/UiUtils.java 查看文件

@@ -30,6 +30,22 @@ public class UiUtils {
30 30
         });
31 31
     }
32 32
 
33
+    public static void runOnMeasured(View view, Runnable task) {
34
+        if (view.getHeight() > 0 && view.getWidth() > 0) {
35
+            task.run();
36
+        } else {
37
+            view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
38
+                @Override
39
+                public void onGlobalLayout() {
40
+                    if (view.getHeight() > 0 && view.getWidth() > 0) {
41
+                        view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
42
+                        task.run();
43
+                    }
44
+                }
45
+            });
46
+        }
47
+    }
48
+
33 49
 	public static void runOnMainThread(Runnable runnable) {
34 50
 		new Handler(Looper.getMainLooper()).post(runnable);
35 51
 	}

+ 8
- 0
lib/android/app/src/main/java/com/reactnativenavigation/utils/ViewUtils.java 查看文件

@@ -4,6 +4,7 @@ import android.graphics.Point;
4 4
 import android.support.annotation.Nullable;
5 5
 import android.view.View;
6 6
 import android.view.ViewGroup;
7
+import android.view.ViewManager;
7 8
 import android.view.ViewParent;
8 9
 
9 10
 import com.facebook.react.views.view.ReactViewBackgroundDrawable;
@@ -129,4 +130,11 @@ public class ViewUtils {
129 130
         }
130 131
         throw new RuntimeException(view.getBackground().getClass().getSimpleName() + " is not ReactViewBackgroundDrawable");
131 132
     }
133
+
134
+    public static void removeFromParent(View view) {
135
+        ViewParent parent = view.getParent();
136
+        if (parent != null) {
137
+            ((ViewManager) parent).removeView(view);
138
+        }
139
+    }
132 140
 }

+ 3
- 4
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ParentController.java 查看文件

@@ -42,11 +42,10 @@ public abstract class ParentController<T extends ViewGroup> extends ChildControl
42 42
     @Override
43 43
     @CheckResult
44 44
     public Options resolveCurrentOptions() {
45
-	    if (CollectionUtils.isNullOrEmpty(getChildControllers())) return options;
45
+	    if (CollectionUtils.isNullOrEmpty(getChildControllers())) return initialOptions;
46 46
         return getCurrentChild()
47 47
                 .resolveCurrentOptions()
48
-                .copy()
49
-                .mergeWith(options);
48
+                .mergeWith(initialOptions);
50 49
     }
51 50
 
52 51
     @Override
@@ -97,7 +96,7 @@ public abstract class ParentController<T extends ViewGroup> extends ChildControl
97 96
 
98 97
     @CallSuper
99 98
     public void applyChildOptions(Options options, Component child) {
100
-        this.options = this.options.mergeWith(options);
99
+        this.options = this.initialOptions.mergeWith(options);
101 100
         if (isRoot()) {
102 101
             presenter.applyRootOptions(getView(), options);
103 102
         }

+ 3
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java 查看文件

@@ -45,7 +45,7 @@ public abstract class ViewController<T extends ViewGroup> implements ViewTreeObs
45 45
         boolean onViewDisappear(View view);
46 46
     }
47 47
 
48
-    Options initialOptions;
48
+    protected Options initialOptions;
49 49
     public Options options;
50 50
 
51 51
     private final Activity activity;
@@ -106,9 +106,11 @@ public abstract class ViewController<T extends ViewGroup> implements ViewTreeObs
106 106
 
107 107
     @CallSuper
108 108
     public void mergeOptions(Options options) {
109
+        this.initialOptions = this.initialOptions.mergeWith(options);
109 110
         this.options = this.options.mergeWith(options);
110 111
         if (view != null) applyOptions(this.options);
111 112
         this.options.clearOneTimeOptions();
113
+        initialOptions.clearOneTimeOptions();
112 114
     }
113 115
 
114 116
     @CallSuper

+ 3
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java 查看文件

@@ -131,7 +131,7 @@ public class StackController extends ParentController<StackLayout> {
131 131
 
132 132
     public void push(ViewController child, CommandListener listener) {
133 133
         final ViewController toRemove = stack.peek();
134
-        backButtonHelper.addToPushedChild(child);
134
+        if (size() > 0) backButtonHelper.addToPushedChild(child);
135 135
         child.setParentController(this);
136 136
         stack.push(child.getId(), child);
137 137
         Options resolvedOptions = resolveCurrentOptions(presenter.getDefaultOptions());
@@ -166,6 +166,7 @@ public class StackController extends ParentController<StackLayout> {
166 166
         view.setLayoutParams(new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
167 167
         child.setWaitForRender(resolvedOptions.animations.push.waitForRender);
168 168
         presenter.applyLayoutParamsOptions(resolvedOptions, view);
169
+        if (size() == 1) presenter.applyInitialChildLayoutOptions(resolvedOptions);
169 170
         getView().addView(view, getView().getChildCount() - 1);
170 171
     }
171 172
 
@@ -310,6 +311,7 @@ public class StackController extends ParentController<StackLayout> {
310 311
         child.setLayoutParams(new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
311 312
         Options options = resolveCurrentOptions();
312 313
         presenter.applyLayoutParamsOptions(options, child);
314
+        presenter.applyInitialChildLayoutOptions(options);
313 315
         stackLayout.addView(child, 0);
314 316
     }
315 317
 

+ 2
- 1
lib/android/app/src/main/java/com/reactnativenavigation/views/topbar/TopBar.java 查看文件

@@ -265,6 +265,7 @@ public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAw
265 265
     }
266 266
 
267 267
     public void hideAnimate(AnimationOptions options, Runnable onAnimationEnd) {
268
+        if (!visible()) return;
268 269
         animator.hide(options, onAnimationEnd);
269 270
     }
270 271
 
@@ -275,7 +276,7 @@ public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAw
275 276
     }
276 277
 
277 278
     public void clearTopTabs() {
278
-        topTabs.clear(this);
279
+        topTabs.clear();
279 280
     }
280 281
 
281 282
     @VisibleForTesting

+ 3
- 3
lib/android/app/src/main/java/com/reactnativenavigation/views/toptabs/TopTabs.java 查看文件

@@ -4,10 +4,10 @@ import android.content.Context;
4 4
 import android.graphics.Typeface;
5 5
 import android.support.design.widget.TabLayout;
6 6
 import android.support.v4.view.ViewPager;
7
-import android.view.ViewManager;
8 7
 
9 8
 import com.reactnativenavigation.parse.params.Colour;
10 9
 import com.reactnativenavigation.parse.params.Number;
10
+import com.reactnativenavigation.utils.ViewUtils;
11 11
 import com.reactnativenavigation.views.topbar.TopBar;
12 12
 
13 13
 public class TopTabs extends TabLayout {
@@ -49,9 +49,9 @@ public class TopTabs extends TabLayout {
49 49
         }
50 50
     }
51 51
 
52
-    public void clear(ViewManager parent) {
52
+    public void clear() {
53 53
         setupWithViewPager(null);
54
-        parent.removeView(this);
54
+        ViewUtils.removeFromParent(this);
55 55
     }
56 56
 
57 57
     public void init(ViewPager viewPager) {

+ 6
- 0
lib/android/app/src/test/java/com/reactnativenavigation/TestUtils.java 查看文件

@@ -7,9 +7,11 @@ import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
7 7
 import com.reactnativenavigation.mocks.TopBarBackgroundViewCreatorMock;
8 8
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
9 9
 import com.reactnativenavigation.parse.Options;
10
+import com.reactnativenavigation.parse.params.Bool;
10 11
 import com.reactnativenavigation.presentation.StackOptionsPresenter;
11 12
 import com.reactnativenavigation.utils.ImageLoader;
12 13
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
14
+import com.reactnativenavigation.viewcontrollers.ViewController;
13 15
 import com.reactnativenavigation.viewcontrollers.stack.StackControllerBuilder;
14 16
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewController;
15 17
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
@@ -34,4 +36,8 @@ public class TestUtils {
34 36
                 .setStackPresenter(new StackOptionsPresenter(activity, new TitleBarReactViewCreatorMock(), new TopBarButtonCreatorMock(), new ImageLoader(), new Options())                )
35 37
                 .setInitialOptions(new Options());
36 38
     }
39
+
40
+    public static void hideBackButton(ViewController viewController) {
41
+        viewController.options.topBar.buttons.back.visible = new Bool(false);
42
+    }
37 43
 }

+ 16
- 16
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/BottomTabsControllerTest.java 查看文件

@@ -26,6 +26,7 @@ import com.reactnativenavigation.react.EventEmitter;
26 26
 import com.reactnativenavigation.utils.CommandListenerAdapter;
27 27
 import com.reactnativenavigation.utils.ImageLoader;
28 28
 import com.reactnativenavigation.utils.OptionHelper;
29
+import com.reactnativenavigation.utils.ViewUtils;
29 30
 import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
30 31
 import com.reactnativenavigation.viewcontrollers.stack.StackController;
31 32
 import com.reactnativenavigation.views.BottomTabs;
@@ -38,6 +39,7 @@ import org.mockito.Mockito;
38 39
 import java.util.Arrays;
39 40
 import java.util.List;
40 41
 
42
+import static com.reactnativenavigation.TestUtils.hideBackButton;
41 43
 import static org.assertj.core.api.Java6Assertions.assertThat;
42 44
 import static org.mockito.ArgumentMatchers.any;
43 45
 import static org.mockito.ArgumentMatchers.eq;
@@ -80,6 +82,7 @@ public class BottomTabsControllerTest extends BaseTest {
80 82
         tabs = createTabs();
81 83
         presenter = spy(new BottomTabsOptionsPresenter(tabs, new Options()));
82 84
         uut = createBottomTabs();
85
+        activity.setContentView(uut.getView());
83 86
     }
84 87
 
85 88
     @Test
@@ -158,6 +161,8 @@ public class BottomTabsControllerTest extends BaseTest {
158 161
 
159 162
     @Test
160 163
     public void applyOptions_bottomTabsOptionsAreClearedAfterApply() {
164
+        ViewUtils.removeFromParent(uut.getView());
165
+
161 166
         Options options = new Options();
162 167
         options.bottomTabsOptions.backgroundColor = new Colour(Color.RED);
163 168
         child1.mergeOptions(options);
@@ -235,7 +240,9 @@ public class BottomTabsControllerTest extends BaseTest {
235 240
 
236 241
         SimpleViewController stackChild = new SimpleViewController(activity, childRegistry, "stackChild", new Options());
237 242
         SimpleViewController stackChild2 = new SimpleViewController(activity, childRegistry, "stackChild", new Options());
243
+
238 244
         disablePushAnimation(stackChild, stackChild2);
245
+        hideBackButton(stackChild2);
239 246
 
240 247
         child4.push(stackChild, new CommandListenerAdapter());
241 248
         assertThat(child4.size()).isOne();
@@ -245,17 +252,12 @@ public class BottomTabsControllerTest extends BaseTest {
245 252
 
246 253
     @Test
247 254
     public void deepChildOptionsAreApplied() {
248
-        BottomTabsController spy = spy(uut);
249
-        activity.setContentView(spy.getView());
250
-
251 255
         child6.options.topBar.drawBehind = new Bool(false);
252 256
         disablePushAnimation(child6);
253 257
         child4.push(child6, new CommandListenerAdapter());
254 258
         assertThat(child4.size()).isOne();
255 259
 
256
-
257
-        verify(spy, times(1)).onViewAppeared();
258
-        assertThat(spy.getSelectedIndex()).isZero();
260
+        assertThat(uut.getSelectedIndex()).isZero();
259 261
         verify(child6, times(0)).onViewAppeared();
260 262
         assertThat(child4.getTopBar().getHeight())
261 263
                 .isNotZero()
@@ -264,16 +266,14 @@ public class BottomTabsControllerTest extends BaseTest {
264 266
 
265 267
     @Test
266 268
     public void oneTimeOptionsAreAppliedOnce() {
267
-        initialOptions.bottomTabsOptions.currentTabIndex = new Number(1);
268
-        BottomTabsController spy = spy(createBottomTabs());
269
-        spy.onViewAppeared();
270
-
271
-        assertThat(spy.getSelectedIndex()).isOne();
272
-        spy.selectTab(0);
273
-        tabs.get(0).onViewAppeared();
274
-        verify(spy).clearOptions();
275
-        assertThat(spy.getSelectedIndex()).isZero();
276
-        assertThat(spy.options.bottomTabsOptions.currentTabIndex.hasValue()).isFalse();
269
+        Options options = new Options();
270
+        options.bottomTabsOptions.currentTabIndex = new Number(1);
271
+
272
+        assertThat(uut.getSelectedIndex()).isZero();
273
+        uut.mergeOptions(options);
274
+        assertThat(uut.getSelectedIndex()).isOne();
275
+        assertThat(uut.options.bottomTabsOptions.currentTabIndex.hasValue()).isFalse();
276
+        assertThat(uut.initialOptions.bottomTabsOptions.currentTabIndex.hasValue()).isFalse();
277 277
     }
278 278
 
279 279
     @NonNull

+ 3
- 9
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ParentControllerTest.java 查看文件

@@ -187,20 +187,14 @@ public class ParentControllerTest extends BaseTest {
187 187
     @Test
188 188
     public void resolveCurrentOptions_returnOptionsIfNoChildren() {
189 189
         assertThat(uut.getChildControllers().size()).isZero();
190
-        assertThat(uut.resolveCurrentOptions()).isEqualTo(uut.options);
190
+        assertThat(uut.resolveCurrentOptions()).isEqualTo(uut.initialOptions);
191 191
     }
192 192
 
193 193
     @Test
194 194
     public void resolveCurrentOptions_mergesWithCurrentChild() {
195 195
         ViewController child1 = Mockito.mock(ViewController.class);
196 196
         when(child1.getView()).thenReturn(new FrameLayout(activity));
197
-        Options copiedChildOptions = spy(new Options());
198
-        Options childOptions = spy(new Options() {
199
-            @Override
200
-            public Options copy() {
201
-                return copiedChildOptions;
202
-            }
203
-        });
197
+        Options childOptions = spy(new Options());
204 198
         when(child1.resolveCurrentOptions()).thenReturn(childOptions);
205 199
 
206 200
         children.add(child1);
@@ -209,7 +203,7 @@ public class ParentControllerTest extends BaseTest {
209 203
         assertThat(uut.getCurrentChild()).isEqualTo(child1);
210 204
         uut.resolveCurrentOptions();
211 205
         verify(child1).resolveCurrentOptions();
212
-        verify(copiedChildOptions).mergeWith(uut.options);
206
+        verify(childOptions).mergeWith(uut.initialOptions);
213 207
     }
214 208
 
215 209
     @Test

+ 3
- 5
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/StackOptionsPresenterTest.java 查看文件

@@ -34,7 +34,6 @@ import com.reactnativenavigation.views.topbar.TopBar;
34 34
 import org.json.JSONObject;
35 35
 import org.junit.Test;
36 36
 import org.mockito.ArgumentCaptor;
37
-import org.mockito.Mockito;
38 37
 
39 38
 import java.util.ArrayList;
40 39
 import java.util.Collections;
@@ -279,13 +278,12 @@ public class StackOptionsPresenterTest extends BaseTest {
279 278
     }
280 279
 
281 280
     @Test
282
-    public void applyLayoutParamsOptions() {
281
+    public void applyInitialChildLayoutOptions() {
283 282
         Options options = new Options();
284 283
         options.topBar.visible = new Bool(false);
285
-        options.topBar.animate = new Bool(false);
286
-        View view = Mockito.mock(View.class, Mockito.withSettings().extraInterfaces(com.reactnativenavigation.views.Component.class));
284
+        options.topBar.animate = new Bool(true);
287 285
 
288
-        uut.applyLayoutParamsOptions(options, view);
286
+        uut.applyInitialChildLayoutOptions(options);
289 287
         verify(topBar).hide();
290 288
     }
291 289
 

+ 10
- 24
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsViewControllerTest.java 查看文件

@@ -6,6 +6,7 @@ import android.view.ViewGroup;
6 6
 
7 7
 import com.reactnativenavigation.BaseTest;
8 8
 import com.reactnativenavigation.TestUtils;
9
+import com.reactnativenavigation.mocks.SimpleViewController;
9 10
 import com.reactnativenavigation.mocks.TestComponentViewCreator;
10 11
 import com.reactnativenavigation.mocks.TestReactView;
11 12
 import com.reactnativenavigation.parse.Options;
@@ -65,8 +66,6 @@ public class TopTabsViewControllerTest extends BaseTest {
65 66
 
66 67
         stack = spy(TestUtils.newStackController(activity).build());
67 68
         stack.ensureViewIsCreated();
68
-        stack.push(uut, new CommandListenerAdapter());
69
-        uut.setParentController(stack);
70 69
     }
71 70
 
72 71
     @NonNull
@@ -209,35 +208,22 @@ public class TopTabsViewControllerTest extends BaseTest {
209 208
 
210 209
     @Test
211 210
     public void applyOptions_tabsAreRemovedAfterViewDisappears() {
212
-        stack.getView().removeAllViews();
213
-
214
-        StackController stackController = spy(TestUtils.newStackController(activity).build());
211
+        StackController stackController = TestUtils.newStackController(activity).build();
215 212
         stackController.ensureViewIsCreated();
216
-        ComponentViewController first = new ComponentViewController(
217
-                activity,
218
-                childRegistry,
219
-                "firstScreen",
220
-                "comp1",
221
-                new TestComponentViewCreator(),
222
-                new Options(),
223
-                new OptionsPresenter(activity, new Options())
224
-        );
225
-        first.options.animations.push.enable = new Bool(false);
226
-        uut.options.animations.push.enable = new Bool(false);
213
+        ViewController first = new SimpleViewController(activity, childRegistry, "first", Options.EMPTY);
214
+        disablePushAnimation(first, uut);
227 215
         stackController.push(first, new CommandListenerAdapter());
228 216
         stackController.push(uut, new CommandListenerAdapter());
229 217
 
230
-        first.ensureViewIsCreated();
231
-        uut.ensureViewIsCreated();
232 218
         uut.onViewAppeared();
233 219
 
234 220
         assertThat(ViewHelper.isVisible(stackController.getTopBar().getTopTabs())).isTrue();
235
-        stackController.pop(Options.EMPTY, new CommandListenerAdapter() {
236
-            @Override
237
-            public void onSuccess(String childId) {
238
-                assertThat(ViewHelper.isVisible(stackController.getTopBar().getTopTabs())).isFalse();
239
-            }
240
-        });
221
+        disablePopAnimation(uut);
222
+        stackController.pop(Options.EMPTY, new CommandListenerAdapter());
223
+
224
+        first.onViewAppeared();
225
+
226
+        assertThat(ViewHelper.isVisible(stackController.getTopBar().getTopTabs())).isFalse();
241 227
     }
242 228
 
243 229
     @Test

+ 5
- 3
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.java 查看文件

@@ -22,6 +22,7 @@ import com.reactnativenavigation.utils.CommandListenerAdapter;
22 22
 import com.reactnativenavigation.utils.ImageLoader;
23 23
 import com.reactnativenavigation.utils.TitleBarHelper;
24 24
 import com.reactnativenavigation.utils.ViewHelper;
25
+import com.reactnativenavigation.utils.ViewUtils;
25 26
 import com.reactnativenavigation.viewcontrollers.ChildControllersRegistry;
26 27
 import com.reactnativenavigation.viewcontrollers.ParentController;
27 28
 import com.reactnativenavigation.viewcontrollers.ViewController;
@@ -82,7 +83,7 @@ public class StackControllerTest extends BaseTest {
82 83
         child3 = spy(new SimpleViewController(activity, childRegistry, "child3", new Options()));
83 84
         child4 = spy(new SimpleViewController(activity, childRegistry, "child4", new Options()));
84 85
         uut = createStack();
85
-        uut.ensureViewIsCreated();
86
+        activity.setContentView(uut.getView());
86 87
     }
87 88
 
88 89
     @Test
@@ -140,9 +141,7 @@ public class StackControllerTest extends BaseTest {
140 141
         child2.options.topBar.buttons.left = new ArrayList<>(Collections.singleton(TitleBarHelper.iconButton("someButton", "icon.png")));
141 142
 
142 143
         uut.push(child2, new CommandListenerAdapter());
143
-        child2.onViewAppeared();
144 144
         assertThat(topBarController.getView().getTitleBar().getNavigationIcon()).isNotNull();
145
-        verify(topBarController.getView(), times(1)).setLeftButtons(any());
146 145
         verify(topBarController.getView(), times(0)).setBackButton(any());
147 146
     }
148 147
 
@@ -674,6 +673,7 @@ public class StackControllerTest extends BaseTest {
674 673
     @Test
675 674
     public void pop_doesNotAnimateTopBarIfScreenIsPushedWithoutAnimation() {
676 675
         uut.ensureViewIsCreated();
676
+        disablePushAnimation(child1, child2);
677 677
 
678 678
         child1.options.topBar.visible = new Bool(false);
679 679
         child1.options.topBar.animate = new Bool(false);
@@ -720,6 +720,7 @@ public class StackControllerTest extends BaseTest {
720 720
 
721 721
     @Test
722 722
     public void stackCanBePushed() {
723
+        ViewUtils.removeFromParent(uut.getView());
723 724
         StackController parent = createStack("someStack");
724 725
         parent.ensureViewIsCreated();
725 726
         parent.push(uut, new CommandListenerAdapter());
@@ -729,6 +730,7 @@ public class StackControllerTest extends BaseTest {
729 730
 
730 731
     @Test
731 732
     public void applyOptions_applyOnlyOnFirstStack() {
733
+        ViewUtils.removeFromParent(uut.getView());
732 734
         StackController parent = spy(createStack("someStack"));
733 735
         parent.ensureViewIsCreated();
734 736
         parent.push(uut, new CommandListenerAdapter());

+ 1
- 1
playground/src/app.js 查看文件

@@ -38,7 +38,7 @@ function start() {
38 38
         }
39 39
       },
40 40
       _animations: {
41
-        startApp: {
41
+        setRoot: {
42 42
           y: {
43 43
             from: 1000,
44 44
             to: 0,