Browse Source

Sliding overlay (#651)

* WIP

* Core function works e2e

* Queued overlays support

* Remove unneeded activity ref

* Add post-PR changes
d4vidi 8 years ago
parent
commit
e283d44f2f

+ 60
- 0
android/app/src/main/java/com/reactnativenavigation/animation/PeekingAnimator.java View File

1
+package com.reactnativenavigation.animation;
2
+
3
+import android.animation.Animator;
4
+import android.animation.AnimatorSet;
5
+import android.animation.ObjectAnimator;
6
+import android.view.View;
7
+import android.view.animation.OvershootInterpolator;
8
+
9
+import static android.view.View.TRANSLATION_Y;
10
+
11
+public class PeekingAnimator {
12
+
13
+    private static final int SLIDE_OUT_DURATION = 300;
14
+    private static final int SLIDE_IN_DURATION = 600;
15
+    private static final int SUSTAIN_DURATION = 3000;
16
+
17
+    private final Animator animator;
18
+
19
+    public PeekingAnimator(View view) {
20
+        this.animator = createAnimator(view);
21
+    }
22
+
23
+    public void addListener(Animator.AnimatorListener listener) {
24
+        this.animator.addListener(listener);
25
+    }
26
+
27
+    public void animate() {
28
+        animator.start();
29
+    }
30
+
31
+    private Animator createAnimator(View view) {
32
+        final int heightPixels = view.getLayoutParams().height;
33
+
34
+        view.setTranslationY(-heightPixels);
35
+
36
+        ObjectAnimator slideIn = createSlideInAnimator(view);
37
+        ObjectAnimator slideOut = createSlideOutAnimator(view, heightPixels, slideIn);
38
+        AnimatorSet animatorSet = createAnimatorSet(slideIn, slideOut);
39
+        return animatorSet;
40
+    }
41
+
42
+    private ObjectAnimator createSlideInAnimator(View view) {
43
+        ObjectAnimator slideIn = ObjectAnimator.ofFloat(view, TRANSLATION_Y, 0);
44
+        slideIn.setDuration(SLIDE_IN_DURATION);
45
+        slideIn.setInterpolator(new OvershootInterpolator(0.8f));
46
+        return slideIn;
47
+    }
48
+
49
+    private ObjectAnimator createSlideOutAnimator(View view, int heightPixels, ObjectAnimator slideIn) {
50
+        ObjectAnimator slideOut = ObjectAnimator.ofFloat(view, TRANSLATION_Y, -heightPixels);
51
+        slideIn.setDuration(SLIDE_OUT_DURATION);
52
+        return slideOut;
53
+    }
54
+
55
+    private AnimatorSet createAnimatorSet(ObjectAnimator slideIn, ObjectAnimator slideOut) {
56
+        AnimatorSet animatorSet = new AnimatorSet();
57
+        animatorSet.play(slideOut).after(SUSTAIN_DURATION).after(slideIn);
58
+        return animatorSet;
59
+    }
60
+}

+ 8
- 0
android/app/src/main/java/com/reactnativenavigation/bridge/NavigationReactModule.java View File

9
 import com.reactnativenavigation.controllers.NavigationCommandsHandler;
9
 import com.reactnativenavigation.controllers.NavigationCommandsHandler;
10
 import com.reactnativenavigation.params.ContextualMenuParams;
10
 import com.reactnativenavigation.params.ContextualMenuParams;
11
 import com.reactnativenavigation.params.FabParams;
11
 import com.reactnativenavigation.params.FabParams;
12
+import com.reactnativenavigation.params.SlidingOverlayParams;
12
 import com.reactnativenavigation.params.SnackbarParams;
13
 import com.reactnativenavigation.params.SnackbarParams;
13
 import com.reactnativenavigation.params.TitleBarButtonParams;
14
 import com.reactnativenavigation.params.TitleBarButtonParams;
14
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
15
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
15
 import com.reactnativenavigation.params.parsers.ContextualMenuParamsParser;
16
 import com.reactnativenavigation.params.parsers.ContextualMenuParamsParser;
16
 import com.reactnativenavigation.params.parsers.FabParamsParser;
17
 import com.reactnativenavigation.params.parsers.FabParamsParser;
18
+import com.reactnativenavigation.params.parsers.SlidingOverlayParamsParser;
17
 import com.reactnativenavigation.params.parsers.SnackbarParamsParser;
19
 import com.reactnativenavigation.params.parsers.SnackbarParamsParser;
18
 import com.reactnativenavigation.params.parsers.TitleBarButtonParamsParser;
20
 import com.reactnativenavigation.params.parsers.TitleBarButtonParamsParser;
19
 import com.reactnativenavigation.params.parsers.TitleBarLeftButtonParamsParser;
21
 import com.reactnativenavigation.params.parsers.TitleBarLeftButtonParamsParser;
185
         NavigationCommandsHandler.dismissTopModal();
187
         NavigationCommandsHandler.dismissTopModal();
186
     }
