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

@@ -0,0 +1,60 @@
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,11 +9,13 @@ import com.facebook.react.bridge.ReadableMap;
9 9
 import com.reactnativenavigation.controllers.NavigationCommandsHandler;
10 10
 import com.reactnativenavigation.params.ContextualMenuParams;
11 11
 import com.reactnativenavigation.params.FabParams;
12
+import com.reactnativenavigation.params.SlidingOverlayParams;
12 13
 import com.reactnativenavigation.params.SnackbarParams;
13 14
 import com.reactnativenavigation.params.TitleBarButtonParams;
14 15
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
15 16
 import com.reactnativenavigation.params.parsers.ContextualMenuParamsParser;
16 17
 import com.reactnativenavigation.params.parsers.FabParamsParser;
18
+import com.reactnativenavigation.params.parsers.SlidingOverlayParamsParser;
17 19
 import com.reactnativenavigation.params.parsers.SnackbarParamsParser;
18 20
 import com.reactnativenavigation.params.parsers.TitleBarButtonParamsParser;
19 21
 import com.reactnativenavigation.params.parsers.TitleBarLeftButtonParamsParser;
@@ -185,6 +187,12 @@ public class NavigationReactModule extends ReactContextBaseJavaModule {
185 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 196
     @ReactMethod
189 197
     public void showSnackbar(final ReadableMap params) {
190 198
         SnackbarParams snackbarParams = new SnackbarParamsParser().parse(BundleConverter.toBundle(params));

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

@@ -26,6 +26,7 @@ import com.reactnativenavigation.params.AppStyle;
26 26
 import com.reactnativenavigation.params.ContextualMenuParams;
27 27
 import com.reactnativenavigation.params.FabParams;
28 28
 import com.reactnativenavigation.params.ScreenParams;
29
+import com.reactnativenavigation.params.SlidingOverlayParams;
29 30
 import com.reactnativenavigation.params.SnackbarParams;
30 31
 import com.reactnativenavigation.params.TitleBarButtonParams;
31 32
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
@@ -291,6 +292,10 @@ public class NavigationActivity extends AppCompatActivity implements DefaultHard
291 292
         }
292 293
     }
293 294
 
295
+    public void showSlidingOverlay(SlidingOverlayParams params) {
296
+        layout.showSlidingOverlay(params);
297
+    }
298
+
294 299
     public void showSnackbar(SnackbarParams params) {
295 300
         layout.showSnackbar(params);
296 301
     }

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

@@ -9,6 +9,7 @@ import com.reactnativenavigation.params.ActivityParams;
9 9
 import com.reactnativenavigation.params.ContextualMenuParams;
10 10
 import com.reactnativenavigation.params.FabParams;
11 11
 import com.reactnativenavigation.params.ScreenParams;
12
+import com.reactnativenavigation.params.SlidingOverlayParams;
12 13
 import com.reactnativenavigation.params.SnackbarParams;
13 14
 import com.reactnativenavigation.params.TitleBarButtonParams;
