Browse Source

Initial implementation for Navigator.push

Navigator.push allows us to open a new screen. Currently it starts a new Activity with the screen
as it’s root view, but this is only a temporary behaviour. The intended behaviour is similar to
View Controllers on iOS which allows you to manage view hierarchies or a stack of fragments
managed by FragmentManager on Android.
Guy Carmeli 8 years ago
parent
commit
362b74fad8
25 changed files with 507 additions and 185 deletions
  1. 2
    1
      android/app/src/main/AndroidManifest.xml
  2. 10
    5
      android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java
  3. 0
    21
      android/app/src/main/java/com/reactnativenavigation/activities/CompoundReactActivity.java
  4. 0
    2
      android/app/src/main/java/com/reactnativenavigation/activities/RctActivity.java
  5. 43
    0
      android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java
  6. 6
    42
      android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java
  7. 0
    24
      android/app/src/main/java/com/reactnativenavigation/adapters/Page.java
  8. 8
    21
      android/app/src/main/java/com/reactnativenavigation/adapters/ViewPagerAdapter.java
  9. 38
    0
      android/app/src/main/java/com/reactnativenavigation/core/Screen.java
  10. 28
    10
      android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java
  11. 1
    1
      android/app/src/main/java/com/reactnativenavigation/packages/RnnPackage.java
  12. 13
    4
      android/app/src/main/java/com/reactnativenavigation/views/RctView.java
  13. 24
    0
      android/app/src/main/res/layout/single_screen_activity.xml
  14. 20
    25
      android/app/src/main/res/layout/tab_activity.xml
  15. 3
    0
      example/android/app/build.gradle
  16. 6
    28
      example/android/app/src/main/java/com/example/MainActivity.java
  17. 3
    0
      example/android/settings.gradle
  18. 19
    0
      example/src/app.js
  19. 111
    0
      example/src/screens/FirstTabScreen.android.js
  20. 0
    0
      example/src/screens/FirstTabScreen.ios.js
  21. 133
    0
      example/src/screens/SecondTabScreen.android.js
  22. 0
    0
      example/src/screens/SecondTabScreen.ios.js
  23. 20
    0
      example/src/screens/index.android.js
  24. 0
    0
      example/src/screens/index.ios.js
  25. 19
    1
      src/platformSpecific.android.js

+ 2
- 1
android/app/src/main/AndroidManifest.xml View File

@@ -3,7 +3,8 @@
3 3
 
4 4
     <application>
5 5
       <activity android:name="com.reactnativenavigation.activities.RctActivity" />
6
-        <activity android:name="com.reactnativenavigation.activities.TabActivity" />
6
+      <activity android:name="com.reactnativenavigation.activities.TabActivity" />
7
+      <activity android:name="com.reactnativenavigation.activities.SingleScreenActivity" />
7 8
     </application>
8 9
 
9 10
 </manifest>

+ 10
- 5
android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java View File

@@ -20,8 +20,9 @@ import com.facebook.react.ReactRootView;
20 20
 import com.facebook.react.common.ReactConstants;
21 21
 import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
22 22
 import com.facebook.react.shell.MainReactPackage;
23
+import com.reactnativenavigation.BuildConfig;
23 24
 import com.reactnativenavigation.core.RctManager;
24
-import com.reactnativenavigation.packages.RCCPackage;
25
+import com.reactnativenavigation.packages.RnnPackage;
25 26
 import com.reactnativenavigation.utils.ContextProvider;
26 27
 
27 28
 import java.util.Arrays;
@@ -32,7 +33,7 @@ import javax.annotation.Nullable;
32 33
 /**
33 34
  * Base Activity for React Native applications.
34 35
  */
35
-public abstract class BaseReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
36
+public class BaseReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
36 37
 
37 38
     private static final String REDBOX_PERMISSION_MESSAGE =
38 39
             "Overlay permissions needs to be granted in order for react native apps to run in dev mode";
@@ -88,12 +89,16 @@ public abstract class BaseReactActivity extends AppCompatActivity implements Def
88 89
      * This is used to schedule rendering of the component.
89 90
      * e.g. "MoviesApp"
90 91
      */
91
-    protected abstract String getMainComponentName();
92
+    protected String getMainComponentName() {
93
+        return "";
94
+    }
92 95
 
93 96
     /**
94 97
      * Returns whether dev mode should be enabled. This enables e.g. the dev menu.
95 98
      */
96
-    protected abstract boolean getUseDeveloperSupport();
99
+    protected boolean getUseDeveloperSupport() {
100
+        return BuildConfig.DEBUG;
101
+    }
97 102
 
98 103
     /**
99 104
      * Returns a list of {@link ReactPackage} used by the app.
@@ -104,7 +109,7 @@ public abstract class BaseReactActivity extends AppCompatActivity implements Def
104 109
     protected List<ReactPackage> getPackages() {
105 110
         return Arrays.asList(
106 111
                 new MainReactPackage(),
107
-                new RCCPackage()
112
+                new RnnPackage()
108 113
         );
109 114
     }
110 115
 

+ 0
- 21
android/app/src/main/java/com/reactnativenavigation/activities/CompoundReactActivity.java View File

@@ -1,21 +0,0 @@
1
-package com.reactnativenavigation.activities;
2
-
3
-import com.reactnativenavigation.BuildConfig;
4
-
5
-/**
6
- * Base Activity for React Native applications.
7
- *
8
- * Created by guyc on 02/04/16.
9
- */
10
-public class CompoundReactActivity extends BaseReactActivity {
11
-    @Override
12
-    protected String getMainComponentName() {
13
-        return "";
14
-    }
15
-
16
-    @Override
17
-    protected boolean getUseDeveloperSupport() {
18
-        return BuildConfig.DEBUG;
19
-    }
20
-}
21
-