188
     }
187
 
189
 
190
+    @ReactMethod
191
+    public void showSlidingOverlay(final ReadableMap params) {
192
+        SlidingOverlayParams slidingOverlayParams = new SlidingOverlayParamsParser().parse(BundleConverter.toBundle(params));
193
+        NavigationCommandsHandler.showSlidingOverlay(slidingOverlayParams);
194
+    }
195
+
188
     @ReactMethod
196
     @ReactMethod
189
     public void showSnackbar(final ReadableMap params) {
197
     public void showSnackbar(final ReadableMap params) {
190
         SnackbarParams snackbarParams = new SnackbarParamsParser().parse(BundleConverter.toBundle(params));
198
         SnackbarParams snackbarParams = new SnackbarParamsParser().parse(BundleConverter.toBundle(params));

+ 5
- 0
android/app/src/main/java/com/reactnativenavigation/controllers/NavigationActivity.java View File

26
 import com.reactnativenavigation.params.ContextualMenuParams;
26
 import com.reactnativenavigation.params.ContextualMenuParams;
27
 import com.reactnativenavigation.params.FabParams;
27
 import com.reactnativenavigation.params.FabParams;
28
 import com.reactnativenavigation.params.ScreenParams;
28
 import com.reactnativenavigation.params.ScreenParams;
29
+import com.reactnativenavigation.params.SlidingOverlayParams;
29
 import com.reactnativenavigation.params.SnackbarParams;
30
 import com.reactnativenavigation.params.SnackbarParams;
30
 import com.reactnativenavigation.params.TitleBarButtonParams;
31
 import com.reactnativenavigation.params.TitleBarButtonParams;
31
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
32
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
291
         }
292
         }
292
     }
293
     }
293
 
294
 
295
+    public void showSlidingOverlay(SlidingOverlayParams params) {
296
+        layout.showSlidingOverlay(params);
297
+    }
298
+
294
     public void showSnackbar(SnackbarParams params) {
299
     public void showSnackbar(SnackbarParams params) {
295
         layout.showSnackbar(params);
300
         layout.showSnackbar(params);
296
     }
301
     }

+ 15
- 0
android/app/src/main/java/com/reactnativenavigation/controllers/NavigationCommandsHandler.java View File

9
 import com.reactnativenavigation.params.ContextualMenuParams;
9
 import com.reactnativenavigation.params.ContextualMenuParams;
10
 import com.reactnativenavigation.params.FabParams;
10
 import com.reactnativenavigation.params.FabParams;
11
 import com.reactnativenavigation.params.ScreenParams;
11
 import com.reactnativenavigation.params.ScreenParams;
12
+import com.reactnativenavigation.params.SlidingOverlayParams;
12
 import com.reactnativenavigation.params.SnackbarParams;
13
 import com.reactnativenavigation.params.SnackbarParams;
13
 import com.reactnativenavigation.params.TitleBarButtonParams;
14
 import com.reactnativenavigation.params.TitleBarButtonParams;
14
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
15
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
336
         });
337
         });
337
     }
338
     }
338
 
339
 
