소스 검색

Merge options into popped screen correctly

Options were merged after screen was popped from the backing stack data structure.
This meant that options were not resolved correctly for it as it was already detached from the stack.
This was especially noticeable when declaring a custom animation is mergeOptions passed to Navigation.pop().

Fixes #3869 and closes #4138
Guy Carmeli 6 년 전
부모
커밋
bc88c194f9

+ 7
- 3
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java 파일 보기

@@ -203,11 +203,15 @@ public class StackController extends ParentController<StackLayout> {
203 203
             return;
204 204
         }
205 205
 
206
+        peek().mergeOptions(mergeOptions);
207
+        Options disappearingOptions = resolveCurrentOptions();
208
+
206 209
         final ViewController disappearing = stack.pop();
207 210
         final ViewController appearing = stack.peek();
208
-        disappearing.mergeOptions(mergeOptions);
211
+
209 212
         disappearing.onViewWillDisappear();
210 213
         appearing.onViewWillAppear();
214
+
211 215
         Options resolvedOptions = resolveCurrentOptions();
212 216
         ViewGroup appearingView = appearing.getView();
213 217
         if (appearingView.getLayoutParams() == null) {
@@ -218,8 +222,8 @@ public class StackController extends ParentController<StackLayout> {
218 222
             getView().addView(appearingView, 0);
219 223
         }
220 224
         presenter.onChildWillAppear(appearing.options, disappearing.options);
221
-        if (disappearing.options.animations.pop.enabled.isTrueOrUndefined()) {
222
-            animator.pop(disappearing.getView(), resolvedOptions.animations.pop, () -> finishPopping(disappearing, listener));
225
+        if (disappearingOptions.animations.pop.enabled.isTrueOrUndefined()) {
226
+            animator.pop(disappearing.getView(), disappearingOptions.animations.pop, () -> finishPopping(disappearing, listener));
223 227
         } else {
224 228
             finishPopping(disappearing, listener);
225 229
         }

+ 31
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.java 파일 보기

@@ -1,5 +1,6 @@
1 1
 package com.reactnativenavigation.viewcontrollers.stack;
2 2
 
3
+import android.animation.Animator;
3 4
 import android.app.Activity;
4 5
 import android.content.Context;
5 6
 import android.view.View;
@@ -13,6 +14,7 @@ import com.reactnativenavigation.mocks.SimpleViewController;
13 14
 import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
14 15
 import com.reactnativenavigation.mocks.TopBarBackgroundViewCreatorMock;
15 16
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
17
+import com.reactnativenavigation.parse.AnimationOptions;
16 18
 import com.reactnativenavigation.parse.NestedAnimationsOptions;
17 19
 import com.reactnativenavigation.parse.Options;
18 20
 import com.reactnativenavigation.parse.params.Bool;
@@ -36,6 +38,7 @@ import com.reactnativenavigation.views.element.ElementTransitionManager;
36 38
 import com.reactnativenavigation.views.topbar.TopBar;
37 39
 
38 40
 import org.assertj.core.api.iterable.Extractor;
41
+import org.json.JSONException;
39 42
 import org.json.JSONObject;
40 43
 import org.junit.Test;
41 44
 import org.mockito.ArgumentCaptor;
@@ -317,7 +320,7 @@ public class StackControllerTest extends BaseTest {
317 320
     }
318 321
 
319 322
     @Test
320
-    public void popDoesNothingWhenZeroOrOneChild() {
323
+    public void pop_doesNothingWhenZeroOrOneChild() {
321 324
         assertThat(uut.isEmpty()).isTrue();
322 325
         uut.pop(Options.EMPTY, new CommandListenerAdapter());
323 326
         assertThat(uut.isEmpty()).isTrue();
@@ -327,6 +330,33 @@ public class StackControllerTest extends BaseTest {
327 330
         assertContainsOnlyId(child1.getId());
328 331
     }
329 332
 
333
+    @SuppressWarnings("MagicNumber")
334
+    @Test
335
+    public void pop_animationOptionsAreMergedCorrectlyToDisappearingChild() throws JSONException {
336
+        disablePushAnimation(child1, child2);
337
+
338
+        uut.push(child1, new CommandListenerAdapter());
339
+        uut.push(child2, new CommandListenerAdapter());
340
+
341
+        Options mergeOptions = new Options();
342
+        JSONObject content = new JSONObject();
343
+        JSONObject x = new JSONObject();
344
+        x.put("duration", 300);
345
+        x.put("from", 0);
346
+        x.put("to", 1000);
347
+        content.put("x", x);
348
+        mergeOptions.animations.pop.content = AnimationOptions.parse(content);
349
+
350
+        uut.pop(mergeOptions, new CommandListenerAdapter());
351
+        ArgumentCaptor<NestedAnimationsOptions> captor = ArgumentCaptor.forClass(NestedAnimationsOptions.class);
352
+        verify(animator, times(1)).pop(any(), captor.capture(), any());
353
+        Animator animator = captor.getValue().content
354
+                .getAnimation(mock(View.class))
355
+                .getChildAnimations()
356
+                .get(0);
357
+        assertThat(animator.getDuration()).isEqualTo(300);
358
+    }
359
+
330 360
     @Test
331 361
     public void canPopWhenSizeIsMoreThanOne() {
332 362
         assertThat(uut.isEmpty()).isTrue();