+ 0
- 2
android/app/src/main/java/com/reactnativenavigation/activities/RctActivity.java View File

@@ -25,14 +25,12 @@ public class RctActivity extends BaseReactActivity {
25 25
 
26 26
     @Override
27 27
     public void onCreate(Bundle savedInstanceState) {
28
-        Log.v(TAG, "onCreate");
29 28
         if (mComponentName == null) {
30 29
             Intent intent = getIntent();
31 30
             assert intent != null;
32 31
             mComponentName = intent.getStringExtra(EXTRA_COMPONENT_NAME);
33 32
             assert mComponentName != null;
34 33
         }
35
-        Log.v(TAG, "mComponentName: " + mComponentName);
36 34
 
37 35
         super.onCreate(savedInstanceState);
38 36
     }

+ 43
- 0
android/app/src/main/java/com/reactnativenavigation/activities/SingleScreenActivity.java View File

@@ -0,0 +1,43 @@
1
+package com.reactnativenavigation.activities;
2
+
3
+import android.support.v7.widget.Toolbar;
4
+import android.view.View;
5
+import android.widget.FrameLayout;
6
+
7
+import com.reactnativenavigation.R;
8
+import com.reactnativenavigation.core.RctManager;
9
+import com.reactnativenavigation.core.Screen;
10
+import com.reactnativenavigation.views.RctView;
11
+
12
+/**
13
+ * Created by guyc on 05/04/16.
14
+ */
15
+public class SingleScreenActivity extends BaseReactActivity {
16
+
17
+    public static final String EXTRA_SCREEN = "extraScreen";
18
+
19
+    private Toolbar mToolbar;
20
+    private FrameLayout mContentFrame;
21
+
22
+    @Override
23
+    protected void handleOnCreate() {
24
+        mReactInstanceManager = RctManager.getInstance().getReactInstanceManager();
25
+
26
+        setContentView(R.layout.single_screen_activity);
27
+        mToolbar = (Toolbar) findViewById(R.id.toolbar);
28
+        mContentFrame = (FrameLayout) findViewById(R.id.contentFrame);
29
+
30
+        Screen screen = (Screen) getIntent().getSerializableExtra(EXTRA_SCREEN);
31
+        setupToolbar(screen.title);
32
+        setupReactView(screen);
33
+    }
34
+
35
+    private void setupToolbar(String title) {
36
+        mToolbar.setTitle(title);
37
+    }
38
+
39
+    private void setupReactView(Screen screen) {
40
+        View view = new RctView(this, mReactInstanceManager, screen);
41
+        mContentFrame.addView(view);
42
+    }
43
+}

+ 6
- 42
android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java View File

@@ -1,13 +1,11 @@
1 1
 package com.reactnativenavigation.activities;
2 2
 
3
-import android.os.Bundle;
4 3
 import android.support.design.widget.TabLayout;
5 4
 import android.support.v4.view.ViewPager;
6 5
 import android.support.v7.widget.Toolbar;
7
-import android.util.Log;
8 6
 
9 7
 import com.reactnativenavigation.R;
10
-import com.reactnativenavigation.adapters.Page;
8
+import com.reactnativenavigation.core.Screen;
11 9
 import com.reactnativenavigation.adapters.ViewPagerAdapter;
12 10
 import com.reactnativenavigation.core.RctManager;
13 11
 
@@ -16,20 +14,13 @@ import java.util.ArrayList;
16 14
 /**
17 15
  * Created by guyc on 02/04/16.
18 16
  */
19
-public class TabActivity extends CompoundReactActivity {
20
-    private static final String TAG = "TabActivity";
21
-    public static final String EXTRA_TABS = "extraTabs";
17
+public class TabActivity extends BaseReactActivity {
18
+    public static final String EXTRA_SCREENS = "extraTabs";
22 19
 
23 20
     private Toolbar mToolbar;
24 21
     private TabLayout mTabLayout;
25 22
     private ViewPager mViewPager;
26 23
 
27
-    @Override
28
-    public void onCreate(Bundle savedInstanceState) {
29
-        Log.v(TAG, "onCreate");
30
-        super.onCreate(savedInstanceState);
31
-    }
32
-
33 24
     @Override
34 25
     protected void handleOnCreate() {
35 26
         mReactInstanceManager = RctManager.getInstance().getReactInstanceManager();
@@ -43,42 +34,15 @@ public class TabActivity extends CompoundReactActivity {
43 34
         setupViews();
44 35
     }
45 36
 
46
-
47 37
     private void setupToolbar() {
48 38
         setSupportActionBar(mToolbar);
49 39
     }
40
+
50 41
     private void setupViews() {
51
-        ArrayList<Page> pages = (ArrayList<Page>) getIntent().getSerializableExtra(EXTRA_TABS);
52
-        ViewPagerAdapter adapter = new ViewPagerAdapter(this, pages);
42
+        ArrayList<Screen> screens = (ArrayList<Screen>) getIntent().getSerializableExtra(EXTRA_SCREENS);
43
+        ViewPagerAdapter adapter = new ViewPagerAdapter(this, screens);
53 44
         mViewPager.setAdapter(adapter);
54 45
         mTabLayout.setupWithViewPager(mViewPager);
55 46
         adapter.notifyDataSetChanged();
56 47
     }
57
-
58
-    @Override
59
-    protected void onStart() {
60
-        Log.v(TAG, "onStart");
61
-        super.onStart();
62
-    }
63
-
64
-    @Override
65
-    protected void onResume() {
66
-        Log.v(TAG, "onResume");
67
-        super.onResume();
68
-    }
69
-
70
-    @Override
71
-    protected void onPause() {
72
-        super.onPause();
73
-    }
74
-
75
-    @Override
76
-    protected void onStop() {
77
-        super.onStop();
78
-    }
79
-
80
-    @Override
81
-    protected void onDestroy() {
82
-        super.onDestroy();
83
-    }
84 48
 }

+ 0
- 24
android/app/src/main/java/com/reactnativenavigation/adapters/Page.java View File

@@ -1,24 +0,0 @@
1
-package com.reactnativenavigation.adapters;
2
-
3
-import com.facebook.react.bridge.ReadableMap;
4
-
5
-import java.io.Serializable;
6
-
7
-/**
8
- *
9
- * Created by guyc on 02/04/16.
10
- */
11
-public class Page implements Serializable {
12
-    private static final long serialVersionUID = -1033475305421107791L;
13
-    private static final String KEY_TITLE = "title";
14
-    private static final String KEY_SCREEN = "screen";
15
-    private static final String KEY_LABEL = "label";
16
-
17
-    /*package*/ String title;
18
-    /*package*/ String screenId;
19
-
20
-    public Page(ReadableMap page) {
21
-        title = page.getString(KEY_TITLE);
22
-        screenId = page.getString(KEY_SCREEN);
23
-    }
24
-}

+ 8
- 21
android/app/src/main/java/com/reactnativenavigation/adapters/ViewPagerAdapter.java View File

@@ -1,43 +1,38 @@
1 1
 package com.reactnativenavigation.adapters;
2 2
 
3 3
 import android.support.v4.view.PagerAdapter;
4
-import android.util.Log;
5 4
 import android.view.View;
6 5
 import android.view.ViewGroup;
7 6
 
8 7
 import com.facebook.react.ReactInstanceManager;
9
-import com.facebook.react.bridge.ReadableArray;
10 8
 import com.reactnativenavigation.activities.BaseReactActivity;
11 9
 import com.reactnativenavigation.core.RctManager;
10
+import com.reactnativenavigation.core.Screen;
12 11
 import com.reactnativenavigation.views.RctView;
13 12
 
14 13
 import java.util.ArrayList;
15 14
 
16 15
 /**
17
- *
18 16
  * Created by guyc on 02/04/16.
19 17
  */
20 18
 public class ViewPagerAdapter extends PagerAdapter {
21 19
 
22
-    private static final String TAG = "ViewPagerAdapter";
23 20
     private BaseReactActivity mContext;
24
-    private final ArrayList<Page> mPages;
21
+    private final ArrayList<Screen> mScreens;
25 22
     private final ReactInstanceManager mReactInstanceManager;
26 23
 
27
-    public ViewPagerAdapter(BaseReactActivity context, ArrayList<Page> pages) {
24
+    public ViewPagerAdapter(BaseReactActivity context, ArrayList<Screen> screens) {
28 25
         mContext = context;
29
-        mPages = pages;
26
+        mScreens = screens;
30 27
         mReactInstanceManager = RctManager.getInstance().getReactInstanceManager();
31 28
     }
32 29
 
33 30
     @Override
34 31
     public Object instantiateItem(ViewGroup container, int position) {
35
-        Log.v(TAG, "instantiateItem" + position);
36
-        String screenId = mPages.get(position).screenId;
37
-        View view = new RctView(mContext, mReactInstanceManager, screenId);
32
+        Screen screen = mScreens.get(position);
33
+        View view = new RctView(mContext, mReactInstanceManager, screen);
38 34
         container.addView(view);
39 35
         return view;
40
-
41 36
     }
42 37
 
43 38
     @Override
@@ -47,7 +42,7 @@ public class ViewPagerAdapter extends PagerAdapter {
47 42
 
48 43
     @Override
49 44
     public int getCount() {
50
-        return mPages.size();
45
+        return mScreens.size();
51 46
     }
52 47
 
53 48
     @Override
@@ -57,14 +52,6 @@ public class ViewPagerAdapter extends PagerAdapter {
57 52
 
58 53
     @Override
59 54
     public CharSequence getPageTitle(int position) {
60
-        return mPages.get(position).title;
61
-    }
62
-
63
-    public static ArrayList<Page> createDataSet(ReadableArray tabs) {
64
-        ArrayList<Page> ret = new ArrayList<>();
65
-        for(int i = 0; i < tabs.size(); i++) {
66
-            ret.add(new Page(tabs.getMap(i)));
67
-        }
68
-        return ret;
55
+        return mScreens.get(position).title;
69 56
     }
70 57
 }

+ 38
- 0
android/app/src/main/java/com/reactnativenavigation/core/Screen.java View File

@@ -0,0 +1,38 @@
1
+package com.reactnativenavigation.core;
2
+
3
+import com.facebook.react.bridge.ReadableMap;
4
+
5
+import java.io.Serializable;
6
+
7
+/**
8
+ * Created by guyc on 02/04/16.
9
+ */
10
+public class Screen implements Serializable {
11
+    private static final long serialVersionUID = -1033475305421107791L;
12
+    private static final String KEY_TITLE = "title";
13
+    private static final String KEY_SCREEN = "screen";
14
+    public static final String KEY_SCREEN_INSTANCE_ID = "screenInstanceID";
15
+    public static final String KEY_STACK_ID = "stackID";
16
+    public static final String KEY_NAVIGATOR_ID = "navigatorID";
17
+    public static final String KEY_NAVIGATOR_EVENT_ID = "navigatorEventID";
18
+
19
+    public String title;
20
+    public String screenId;
21
+    public String screenInstanceId;
22
+    public String stackId;
23
+    public String navigatorId;
24
+    public String navigatorEventId;
25
+
26
+    public Screen(ReadableMap screen) {
27
+        title = getString(screen, KEY_TITLE);
28
+        screenId = getString(screen, KEY_SCREEN);
29
+        screenInstanceId = getString(screen, KEY_SCREEN_INSTANCE_ID);
30
+        stackId = getString(screen, KEY_STACK_ID);
31
+        navigatorId = getString(screen, KEY_NAVIGATOR_ID);
32
+        navigatorEventId = getString(screen, KEY_NAVIGATOR_EVENT_ID);
33
+    }
34
+
35
+    private String getString(ReadableMap map, String key) {
36
+        return map.hasKey(key) ? map.getString(key) : null;
37
+    }
38
+}

+ 28
- 10
android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java View File

@@ -3,19 +3,21 @@ package com.reactnativenavigation.modules;
3 3
 import android.app.Activity;
4 4
 import android.content.Intent;
5 5
 import android.os.Bundle;
6
-import android.util.Log;
7 6
 
8 7
 import com.facebook.react.bridge.ReactApplicationContext;
9 8
 import com.facebook.react.bridge.ReactContextBaseJavaModule;
10 9
 import com.facebook.react.bridge.ReactMethod;
11 10
 import com.facebook.react.bridge.ReadableArray;
11
+import com.facebook.react.bridge.ReadableMap;
12 12
 import com.reactnativenavigation.activities.RctActivity;
13
+import com.reactnativenavigation.activities.SingleScreenActivity;
13 14
 import com.reactnativenavigation.activities.TabActivity;
14
-import com.reactnativenavigation.adapters.ViewPagerAdapter;
15
+import com.reactnativenavigation.core.Screen;
15 16
 import com.reactnativenavigation.utils.ContextProvider;
16 17
 
18
+import java.util.ArrayList;
19
+
17 20
 /**
18
- *
19 21
  * Created by guyc on 10/03/16.
20 22
  */
21 23
 public class RctActivityModule extends ReactContextBaseJavaModule {
@@ -41,19 +43,35 @@ public class RctActivityModule extends ReactContextBaseJavaModule {
41 43
     }
42 44
 
43 45
     @ReactMethod
44
-    public void startTabBasedApp(ReadableArray tabs) {
45
-        Log.v(REACT_CLASS, "Starting tab based app\n" + tabs);
46
-
47
-
46
+    public void startTabBasedApp(ReadableArray screens) {
48 47
         Activity context = ContextProvider.getActivityContext();
49 48
         if (context != null && !context.isFinishing()) {
50
-            // Create the intent
51 49
             Intent intent = new Intent(context, TabActivity.class);
52 50
 
51
+            Bundle extras = new Bundle();
52
+            extras.putSerializable(TabActivity.EXTRA_SCREENS, createScreens(screens));
53
+            intent.putExtras(extras);
54
+
55
+            context.startActivity(intent);
56
+        }
57
+    }
58
+
59
+    private ArrayList<Screen> createScreens(ReadableArray screens) {
60
+        ArrayList<Screen> ret = new ArrayList<>();
61
+        for(int i = 0; i < screens.size(); i++) {
62
+            ret.add(new Screen(screens.getMap(i)));
63
+        }
64
+        return ret;
65
+    }
66
+
67
+    @ReactMethod
68
+    public void navigatorPush(ReadableMap screen) {
69
+        Activity context = ContextProvider.getActivityContext();
70
+        if (context != null && !context.isFinishing()) {
71
+            Intent intent = new Intent(context, SingleScreenActivity.class);
53 72
 
54
-            // Set extras
55 73
             Bundle extras = new Bundle();
56
-            extras.putSerializable(TabActivity.EXTRA_TABS, ViewPagerAdapter.createDataSet(tabs));
74
+            extras.putSerializable(SingleScreenActivity.EXTRA_SCREEN, new Screen(screen));
57 75
             intent.putExtras(extras);
58 76
 
59 77
             context.startActivity(intent);

android/app/src/main/java/com/reactnativenavigation/packages/RCCPackage.java → android/app/src/main/java/com/reactnativenavigation/packages/RnnPackage.java View File

@@ -19,7 +19,7 @@ import java.util.List;
19 19
  *
20 20
  * Created by guyc on 07/03/16.
21 21
  */
22
-public class RCCPackage implements ReactPackage {
22
+public class RnnPackage implements ReactPackage {
23 23
 
24 24
     @Override
25 25
     public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {

+ 13
- 4
android/app/src/main/java/com/reactnativenavigation/views/RctView.java View File

@@ -1,25 +1,34 @@
1 1
 package com.reactnativenavigation.views;
2 2
 
3
+import android.os.Bundle;
3 4
 import android.widget.FrameLayout;
4 5
 
5 6
 import com.facebook.react.ReactInstanceManager;
6 7
 import com.facebook.react.ReactRootView;
7 8
 import com.reactnativenavigation.activities.BaseReactActivity;
8
-
9
+import com.reactnativenavigation.core.Screen;
9 10
 
10 11
 /**
11
- *
12 12
  * Created by guyc on 10/03/16.
13 13
  */
14 14
 public class RctView extends FrameLayout {
15 15
 
16
-    public RctView(BaseReactActivity ctx, ReactInstanceManager rctInstanceManager, String componentName) {
16
+    public RctView(BaseReactActivity ctx, ReactInstanceManager rctInstanceManager, Screen screen) {
17 17
         super(ctx);
18 18
         setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
19 19
 
20 20
         ReactRootView root = new ReactRootView(ctx);
21 21
         root.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
22
-        root.startReactApplication(rctInstanceManager, componentName, null);
22
+
23
+        String componentName = screen.screenId;
24
+        Bundle passProps = new Bundle();
25
+        passProps.putString(Screen.KEY_SCREEN_INSTANCE_ID, screen.screenInstanceId);
26
+        passProps.putString(Screen.KEY_STACK_ID, screen.stackId);
27
+        passProps.putString(Screen.KEY_NAVIGATOR_ID, screen.navigatorId);
28
+        passProps.putString(Screen.KEY_NAVIGATOR_EVENT_ID, screen.navigatorEventId);
29
+
30
+        root.startReactApplication(rctInstanceManager, componentName, passProps);
31
+
23 32
         addView(root);
24 33
 
25 34
         rctInstanceManager.onResume(ctx, ctx);

+ 24
- 0
android/app/src/main/res/layout/single_screen_activity.xml View File

@@ -0,0 +1,24 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
+    xmlns:app="http://schemas.android.com/apk/res-auto"
4
+    android:orientation="vertical"
5
+    android:layout_width="match_parent"
6
+    android:layout_height="match_parent">
7
+
8
+    <android.support.design.widget.AppBarLayout
9
+        android:id="@+id/appbar"
10
+        android:layout_width="match_parent"
11
+        android:layout_height="wrap_content"
12
+        android:fitsSystemWindows="true">
13
+        <android.support.v7.widget.Toolbar
14
+            android:id="@+id/toolbar"
15
+            android:layout_width="match_parent"
16
+            android:layout_height="?attr/actionBarSize"
17
+            app:layout_scrollFlags="scroll|enterAlways"/>
18
+    </android.support.design.widget.AppBarLayout>
19
+
20
+    <FrameLayout
21
+        android:id="@+id/contentFrame"
22
+        android:layout_width="match_parent"
23
+        android:layout_height="match_parent"/>
24
+</LinearLayout>

+ 20
- 25
android/app/src/main/res/layout/tab_activity.xml View File

@@ -1,33 +1,28 @@
1 1
 <?xml version="1.0" encoding="utf-8"?>
2 2
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
-              xmlns:tools="http://schemas.android.com/tools"
4
-              xmlns:app="http://schemas.android.com/apk/res-auto"
5
-              android:orientation="vertical"
6
-              android:layout_width="match_parent"
7
-              android:layout_height="match_parent"
8
-              tools:context=".activities.TabActivity">
3
+    xmlns:tools="http://schemas.android.com/tools"
4
+    xmlns:app="http://schemas.android.com/apk/res-auto"
5
+    android:orientation="vertical"
6
+    android:layout_width="match_parent"
7
+    android:layout_height="match_parent"
8
+    tools:context=".activities.TabActivity">
9 9
 
10
-    <android.support.design.widget.CoordinatorLayout
11
-        android:id="@+id/coordinator_layout"
10
+    <android.support.design.widget.AppBarLayout
11
+        android:id="@+id/appbar"
12 12
         android:layout_width="match_parent"
13
-        android:layout_height="wrap_content">
14
-        <android.support.design.widget.AppBarLayout
15
-            android:id="@+id/appbar"
13
+        android:layout_height="wrap_content"
14
+        android:fitsSystemWindows="true">
15
+        <android.support.v7.widget.Toolbar
16
+            android:id="@+id/toolbar"
16 17
             android:layout_width="match_parent"
17
-            android:layout_height="wrap_content"
18
-            android:fitsSystemWindows="true">
19
-            <android.support.v7.widget.Toolbar
20
-                android:id="@+id/toolbar"
21
-                android:layout_width="match_parent"
22
-                android:layout_height="?attr/actionBarSize"
23
-                app:layout_scrollFlags="scroll|enterAlways"/>
24
-            <android.support.design.widget.TabLayout
25
-                android:id="@+id/tabLayout"
26
-                android:layout_width="match_parent"
27
-                android:layout_height="?attr/actionBarSize"
28
-                app:layout_scrollFlags="scroll|enterAlways"/>
29
-        </android.support.design.widget.AppBarLayout>
30
-    </android.support.design.widget.CoordinatorLayout>
18
+            android:layout_height="?attr/actionBarSize"
19
+            app:layout_scrollFlags="scroll|enterAlways"/>
20
+        <android.support.design.widget.TabLayout
21
+            android:id="@+id/tabLayout"
22
+            android:layout_width="match_parent"
23
+            android:layout_height="?attr/actionBarSize"
24
+            app:layout_scrollFlags="scroll|enterAlways"/>
25
+    </android.support.design.widget.AppBarLayout>
31 26
 
32 27
     <android.support.v4.view.ViewPager
33 28
         android:id="@+id/viewPager"

+ 3
- 0
example/android/app/build.gradle View File

@@ -123,4 +123,7 @@ dependencies {
123 123
     compile fileTree(dir: "libs", include: ["*.jar"])
124 124
     compile "com.android.support:appcompat-v7:23.0.1"
125 125
     compile "com.facebook.react:react-native:+"  // From node_modules
126
+        debugCompile project(path: ':react-native-navigation', configuration: 'libraryDebug')
127
+        releaseCompile project(path: ':react-native-navigation', configuration: 'libraryRelease')
128
+//    compile project(':react-native-navigation')
126 129
 }

+ 6
- 28
example/android/app/src/main/java/com/example/MainActivity.java View File

@@ -1,40 +1,18 @@
1 1
 package com.example;
2 2
 
3
-import com.facebook.react.ReactActivity;
4
-import com.facebook.react.ReactPackage;
5
-import com.facebook.react.shell.MainReactPackage;
6 3
 
7
-import java.util.Arrays;
8
-import java.util.List;
4
+import com.reactnativenavigation.activities.RctActivity;
9 5
 
10
-public class MainActivity extends ReactActivity {
6
+public class MainActivity extends RctActivity {
11 7
 
12
-    /**
13
-     * Returns the name of the main component registered from JavaScript.
14
-     * This is used to schedule rendering of the component.
15
-     */
16 8
     @Override
17 9
     protected String getMainComponentName() {
18
-        return "example";
10
+        return "App";
19 11
     }
20 12
 
21
-    /**
22
-     * Returns whether dev mode should be enabled.
23
-     * This enables e.g. the dev menu.
24
-     */
25 13
     @Override
26
-    protected boolean getUseDeveloperSupport() {
27
-        return BuildConfig.DEBUG;
28
-    }
29
-
30
-    /**
31
-     * A list of packages used by the app. If the app uses additional views
32
-     * or modules besides the default ones, add more packages here.
33
-     */
34
-    @Override
35
-    protected List<ReactPackage> getPackages() {
36
-        return Arrays.<ReactPackage>asList(
37
-            new MainReactPackage()
38
-        );
14
+    protected void onPause() {
15
+        super.onPause();
16
+        finish();
39 17
     }
40 18
 }

+ 3
- 0
example/android/settings.gradle View File

@@ -1,3 +1,6 @@
1 1
 rootProject.name = 'example'
2 2
 
3 3
 include ':app'
4
+include ':react-native-navigation'
5
+project(':react-native-navigation').projectDir = new File(
6
+        rootProject.projectDir, '../node_modules/react-native-navigation/android/app/')

+ 19
- 0
example/src/app.js View File

@@ -1,9 +1,28 @@
1
+import React, {
2
+  AppRegistry,
3
+  Component,
4
+  View
5
+} from 'react-native';
1 6
 import { Navigation } from 'react-native-navigation';
2 7
 
3 8
 // screen related book keeping
4 9
 import { registerScreens } from './screens';
5 10
 registerScreens();
6 11
 
12
+AppRegistry.registerComponent('App', () => App);
13
+
14
+export default class App extends React.Component {
15
+  constructor(props) {
16
+    super(props);
17
+  }
18
+
19
+  render() {
20
+    return (
21
+      <View />
22
+    );
23
+  }
24
+}
25
+
7 26
 // this will start our app
8 27
 Navigation.startTabBasedApp({
9 28
   tabs: [

+ 111
- 0
example/src/screens/FirstTabScreen.android.js View File

@@ -0,0 +1,111 @@
1
+import React, {
2
+  Component,
3
+  Text,
4
+  View,
5
+  ScrollView,
6
+  TouchableOpacity,
7
+  StyleSheet
8
+} from 'react-native';
9
+
10
+export default class FirstTabScreen extends Component {
11
+  static navigatorButtons = {
12
+    leftButtons: [{
13
+      icon: require('../../img/navicon_menu.png'),
14
+      id: 'menu'
15
+    }],
16
+    rightButtons: [
17
+      {
18
+        title: 'Edit',
19
+        id: 'edit'
20
+      },
21
+      {
22
+        icon: require('../../img/navicon_add.png'),
23
+        id: 'add'
24
+      }
25
+    ]
26
+  };
27
+  static navigatorStyle = {
28
+    drawUnderTabBar: true
29
+  };
30
+  constructor(props) {
31
+    super(props);
32
+    // if you want to listen on navigator events, set this up
33
+    // this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
34
+  }
35
+  onNavigatorEvent(event) {
36
+    if (event.id == 'menu') {
37
+      this.props.navigator.toggleDrawer({
38
+        side: 'left',
39
+        animated: true
40
+      });
41
+    }
42
+    if (event.id == 'edit') {
43
+      // AlertIOS.alert('NavBar', 'Edit button pressed');
44
+    }
45
+    if (event.id == 'add') {
46
+      // AlertIOS.alert('NavBar', 'Add button pressed');
47
+    }
48
+  }
49
+  render() {
50
+    return (
51
+      <View style={{flex: 1, padding: 20}}>
52
+
53
+        <TouchableOpacity onPress={ this.onPushPress.bind(this) }>
54
+          <Text style={styles.button}>Push Plain Screen</Text>
55
+        </TouchableOpacity>
56
+
57
+        <TouchableOpacity onPress={ this.onPushStyledPress.bind(this) }>
58
+          <Text style={styles.button}>Push Styled Screen</Text>
59
+        </TouchableOpacity>
60
+
61
+        <TouchableOpacity onPress={ this.onModalPress.bind(this) }>
62
+          <Text style={styles.button}>Show Modal Screen</Text>
63
+        </TouchableOpacity>
64
+
65
+        <TouchableOpacity onPress={ this.onLightBoxPress.bind(this) }>
66
+          <Text style={styles.button}>Show LightBox</Text>
67
+        </TouchableOpacity>
68
+
69
+      </View>
70
+    );
71
+  }
72
+  onPushPress() {
73
+    this.props.navigator.push({
74
+      title: "More",
75
+      screen: "example.PushedScreen"
76
+    });
77
+  }
78
+  onPushStyledPress() {
79
+    console.warn('navigator.push not implemented yet');
80
+    // this.props.navigator.push({
81
+    //   title: "Styled",
82
+    //   screen: "example.StyledScreen"
83
+    // });
84
+  }
85
+  onModalPress() {
86
+    console.warn('navigator.showModal not implemented yet');
87
+    // this.props.navigator.showModal({
88
+    //   title: "Modal",
89
+    //   screen: "example.ModalScreen"
90
+    // });
91
+  }
92
+  onLightBoxPress() {
93
+    console.warn('navigator.showLightBox not implemented yet');
94
+    // this.props.navigator.showLightBox({
95
+    //   screen: "example.LightBoxScreen",
96
+    //   style: {
97
+    //     backgroundBlur: "dark"
98
+    //   }
99
+    // });
100
+  }
101
+}
102
+
103
+const styles = StyleSheet.create({
104
+  button: {
105
+    textAlign: 'center',
106
+    fontSize: 18,
107
+    marginBottom: 10,
108
+    marginTop:10,
109
+    color: 'blue'
110
+  }
111
+});

example/src/screens/FirstTabScreen.js → example/src/screens/FirstTabScreen.ios.js View File


+ 133
- 0
example/src/screens/SecondTabScreen.android.js View File

@@ -0,0 +1,133 @@
1
+import React, {
2
+  Component,
3
+  Text,
4
+  View,
5
+  ScrollView,
6
+  TouchableOpacity,
7
+  StyleSheet
8
+} from 'react-native';
9
+
10
+export default class SecondTabScreen extends Component {
11
+  static navigatorStyle = {
12
+    drawUnderTabBar: true
13
+  };
14
+  constructor(props) {
15
+    super(props);
16
+    this.buttonsCounter = 0;
17
+    // if you want to listen on navigator events, set this up
18
+    // this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
19
+  }
20
+  render() {
21
+    return (
22
+      <View style={{flex: 1, padding: 20}}>
23
+
24
+        <TouchableOpacity onPress={ this.onChangeButtonsPress.bind(this) }>
25
+          <Text style={styles.button}>Change Buttons</Text>
26
+        </TouchableOpacity>
27
+
28
+        <TouchableOpacity onPress={ this.onChangeTitlePress.bind(this) }>
29
+          <Text style={styles.button}>Change Title</Text>
30
+        </TouchableOpacity>
31
+
32
+        <TouchableOpacity onPress={ this.onSwitchTabPress.bind(this) }>
33
+          <Text style={styles.button}>Switch To Tab#1</Text>
34
+        </TouchableOpacity>
35
+
36
+        <TouchableOpacity onPress={ this.onSetTabBadgePress.bind(this) }>
37
+          <Text style={styles.button}>Set Tab Badge</Text>
38
+        </TouchableOpacity>
39
+
40
+        <TouchableOpacity onPress={ this.onToggleTabsPress.bind(this) }>
41
+          <Text style={styles.button}>Toggle Tabs</Text>
42
+        </TouchableOpacity>
43
+
44
+      </View>
45
+    );
46
+  }
47
+  onChangeTitlePress() {
48
+    this.props.navigator.setTitle({
49
+      title: Math.round(Math.random() * 100000).toString()
50
+    });
51
+  }
52
+  onChangeButtonsPress() {
53
+    let buttons;
54
+    if (this.buttonsCounter % 3 == 0) {
55
+      buttons = [
56
+        {
57
+          title: 'Edit',
58
+          id: 'edit',
59
+          disabled: true
60
+        },
61
+        {
62
+          icon: require('../../img/navicon_add.png'),
63
+          id: 'add'
64
+        }
65
+      ];
66
+    } else if (this.buttonsCounter % 3 == 1) {
67
+      buttons = [{
68
+        title: 'Save',
69
+        id: 'save'
70
+      }];
71
+    } else {
72
+      buttons = [];
73
+    }
74
+    this.buttonsCounter++;
75
+
76
+    this.props.navigator.setButtons({
77
+      rightButtons: buttons,
78
+      animated: true
79
+    });
80
+  }
81
+  onSwitchTabPress() {
82
+    this.props.navigator.switchToTab({
83
+      tabIndex: 0
84
+    });
85
+  }
86
+  onSetTabBadgePress() {
87
+    this.props.navigator.setTabBadge({
88
+      badge: 12
89
+    });
90
+  }
91
+  onToggleTabsPress() {
92
+    this.props.navigator.toggleTabs({
93
+      to: this.tabsHidden ? 'shown' : 'hidden'
94
+    });
95
+    this.tabsHidden = !this.tabsHidden;
96
+  }
97
+  onNavigatorEvent(event) {
98
+    // handle a deep link
99
+    if (event.type == 'DeepLink') {
100
+      const parts = event.link.split('/');
101
+      if (parts[0] == 'tab2') {
102
+        this.props.navigator.resetTo({
103
+          title: "Replaced Root",
104
+          screen: parts[1],
105
+          animated: true
106
+        });
107
+        this.props.navigator.switchToTab();
108
+      }
109
+    }
110
+    // handle a button press
111
+    // if (event.type == 'NavBarButtonPress') {
112
+    //   if (event.id == 'edit') {
113
+    //     AlertIOS.alert('NavBar', 'Dynamic Edit button pressed');
114
+    //   }
115
+    //   if (event.id == 'add') {
116
+    //     AlertIOS.alert('NavBar', 'Dynamic Add button pressed');
117
+    //   }
118
+    //   if (event.id == 'save') {
119
+    //     AlertIOS.alert('NavBar', 'Dynamic Save button pressed');
120
+    //   }
121
+    // }
122
+  }
123
+}
124
+
125
+const styles = StyleSheet.create({
126
+  button: {
127
+    textAlign: 'center',
128
+    fontSize: 18,
129
+    marginBottom: 10,
130
+    marginTop:10,
131
+    color: 'blue'
132
+  }
133
+});

example/src/screens/SecondTabScreen.js → example/src/screens/SecondTabScreen.ios.js View File


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

@@ -0,0 +1,20 @@
1
+import { Navigation } from 'react-native-navigation';
2
+
3
+import FirstTabScreen from './FirstTabScreen';
4
+import SecondTabScreen from './SecondTabScreen';
5
+import ThirdTabScreen from './ThirdTabScreen';
6
+import PushedScreen from './PushedScreen';
7
+import StyledScreen from './StyledScreen';
8
+import ModalScreen from './ModalScreen';
9
+import LightBoxScreen from './LightBoxScreen';
10
+import SideMenu from './SideMenu';
11
+
12
+// register all screens of the app (including internal ones)
13
+export function registerScreens() {
14
+  Navigation.registerComponent('example.FirstTabScreen', () => FirstTabScreen);
15
+  Navigation.registerComponent('example.SecondTabScreen', () => SecondTabScreen);
16
+  Navigation.registerComponent('example.ThirdTabScreen', () => ThirdTabScreen);
17
+  Navigation.registerComponent('example.PushedScreen', () => PushedScreen);
18
+  Navigation.registerComponent('example.StyledScreen', () => StyledScreen);
19
+  Navigation.registerComponent('example.SideMenu', () => SideMenu);
20
+}

example/src/screens/index.js → example/src/screens/index.ios.js View File


+ 19
- 1
src/platformSpecific.android.js View File

@@ -1,4 +1,5 @@
1 1
 import Navigation from './Navigation';
2
+import utils from './utils';
2 3
 
3 4
 import {
4 5
   RctActivity
@@ -12,6 +13,9 @@ function startSingleScreenApp(params) {
12 13
   }
13 14
 
14 15
   console.warn('startSingleScreenApp not implemented yet');
16
+  // RctActivity.startSingleScreenApp(params);
17
+  // add screenInstanceID using random
18
+
15 19
 }
16 20
 
17 21
 function startTabBasedApp(params) {
@@ -20,10 +24,24 @@ function startTabBasedApp(params) {
20 24
     return;
21 25
   }
22 26
 
27
+  // Add stackID for each tab
28
+  // TODO: Add propper documentation + switch to UUID? -guy
29
+  params.tabs.forEach(function (tab, idx) {
30
+    tab.stackID = utils.getRandomId();
31
+    tab.navigatorID = utils.getRandomId() + '_nav' + idx;
32
+    tab.screenInstanceID = utils.getRandomId();
33
+    tab.navigatorEventID = tab.screenInstanceID + '_events';
34
+  });
35
+
23 36
   RctActivity.startTabBasedApp(params.tabs);
24 37
 }
25 38
 
39
+function navigatorPush(navigator, params) {
40
+  RctActivity.navigatorPush(params);
41
+}
42
+
26 43
 export default {
27 44
   startSingleScreenApp,
28
-  startTabBasedApp
45
+  startTabBasedApp,
46
+  navigatorPush
29 47
 }