340
+    public static void showSlidingOverlay(final SlidingOverlayParams params) {
341
+        final NavigationActivity currentActivity = NavigationActivity.currentActivity;
342
+        if (currentActivity == null) {
343
+            return;
344
+        }
345
+
346
+        NavigationApplication.instance.runOnMainThread(new Runnable() {
347
+            @Override
348
+            public void run() {
349
+                currentActivity.showSlidingOverlay(params);
350
+            }
351
+        });
352
+    }
353
+
339
     public static void showSnackbar(final SnackbarParams params) {
354
     public static void showSnackbar(final SnackbarParams params) {
340
         final NavigationActivity currentActivity = NavigationActivity.currentActivity;
355
         final NavigationActivity currentActivity = NavigationActivity.currentActivity;
341
         if (currentActivity == null) {
356
         if (currentActivity == null) {

+ 15
- 0
android/app/src/main/java/com/reactnativenavigation/layouts/BaseLayout.java View File

1
+package com.reactnativenavigation.layouts;
2
+
3
+import android.support.v7.app.AppCompatActivity;
4
+import android.widget.RelativeLayout;
5
+
6
+public abstract class BaseLayout extends RelativeLayout implements Layout {
7
+
8
+    public BaseLayout(AppCompatActivity activity) {
9
+        super(activity);
10
+    }
11
+
12
+    protected AppCompatActivity getActivity() {
13
+        return (AppCompatActivity) getContext();
14
+    }
15
+}

+ 12
- 5
android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java View File

18
 import com.reactnativenavigation.params.FabParams;
18
 import com.reactnativenavigation.params.FabParams;
19
 import com.reactnativenavigation.params.ScreenParams;
19
 import com.reactnativenavigation.params.ScreenParams;
20
 import com.reactnativenavigation.params.SideMenuParams;
20
 import com.reactnativenavigation.params.SideMenuParams;
21
+import com.reactnativenavigation.params.SlidingOverlayParams;
21
 import com.reactnativenavigation.params.SnackbarParams;
22
 import com.reactnativenavigation.params.SnackbarParams;
22
 import com.reactnativenavigation.params.TitleBarButtonParams;
23
 import com.reactnativenavigation.params.TitleBarButtonParams;
23
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
24
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
27
 import com.reactnativenavigation.views.SideMenu;
28
 import com.reactnativenavigation.views.SideMenu;
28
 import com.reactnativenavigation.views.SideMenu.Side;
29
 import com.reactnativenavigation.views.SideMenu.Side;
29
 import com.reactnativenavigation.views.SnackbarAndFabContainer;
30
 import com.reactnativenavigation.views.SnackbarAndFabContainer;
31
+import com.reactnativenavigation.views.slidingOverlay.SlidingOverlay;
32
+import com.reactnativenavigation.views.slidingOverlay.SlidingOverlaysQueue;
30
 
33
 
31
 import java.util.List;
34
 import java.util.List;
32
 
35
 
33
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
36
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
34
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
37
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
35
 
38
 
36
-public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottomNavigation.OnTabSelectedListener {
39
+public class BottomTabsLayout extends BaseLayout implements AHBottomNavigation.OnTabSelectedListener {
37
 
40
 
38
-    private final AppCompatActivity activity;
39
     private ActivityParams params;
41
     private ActivityParams params;
40
     private SnackbarAndFabContainer snackbarAndFabContainer;
42
     private SnackbarAndFabContainer snackbarAndFabContainer;
41
     private BottomTabs bottomTabs;
43
     private BottomTabs bottomTabs;
42
     private ScreenStack[] screenStacks;
44
     private ScreenStack[] screenStacks;
43
     private final SideMenuParams leftSideMenuParams;
45
     private final SideMenuParams leftSideMenuParams;
44
     private final SideMenuParams rightSideMenuParams;
46
     private final SideMenuParams rightSideMenuParams;
47
+    private final SlidingOverlaysQueue slidingOverlaysQueue = new SlidingOverlaysQueue();
45
     private @Nullable SideMenu sideMenu;
48
     private @Nullable SideMenu sideMenu;
46
     private int currentStackIndex = 0;
49
     private int currentStackIndex = 0;
47
 
50
 
48
     public BottomTabsLayout(AppCompatActivity activity, ActivityParams params) {
51
     public BottomTabsLayout(AppCompatActivity activity, ActivityParams params) {
49
         super(activity);
52
         super(activity);
50
-        this.activity = activity;
51
         this.params = params;
53
         this.params = params;
52
         leftSideMenuParams = params.leftSideMenuParams;
54
         leftSideMenuParams = params.leftSideMenuParams;
53
         rightSideMenuParams = params.rightSideMenuParams;
55
         rightSideMenuParams = params.rightSideMenuParams;
81
 
83
 
82
     private void createAndAddScreens(int position) {
84
     private void createAndAddScreens(int position) {
83
         ScreenParams screenParams = params.tabParams.get(position);
85
         ScreenParams screenParams = params.tabParams.get(position);
84
-        ScreenStack newStack = new ScreenStack(activity, getScreenStackParent(), screenParams.getNavigatorId(), this);
86
+        ScreenStack newStack = new ScreenStack(getActivity(), getScreenStackParent(), screenParams.getNavigatorId(), this);
85
         newStack.pushInitialScreen(screenParams, createScreenLayoutParams(screenParams));
87
         newStack.pushInitialScreen(screenParams, createScreenLayoutParams(screenParams));
86
         screenStacks[position] = newStack;
88
         screenStacks[position] = newStack;
87
     }
89
     }
209
         snackbarAndFabContainer.showSnackbar(eventId, params);
211
         snackbarAndFabContainer.showSnackbar(eventId, params);
210
     }
212
     }
211
 
213
 
214
+    @Override
215
+    public void showSlidingOverlay(final SlidingOverlayParams params) {
216
+        slidingOverlaysQueue.add(new SlidingOverlay(this, params));
217
+    }
218
+
212
     @Override
219
     @Override
213
     public void onModalDismissed() {
220
     public void onModalDismissed() {
214
         EventBus.instance.post(new ScreenChangedEvent(getCurrentScreenStack().peek().getScreenParams()));
221
         EventBus.instance.post(new ScreenChangedEvent(getCurrentScreenStack().peek().getScreenParams()));
277
         removeView(currentScreenStack.peek());
284
         removeView(currentScreenStack.peek());
278
         currentScreenStack.destroy();
285
         currentScreenStack.destroy();
279
 
286
 
280
-        ScreenStack newStack = new ScreenStack(activity, getScreenStackParent(), params.getNavigatorId(), this);
287
+        ScreenStack newStack = new ScreenStack(getActivity(), getScreenStackParent(), params.getNavigatorId(), this);
281
         LayoutParams lp = createScreenLayoutParams(params);
288
         LayoutParams lp = createScreenLayoutParams(params);
282
         newStack.pushInitialScreenWithAnimation(params, lp);
289
         newStack.pushInitialScreenWithAnimation(params, lp);
283
         screenStacks[currentStackIndex] = newStack;
290
         screenStacks[currentStackIndex] = newStack;

+ 3
- 0
android/app/src/main/java/com/reactnativenavigation/layouts/Layout.java View File

5
 import com.facebook.react.bridge.Callback;
5
 import com.facebook.react.bridge.Callback;
6
 import com.reactnativenavigation.params.ContextualMenuParams;
6
 import com.reactnativenavigation.params.ContextualMenuParams;
7
 import com.reactnativenavigation.params.FabParams;
7
 import com.reactnativenavigation.params.FabParams;
8
+import com.reactnativenavigation.params.SlidingOverlayParams;
8
 import com.reactnativenavigation.params.SnackbarParams;
9
 import com.reactnativenavigation.params.SnackbarParams;
9
 import com.reactnativenavigation.params.TitleBarButtonParams;
10
 import com.reactnativenavigation.params.TitleBarButtonParams;
10
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
11
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
36
 
37
 
37
     void showSnackbar(SnackbarParams params);
38
     void showSnackbar(SnackbarParams params);
38
 
39
 
40
+    void showSlidingOverlay(SlidingOverlayParams params);
41
+
39
     void onModalDismissed();
42
     void onModalDismissed();
40
 
43
 
41
     boolean containsNavigator(String navigatorId);
44
     boolean containsNavigator(String navigatorId);

+ 12
- 5
android/app/src/main/java/com/reactnativenavigation/layouts/SingleScreenLayout.java View File

13
 import com.reactnativenavigation.params.FabParams;
13
 import com.reactnativenavigation.params.FabParams;
14
 import com.reactnativenavigation.params.ScreenParams;
14
 import com.reactnativenavigation.params.ScreenParams;
15
 import com.reactnativenavigation.params.SideMenuParams;
15
 import com.reactnativenavigation.params.SideMenuParams;
16
+import com.reactnativenavigation.params.SlidingOverlayParams;
16
 import com.reactnativenavigation.params.SnackbarParams;
17
 import com.reactnativenavigation.params.SnackbarParams;
17
 import com.reactnativenavigation.params.TitleBarButtonParams;
18
 import com.reactnativenavigation.params.TitleBarButtonParams;
18
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
19
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
22
 import com.reactnativenavigation.views.SideMenu;
23
 import com.reactnativenavigation.views.SideMenu;
23
 import com.reactnativenavigation.views.SideMenu.Side;
24
 import com.reactnativenavigation.views.SideMenu.Side;
24
 import com.reactnativenavigation.views.SnackbarAndFabContainer;
25
 import com.reactnativenavigation.views.SnackbarAndFabContainer;
26
+import com.reactnativenavigation.views.slidingOverlay.SlidingOverlay;
27
+import com.reactnativenavigation.views.slidingOverlay.SlidingOverlaysQueue;
25
 
28
 
26
 import java.util.List;
29
 import java.util.List;
27
 
30
 
28
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
31
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
29
 
32
 
30
-public class SingleScreenLayout extends RelativeLayout implements Layout {
33
+public class SingleScreenLayout extends BaseLayout {
31
 
34
 
32
-    private final AppCompatActivity activity;
33
     protected final ScreenParams screenParams;
35
     protected final ScreenParams screenParams;
34
     private final SideMenuParams leftSideMenuParams;
36
     private final SideMenuParams leftSideMenuParams;
35
     private final SideMenuParams rightSideMenuParams;
37
     private final SideMenuParams rightSideMenuParams;
37
     private SnackbarAndFabContainer snackbarAndFabContainer;
39
     private SnackbarAndFabContainer snackbarAndFabContainer;
38
     protected LeftButtonOnClickListener leftButtonOnClickListener;
40
     protected LeftButtonOnClickListener leftButtonOnClickListener;
39
     private @Nullable SideMenu sideMenu;
41
     private @Nullable SideMenu sideMenu;
42
+    private final SlidingOverlaysQueue slidingOverlaysQueue = new SlidingOverlaysQueue();
40
 
43
 
41
     public SingleScreenLayout(AppCompatActivity activity, SideMenuParams leftSideMenuParams,
44
     public SingleScreenLayout(AppCompatActivity activity, SideMenuParams leftSideMenuParams,
42
                               SideMenuParams rightSideMenuParams, ScreenParams screenParams) {
45
                               SideMenuParams rightSideMenuParams, ScreenParams screenParams) {
43
         super(activity);
46
         super(activity);
44
-        this.activity = activity;
45
         this.screenParams = screenParams;
47
         this.screenParams = screenParams;
46
         this.leftSideMenuParams = leftSideMenuParams;
48
         this.leftSideMenuParams = leftSideMenuParams;
47
         this.rightSideMenuParams = rightSideMenuParams;
49
         this.rightSideMenuParams = rightSideMenuParams;
74
         if (stack != null) {
76
         if (stack != null) {
75
             stack.destroy();
77
             stack.destroy();
76
         }
78
         }
77
-        stack = new ScreenStack(activity, parent, screenParams.getNavigatorId(), this);
79
+        stack = new ScreenStack(getActivity(), parent, screenParams.getNavigatorId(), this);
78
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
80
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
79
         pushInitialScreen(lp);
81
         pushInitialScreen(lp);
80
     }
82
     }
148
         removeView(stack.peek());
150
         removeView(stack.peek());
149
         stack.destroy();
151
         stack.destroy();
150
 
152
 
151
-        ScreenStack newStack = new ScreenStack(activity, getScreenStackParent(), params.getNavigatorId(), this);
153
+        ScreenStack newStack = new ScreenStack(getActivity(), getScreenStackParent(), params.getNavigatorId(), this);
152
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
154
         LayoutParams lp = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
153
         newStack.pushInitialScreenWithAnimation(params, lp);
155
         newStack.pushInitialScreenWithAnimation(params, lp);
154
         stack = newStack;
156
         stack = newStack;
212
         snackbarAndFabContainer.showSnackbar(navigatorEventId, params);
214
         snackbarAndFabContainer.showSnackbar(navigatorEventId, params);
213
     }
215
     }
214
 
216
 
217
+    @Override
218
+    public void showSlidingOverlay(final SlidingOverlayParams params) {
219
+        slidingOverlaysQueue.add(new SlidingOverlay(this, params));
220
+    }
221
+
215
     @Override
222
     @Override
216
     public void onModalDismissed() {
223
     public void onModalDismissed() {
217
         EventBus.instance.post(new ScreenChangedEvent(stack.peek().getScreenParams()));
224
         EventBus.instance.post(new ScreenChangedEvent(stack.peek().getScreenParams()));

+ 6
- 0
android/app/src/main/java/com/reactnativenavigation/params/SlidingOverlayParams.java View File

1
+package com.reactnativenavigation.params;
2
+
3
+public class SlidingOverlayParams {
4
+    public String screenInstanceId;
5
+    public NavigationParams navigationParams;
6
+}

+ 16
- 0
android/app/src/main/java/com/reactnativenavigation/params/parsers/SlidingOverlayParamsParser.java View File

1
+package com.reactnativenavigation.params.parsers;
2
+
3
+import android.os.Bundle;
4
+
5
+import com.reactnativenavigation.params.NavigationParams;
6
+import com.reactnativenavigation.params.SlidingOverlayParams;
7
+
8
+public class SlidingOverlayParamsParser extends Parser {
9
+
10
+    public SlidingOverlayParams parse(Bundle bundle) {
11
+        final SlidingOverlayParams result = new SlidingOverlayParams();
12
+        result.screenInstanceId = bundle.getString("screen");
13
+        result.navigationParams = new NavigationParams(bundle.getBundle("navigationParams"));
14
+        return result;
15
+    }
16
+}

+ 79
- 0
android/app/src/main/java/com/reactnativenavigation/views/slidingOverlay/SlidingOverlay.java View File

1
+package com.reactnativenavigation.views.slidingOverlay;
2
+
3
+import android.animation.Animator;
4
+import android.animation.AnimatorListenerAdapter;
5
+import android.view.View;
6
+import android.widget.RelativeLayout;
7
+
8
+import com.reactnativenavigation.animation.PeekingAnimator;
9
+import com.reactnativenavigation.params.SlidingOverlayParams;
10
+import com.reactnativenavigation.screens.Screen;
11
+import com.reactnativenavigation.utils.ViewUtils;
12
+import com.reactnativenavigation.views.ContentView;
13
+
14
+public class SlidingOverlay {
15
+
16
+    private final RelativeLayout parent;
17
+    private final SlidingOverlayParams params;
18
+
19
+    private SlidingListener listener;
20
+
21
+    public interface SlidingListener {
22
+        void onSlidingOverlayGone();
23
+    }
24
+
25
+    public SlidingOverlay(RelativeLayout parent, SlidingOverlayParams params) {
26
+        this.parent = parent;
27
+        this.params = params;
28
+    }
29
+
30
+    public void setSlidingListener(SlidingListener listener) {
31
+        this.listener = listener;
32
+    }
33
+
34
+    public void show() {
35
+        final ContentView view = createSlidingOverlayView(params);
36
+        parent.addView(view);
37
+
38
+        final PeekingAnimator animator = new PeekingAnimator(view);
39
+        animator.addListener(new AnimatorListenerAdapter() {
40
+            @Override
41
+            public void onAnimationCancel(Animator animator) {
42
+                onSlidingOverlayEnd(view);
43
+            }
44
+
45
+            @Override
46
+            public void onAnimationEnd(Animator animator) {
47
+                onSlidingOverlayEnd(view);
48
+            }
49
+        });
50
+        view.setOnDisplayListener(new Screen.OnDisplayListener() {
51
+            @Override
52
+            public void onDisplay() {
53
+                view.setVisibility(View.VISIBLE);
54
+                animator.animate();
55
+            }
56
+        });
57
+    }
58
+
59
+    protected ContentView createSlidingOverlayView(SlidingOverlayParams params) {
60
+        final float heightPixels = ViewUtils.convertDpToPixel(100);
61
+
62
+        final RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, (int) heightPixels);
63
+        lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
64
+
65
+        final ContentView view = new ContentView(parent.getContext(), params.screenInstanceId, params.navigationParams);
66
+        view.setLayoutParams(lp);
67
+        view.setVisibility(View.INVISIBLE);
68
+        return view;
69
+    }
70
+
71
+    protected void onSlidingOverlayEnd(ContentView view) {
72
+        view.unmountReactView();
73
+        parent.removeView(view);
74
+
75
+        if (listener != null) {
76
+            listener.onSlidingOverlayGone();
77
+        }
78
+    }
79
+}

+ 42
- 0
android/app/src/main/java/com/reactnativenavigation/views/slidingOverlay/SlidingOverlaysQueue.java View File

1
+package com.reactnativenavigation.views.slidingOverlay;
2
+
3
+import com.reactnativenavigation.NavigationApplication;
4
+
5
+import java.util.LinkedList;
6
+import java.util.Queue;
7
+
8
+public class SlidingOverlaysQueue implements SlidingOverlay.SlidingListener{
9
+
10
+    protected Queue<SlidingOverlay> queue = new LinkedList<>();
11
+
12
+    public void add(final SlidingOverlay slidingOverlay) {
13
+        NavigationApplication.instance.runOnMainThread(new Runnable() {
14
+            @Override
15
+            public void run() {
16
+                queue.add(slidingOverlay);
17
+                if (queue.size() == 1) {
18
+                    dispatchNextSlidingOverlay();
19
+                }
20
+            }
21
+        });
22
+    }
23
+
24
+    @Override
25
+    public void onSlidingOverlayGone() {
26
+        queue.poll();
27
+        dispatchNextSlidingOverlay();
28
+    }
29
+
30
+    protected void dispatchNextSlidingOverlay() {
31
+        NavigationApplication.instance.runOnMainThread(new Runnable() {
32
+            @Override
33
+            public void run() {
34
+                final SlidingOverlay nextSlidingOverlay = queue.peek();
35
+                if (nextSlidingOverlay != null) {
36
+                    nextSlidingOverlay.setSlidingListener(SlidingOverlaysQueue.this);
37
+                    nextSlidingOverlay.show();
38
+                }
39
+            }
40
+        });
41
+    }
42
+}

+ 42
- 0
example/src/screens/InAppNotification.js View File

1
+import React, {Component} from 'react';
2
+import {
3
+  Text,
4
+  View,
5
+  TouchableHighlight,
6
+  StyleSheet,
7
+  Alert
8
+} from 'react-native';
9
+
10
+const styleSheet = StyleSheet.create({
11
+  container: {
12
+    flex: 1,
13
+    backgroundColor: 'white',
14
+    alignItems: 'center',
15
+    justifyContent: 'center',
16
+    marginLeft: 10,
17
+    marginRight: 10,
18
+    marginTop: 18,
19
+    marginBottom: 18
20
+  }
21
+});
22
+
23
+let globalCounter = 0;
24
+export default class InAppNotification extends Component {
25
+
26
+  constructor(props) {
27
+    super(props);
28
+    this._counter = globalCounter++;
29
+  }
30
+
31
+  render() {
32
+    const message = `I'm notification #${this._counter}!`;
33
+    return (
34
+      <View style={styleSheet.container}>
35
+          <Text style={{color: 'black', fontSize: 20}}>{message}</Text>
36
+          <TouchableHighlight onPress={() => Alert.alert(`You've tapped on notification #${this._counter}`, 'We hope you had fun!')}>
37
+            <Text>Tap Me</Text>
38
+          </TouchableHighlight>
39
+      </View>
40
+    );
41
+  }
42
+}

+ 13
- 1
example/src/screens/SideMenu.js View File

24
         <TouchableOpacity onPress={ this.onModalPress.bind(this) }>
24
         <TouchableOpacity onPress={ this.onModalPress.bind(this) }>
25
           <Text style={styles.button}>Show Modal Screen</Text>
25
           <Text style={styles.button}>Show Modal Screen</Text>
26
         </TouchableOpacity>
26
         </TouchableOpacity>
27
-      </View>
27
+
28
+        <TouchableOpacity onPress={ this.onShowInAppNotification.bind(this) }>
29
+          <Text style={styles.button}>Show In-App Notification</Text>
30
+        </TouchableOpacity>
31
+
32
+    </View>
28
     );
33
     );
29
   }
34
   }
30
   onReplaceTab2Press() {
35
   onReplaceTab2Press() {
45
     });
50
     });
46
   }
51
   }
47
 
52
 
53
+  onShowInAppNotification() {
54
+    this._toggleDrawer();
55
+    this.props.navigator.showInAppNotification({
56
+      screen: "example.InAppNotification"
57
+    });
58
+  }
59
+
48
   _toggleDrawer() {
60
   _toggleDrawer() {
49
     this.props.navigator.toggleDrawer({
61
     this.props.navigator.toggleDrawer({
50
       to: 'closed',
62
       to: 'closed',

+ 2
- 0
example/src/screens/index.android.js View File

7
 import SideMenu from './SideMenu';
7
 import SideMenu from './SideMenu';
8
 import ModalScreen from './ModalScreen';
8
 import ModalScreen from './ModalScreen';
9
 import CollapsingTopBarScreen from './CollapsingTopBarScreen';
9
 import CollapsingTopBarScreen from './CollapsingTopBarScreen';
10
+import InAppNotification from './InAppNotification';
10
 
11
 
11
 // register all screens of the app (including internal ones)
12
 // register all screens of the app (including internal ones)
12
 export function registerScreens() {
13
 export function registerScreens() {
17
   Navigation.registerComponent('example.ModalScreen', () => ModalScreen);
18
   Navigation.registerComponent('example.ModalScreen', () => ModalScreen);
18
   Navigation.registerComponent('example.SideMenu', () => SideMenu);
19
   Navigation.registerComponent('example.SideMenu', () => SideMenu);
19
   Navigation.registerComponent('example.CollapsingTopBarScreen', () => CollapsingTopBarScreen);
20
   Navigation.registerComponent('example.CollapsingTopBarScreen', () => CollapsingTopBarScreen);
21
+  Navigation.registerComponent('example.InAppNotification', () => InAppNotification);
20
 }
22
 }

+ 7
- 0
src/deprecated/platformSpecificDeprecated.android.js View File

363
   newPlatformSpecific.dismissAllModals();
363
   newPlatformSpecific.dismissAllModals();
364
 }
364
 }
365
 
365
 
366
+function showInAppNotification(params) {
367
+  params.navigationParams = {};
368
+  addNavigatorParams(params.navigationParams);
369
+  newPlatformSpecific.showInAppNotification(params);
370
+}
371
+
366
 function addNavigatorParams(screen, navigator = null, idx = '') {
372
 function addNavigatorParams(screen, navigator = null, idx = '') {
367
   screen.navigatorID = navigator ? navigator.navigatorID : _.uniqueId('navigatorID') + '_nav' + idx;
373
   screen.navigatorID = navigator ? navigator.navigatorID : _.uniqueId('navigatorID') + '_nav' + idx;
368
   screen.screenInstanceID = _.uniqueId('screenInstanceID');
374
   screen.screenInstanceID = _.uniqueId('screenInstanceID');
549
   showModal,
555
   showModal,
550
   dismissModal,
556
   dismissModal,
551
   dismissAllModals,
557
   dismissAllModals,
558
+  showInAppNotification,
552
   navigatorSetButtons,
559
   navigatorSetButtons,
553
   navigatorSetTabBadge,
560
   navigatorSetTabBadge,
554
   navigatorSetTitle,
561
   navigatorSetTitle,

+ 5
- 0
src/platformSpecific.android.js View File

61
   NativeReactModule.dismissAllModals();
61
   NativeReactModule.dismissAllModals();
62
 }
62
 }
63
 
63
 
64
+function showInAppNotification(params) {
65
+  NativeReactModule.showSlidingOverlay(params);
66
+}
67
+
64
 function savePassProps(params) {
68
 function savePassProps(params) {
65
   if (params.navigationParams && params.passProps) {
69
   if (params.navigationParams && params.passProps) {
66
     PropRegistry.save(params.navigationParams.screenInstanceID, params.passProps);
70
     PropRegistry.save(params.navigationParams.screenInstanceID, params.passProps);
145
   showModal,
149
   showModal,
146
   dismissTopModal,
150
   dismissTopModal,
147
   dismissAllModals,
151
   dismissAllModals,
152
+  showInAppNotification,
148
   toggleSideMenuVisible,
153
   toggleSideMenuVisible,
149
   setSideMenuVisible,
154
   setSideMenuVisible,
150
   selectBottomTabByNavigatorId,
155
   selectBottomTabByNavigatorId,