14 15
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
@@ -336,6 +337,20 @@ public class NavigationCommandsHandler {
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 354
     public static void showSnackbar(final SnackbarParams params) {
340 355
         final NavigationActivity currentActivity = NavigationActivity.currentActivity;
341 356
         if (currentActivity == null) {

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

@@ -0,0 +1,15 @@
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,6 +18,7 @@ import com.reactnativenavigation.params.ContextualMenuParams;
18 18
 import com.reactnativenavigation.params.FabParams;
19 19
 import com.reactnativenavigation.params.ScreenParams;
20 20
 import com.reactnativenavigation.params.SideMenuParams;
21
+import com.reactnativenavigation.params.SlidingOverlayParams;
21 22
 import com.reactnativenavigation.params.SnackbarParams;
22 23
 import com.reactnativenavigation.params.TitleBarButtonParams;
23 24
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
@@ -27,27 +28,28 @@ import com.reactnativenavigation.views.BottomTabs;
27 28
 import com.reactnativenavigation.views.SideMenu;
28 29
 import com.reactnativenavigation.views.SideMenu.Side;
29 30
 import com.reactnativenavigation.views.SnackbarAndFabContainer;
31
+import com.reactnativenavigation.views.slidingOverlay.SlidingOverlay;
32
+import com.reactnativenavigation.views.slidingOverlay.SlidingOverlaysQueue;
30 33
 
31 34
 import java.util.List;
32 35
 
33 36
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
34 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 41
     private ActivityParams params;
40 42
     private SnackbarAndFabContainer snackbarAndFabContainer;
41 43
     private BottomTabs bottomTabs;
42 44
     private ScreenStack[] screenStacks;
43 45
     private final SideMenuParams leftSideMenuParams;
44 46
     private final SideMenuParams rightSideMenuParams;
47
+    private final SlidingOverlaysQueue slidingOverlaysQueue = new SlidingOverlaysQueue();
45 48
     private @Nullable SideMenu sideMenu;
46 49
     private int currentStackIndex = 0;
47 50
 
48 51
     public BottomTabsLayout(AppCompatActivity activity, ActivityParams params) {
49 52
         super(activity);
50
-        this.activity = activity;
51 53
         this.params = params;
52 54
         leftSideMenuParams = params.leftSideMenuParams;
53 55
         rightSideMenuParams = params.rightSideMenuParams;
@@ -81,7 +83,7 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
81 83
 
82 84
     private void createAndAddScreens(int position) {
83 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 87
         newStack.pushInitialScreen(screenParams, createScreenLayoutParams(screenParams));
86 88
         screenStacks[position] = newStack;
87 89
     }
@@ -209,6 +211,11 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
209 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 219
     @Override
213 220
     public void onModalDismissed() {
214 221
         EventBus.instance.post(new ScreenChangedEvent(getCurrentScreenStack().peek().getScreenParams()));
@@ -277,7 +284,7 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
277 284
         removeView(currentScreenStack.peek());
278 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 288
         LayoutParams lp = createScreenLayoutParams(params);
282 289
         newStack.pushInitialScreenWithAnimation(params, lp);
283 290
         screenStacks[currentStackIndex] = newStack;

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

@@ -5,6 +5,7 @@ import android.view.View;
5 5
 import com.facebook.react.bridge.Callback;
6 6
 import com.reactnativenavigation.params.ContextualMenuParams;
7 7
 import com.reactnativenavigation.params.FabParams;
8
+import com.reactnativenavigation.params.SlidingOverlayParams;
8 9
 import com.reactnativenavigation.params.SnackbarParams;
9 10
 import com.reactnativenavigation.params.TitleBarButtonParams;
10 11
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
@@ -36,6 +37,8 @@ public interface Layout extends ScreenStackContainer {
36 37
 
37 38
     void showSnackbar(SnackbarParams params);
38 39
 
40
+    void showSlidingOverlay(SlidingOverlayParams params);
41
+
39 42
     void onModalDismissed();
40 43
 
41 44
     boolean containsNavigator(String navigatorId);

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

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

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

@@ -0,0 +1,6 @@
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

@@ -0,0 +1,16 @@
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

@@ -0,0 +1,79 @@
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

@@ -0,0 +1,42 @@
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

@@ -0,0 +1,42 @@
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,7 +24,12 @@ export default class SideMenu extends Component {
24 24
         <TouchableOpacity onPress={ this.onModalPress.bind(this) }>
25 25
           <Text style={styles.button}>Show Modal Screen</Text>
26 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 35
   onReplaceTab2Press() {
@@ -45,6 +50,13 @@ export default class SideMenu extends Component {
45 50
     });
46 51
   }
47 52
 
53
+  onShowInAppNotification() {
54
+    this._toggleDrawer();
55
+    this.props.navigator.showInAppNotification({
56
+      screen: "example.InAppNotification"
57
+    });
58
+  }
59
+
48 60
   _toggleDrawer() {
49 61
     this.props.navigator.toggleDrawer({
50 62
       to: 'closed',

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

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

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

@@ -363,6 +363,12 @@ function dismissAllModals(params) {
363 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 372
 function addNavigatorParams(screen, navigator = null, idx = '') {
367 373
   screen.navigatorID = navigator ? navigator.navigatorID : _.uniqueId('navigatorID') + '_nav' + idx;
368 374
   screen.screenInstanceID = _.uniqueId('screenInstanceID');
@@ -549,6 +555,7 @@ export default {
549 555
   showModal,
550 556
   dismissModal,
551 557
   dismissAllModals,
558
+  showInAppNotification,
552 559
   navigatorSetButtons,
553 560
   navigatorSetTabBadge,
554 561
   navigatorSetTitle,

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

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