Selaa lähdekoodia

Initial commit for Android implementation

The approach we took is fairly simple. Navigation is created natively in corresponding activity,
currently only TabActivity is supported, and we pass the styling parameters and screenId to it.
Each screen is rendered in its own ReactRootView and is wired to the same ReactInstanceManager,
so all screens share the same java script context.
Guy Carmeli 8 vuotta sitten
vanhempi
commit
af2ea9207e
30 muutettua tiedostoa jossa 1950 lisäystä ja 0 poistoa
  1. 36
    0
      android/app/build.gradle
  2. 126
    0
      android/app/react-native-navigation.iml
  3. 97
    0
      android/app/react.gradle
  4. 9
    0
      android/app/src/main/AndroidManifest.xml
  5. 244
    0
      android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java
  6. 21
    0
      android/app/src/main/java/com/reactnativenavigation/activities/CompoundReactActivity.java
  7. 84
    0
      android/app/src/main/java/com/reactnativenavigation/activities/RctActivity.java
  8. 84
    0
      android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java
  9. 24
    0
      android/app/src/main/java/com/reactnativenavigation/adapters/Page.java
  10. 70
    0
      android/app/src/main/java/com/reactnativenavigation/adapters/ViewPagerAdapter.java
  11. 85
    0
      android/app/src/main/java/com/reactnativenavigation/core/RctManager.java
  12. 42
    0
      android/app/src/main/java/com/reactnativenavigation/events/TabSelectedEvent.java
  13. 70
    0
      android/app/src/main/java/com/reactnativenavigation/layouts/ReactTabLayout.java
  14. 109
    0
      android/app/src/main/java/com/reactnativenavigation/managers/AppBarLayoutManager.java
  15. 48
    0
      android/app/src/main/java/com/reactnativenavigation/managers/CoordinatorLayoutManager.java
  16. 293
    0
      android/app/src/main/java/com/reactnativenavigation/managers/TabLayoutManager.java
  17. 40
    0
      android/app/src/main/java/com/reactnativenavigation/managers/ToolbarManager.java
  18. 62
    0
      android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java
  19. 36
    0
      android/app/src/main/java/com/reactnativenavigation/modules/RctLayoutManager.java
  20. 45
    0
      android/app/src/main/java/com/reactnativenavigation/packages/RCCPackage.java
  21. 30
    0
      android/app/src/main/java/com/reactnativenavigation/utils/ContextProvider.java
  22. 21
    0
      android/app/src/main/java/com/reactnativenavigation/utils/ResourceUtils.java
  23. 28
    0
      android/app/src/main/java/com/reactnativenavigation/views/RctView.java
  24. 37
    0
      android/app/src/main/res/layout/tab_activity.xml
  25. 8
    0
      android/app/src/main/res/layout/toolbar.xml
  26. 4
    0
      android/app/src/main/res/values/ids.xml
  27. 24
    0
      android/build.gradle
  28. 20
    0
      android/gradle.properties
  29. 134
    0
      android/react-native-navigation.iml
  30. 19
    0
      android/react-navtive-navigation.iml

+ 36
- 0
android/app/build.gradle Näytä tiedosto

@@ -0,0 +1,36 @@
1
+apply plugin: 'com.android.library'
2
+
3
+apply from: "react.gradle"
4
+
5
+android {
6
+    compileSdkVersion 23
7
+    buildToolsVersion "23.0.1"
8
+
9
+    defaultConfig {
10
+        minSdkVersion 16
11
+        targetSdkVersion 22
12
+        versionCode 1
13
+        versionName "1.0"
14
+    }
15
+    defaultPublishConfig 'release'
16
+    publishNonDefault true
17
+    productFlavors {
18
+        library {
19
+        }
20
+    }
21
+    buildTypes {
22
+        release {
23
+            minifyEnabled false
24
+        }
25
+        debug {
26
+            minifyEnabled false
27
+        }
28
+    }
29
+}
30
+
31
+dependencies {
32
+    compile fileTree(dir: "libs", include: ["*.jar"])
33
+    compile "com.android.support:appcompat-v7:23.0.1"
34
+    compile 'com.android.support:design:23.1.1'
35
+    compile "com.facebook.react:react-native:+"  // From node_modules
36
+}

+ 126
- 0
android/app/react-native-navigation.iml Näytä tiedosto

@@ -0,0 +1,126 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<module external.linked.project.id=":react-native-navigation" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../../../../android" external.system.id="GRADLE" external.system.module.group="example" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
3
+  <component name="FacetManager">
4
+    <facet type="android-gradle" name="Android-Gradle">
5
+      <configuration>
6
+        <option name="GRADLE_PROJECT_PATH" value=":react-native-navigation" />
7
+      </configuration>
8
+    </facet>
9
+    <facet type="android" name="Android">
10
+      <configuration>
11
+        <option name="SELECTED_BUILD_VARIANT" value="libraryDebug" />
12
+        <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
13
+        <option name="ASSEMBLE_TASK_NAME" value="assembleLibraryDebug" />
14
+        <option name="COMPILE_JAVA_TASK_NAME" value="compileLibraryDebugSources" />
15
+        <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleLibraryDebugAndroidTest" />
16
+        <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileLibraryDebugAndroidTestSources" />
17
+        <afterSyncTasks>
18
+          <task>generateLibraryDebugAndroidTestSources</task>
19
+          <task>generateLibraryDebugSources</task>
20
+        </afterSyncTasks>
21
+        <option name="ALLOW_USER_CONFIGURATION" value="false" />
22
+        <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
23
+        <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
24
+        <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
25
+        <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
26
+        <option name="LIBRARY_PROJECT" value="true" />
27
+      </configuration>
28
+    </facet>
29
+  </component>
30
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
31
+    <output url="file://$MODULE_DIR$/build/intermediates/classes/library/debug" />
32
+    <output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/library/debug" />
33
+    <exclude-output />
34
+    <content url="file://$MODULE_DIR$">
35
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/library/debug" isTestSource="false" generated="true" />
36
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/library/debug" isTestSource="false" generated="true" />
37
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/library/debug" isTestSource="false" generated="true" />
38
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/library/debug" isTestSource="false" generated="true" />
39
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/library/debug" type="java-resource" />
40
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/library/debug" type="java-resource" />
41
+      <sourceFolder url="file://$MODULE_DIR$/src/libraryDebug/res" type="java-resource" />
42
+      <sourceFolder url="file://$MODULE_DIR$/src/libraryDebug/resources" type="java-resource" />
43
+      <sourceFolder url="file://$MODULE_DIR$/src/libraryDebug/assets" type="java-resource" />
44
+      <sourceFolder url="file://$MODULE_DIR$/src/libraryDebug/aidl" isTestSource="false" />
45
+      <sourceFolder url="file://$MODULE_DIR$/src/libraryDebug/java" isTestSource="false" />
46
+      <sourceFolder url="file://$MODULE_DIR$/src/libraryDebug/jni" isTestSource="false" />
47
+      <sourceFolder url="file://$MODULE_DIR$/src/libraryDebug/rs" isTestSource="false" />
48
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/library/debug" isTestSource="true" generated="true" />
49
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/library/debug" isTestSource="true" generated="true" />
50
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/library/debug" isTestSource="true" generated="true" />
51
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/library/debug" isTestSource="true" generated="true" />
52
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/library/debug" type="java-test-resource" />
53
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/library/debug" type="java-test-resource" />
54
+      <sourceFolder url="file://$MODULE_DIR$/src/library/res" type="java-resource" />
55
+      <sourceFolder url="file://$MODULE_DIR$/src/library/resources" type="java-resource" />
56
+      <sourceFolder url="file://$MODULE_DIR$/src/library/assets" type="java-resource" />
57
+      <sourceFolder url="file://$MODULE_DIR$/src/library/aidl" isTestSource="false" />
58
+      <sourceFolder url="file://$MODULE_DIR$/src/library/java" isTestSource="false" />
59
+      <sourceFolder url="file://$MODULE_DIR$/src/library/jni" isTestSource="false" />
60
+      <sourceFolder url="file://$MODULE_DIR$/src/library/rs" isTestSource="false" />
61
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestLibrary/res" type="java-test-resource" />
62
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestLibrary/resources" type="java-test-resource" />
63
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestLibrary/assets" type="java-test-resource" />
64
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestLibrary/aidl" isTestSource="true" />
65
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestLibrary/java" isTestSource="true" />
66
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestLibrary/jni" isTestSource="true" />
67
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestLibrary/rs" isTestSource="true" />
68
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
69
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
70
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
71
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
72
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
73
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
74
+      <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
75
+      <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
76
+      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
77
+      <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
78
+      <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
79
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
80
+      <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
81
+      <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
82
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
83
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
84
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
85
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
86
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
87
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
88
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
89
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotations" />
90
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
91
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
92
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
93
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.20.1/jars" />
94
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
95
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
96
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
97
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
98
+      <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
99
+      <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
100
+    </content>
101
+    <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
102
+    <orderEntry type="sourceFolder" forTests="false" />
103
+    <orderEntry type="library" exported="" name="support-annotations-23.1.1" level="project" />
104
+    <orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
105
+    <orderEntry type="library" exported="" name="design-23.1.1" level="project" />
106
+    <orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
107
+    <orderEntry type="library" exported="" name="imagepipeline-0.8.1" level="project" />
108
+    <orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
109
+    <orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
110
+    <orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
111
+    <orderEntry type="library" exported="" name="recyclerview-v7-23.1.1" level="project" />
112
+    <orderEntry type="library" exported="" name="react-native-0.20.1" level="project" />
113
+    <orderEntry type="library" exported="" name="support-v4-23.1.1" level="project" />
114
+    <orderEntry type="library" exported="" name="appcompat-v7-23.1.1" level="project" />
115
+    <orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
116
+    <orderEntry type="library" exported="" name="okhttp-ws-2.5.0" level="project" />
117
+    <orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
118
+    <orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
119
+    <orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
120
+    <orderEntry type="library" exported="" name="drawee-0.8.1" level="project" />
121
+    <orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
122
+    <orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
123
+    <orderEntry type="library" exported="" name="library-2.4.0" level="project" />
124
+    <orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
125
+  </component>
126
+</module>

+ 97
- 0
android/app/react.gradle Näytä tiedosto

@@ -0,0 +1,97 @@
1
+import org.apache.tools.ant.taskdefs.condition.Os
2
+
3
+def config = project.hasProperty("react") ? project.react : [];
4
+
5
+def bundleAssetName = config.bundleAssetName ?: "index.android.bundle"
6
+def entryFile = config.entryFile ?: "index.android.js"
7
+
8
+// because elvis operator
9
+def elvisFile(thing) {
10
+    return thing ? file(thing) : null;
11
+}
12
+
13
+def reactRoot = elvisFile(config.root) ?: file("../../")
14
+def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"]
15
+
16
+void runBefore(String dependentTaskName, Task task) {
17
+    Task dependentTask = tasks.findByPath(dependentTaskName);
18
+    if (dependentTask != null) {
19
+        dependentTask.dependsOn task
20
+    }
21
+}
22
+
23
+gradle.projectsEvaluated {
24
+    // Grab all build types and product flavors
25
+    def buildTypes = android.buildTypes.collect { type -> type.name }
26
+    def productFlavors = android.productFlavors.collect { flavor -> flavor.name }
27
+
28
+    // When no product flavors defined, use empty
29
+    if (!productFlavors) productFlavors.add('')
30
+
31
+    productFlavors.each { productFlavorName ->
32
+        buildTypes.each { buildTypeName ->
33
+            // Create variant and target names
34
+            def targetName = "${productFlavorName.capitalize()}${buildTypeName.capitalize()}"
35
+            def targetPath = productFlavorName ?
36
+                    "${productFlavorName}/${buildTypeName}" :
37
+                    "${buildTypeName}"
38
+
39
+            // React js bundle directories
40
+            def jsBundleDirConfigName = "jsBundleDir${targetName}"
41
+            def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?:
42
+                    file("$buildDir/intermediates/assets/${targetPath}")
43
+
44
+            def resourcesDirConfigName = "resourcesDir${targetName}"
45
+            def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?:
46
+                    file("$buildDir/intermediates/res/merged/${targetPath}")
47
+            def jsBundleFile = file("$jsBundleDir/$bundleAssetName")
48
+
49
+            // Bundle task name for variant
50
+            def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets"
51
+
52
+            def currentBundleTask = tasks.create(
53
+                    name: bundleJsAndAssetsTaskName,
54
+                    type: Exec) {
55
+                group = "react"
56
+                description = "bundle JS and assets for ${targetName}."
57
+
58
+                // Create dirs if they are not there (e.g. the "clean" task just ran)
59
+                doFirst {
60
+                    jsBundleDir.mkdirs()
61
+                    resourcesDir.mkdirs()
62
+                }
63
+
64
+                // Set up inputs and outputs so gradle can cache the result
65
+                inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
66
+                outputs.dir jsBundleDir
67
+                outputs.dir resourcesDir
68
+
69
+                // Set up the call to the react-native cli
70
+                workingDir reactRoot
71
+
72
+                // Set up dev mode
73
+                def devEnabled = !targetName.toLowerCase().contains("release")
74
+                if (Os.isFamily(Os.FAMILY_WINDOWS)) {
75
+                    commandLine "cmd", "/c", "react-native", "bundle", "--platform", "android", "--dev", "${devEnabled}",
76
+                            "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir
77
+                } else {
78
+                    commandLine "react-native", "bundle", "--platform", "android", "--dev", "${devEnabled}",
79
+                            "--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir
80
+                }
81
+
82
+                enabled config."bundleIn${targetName}" ||
83
+                    config."bundleIn${buildTypeName.capitalize()}" ?:
84
+                            targetName.toLowerCase().contains("release")
85
+            }
86
+
87
+            // Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process
88
+            currentBundleTask.dependsOn("merge${targetName}Resources")
89
+            currentBundleTask.dependsOn("merge${targetName}Assets")
90
+
91
+            runBefore("processArmeabi-v7a${targetName}Resources", currentBundleTask)
92
+            runBefore("processX86${targetName}Resources", currentBundleTask)
93
+            runBefore("processUniversal${targetName}Resources", currentBundleTask)
94
+            runBefore("process${targetName}Resources", currentBundleTask)
95
+        }
96
+    }
97
+}

+ 9
- 0
android/app/src/main/AndroidManifest.xml Näytä tiedosto

@@ -0,0 +1,9 @@
1
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+    package="com.reactnativenavigation">
3
+
4
+    <application>
5
+      <activity android:name="com.reactnativenavigation.activities.RctActivity" />
6
+        <activity android:name="com.reactnativenavigation.activities.TabActivity" />
7
+    </application>
8
+
9
+</manifest>

+ 244
- 0
android/app/src/main/java/com/reactnativenavigation/activities/BaseReactActivity.java Näytä tiedosto

@@ -0,0 +1,244 @@
1
+package com.reactnativenavigation.activities;
2
+
3
+import android.app.Activity;
4
+import android.content.Intent;
5
+import android.os.Build;
6
+import android.os.Bundle;
7
+import android.os.Handler;
8
+import android.provider.Settings;
9
+import android.support.v7.app.AppCompatActivity;
10
+import android.util.Log;
11
+import android.view.KeyEvent;
12
+import android.widget.EditText;
13
+import android.widget.Toast;
14
+
15
+import com.facebook.common.logging.FLog;
16
+import com.facebook.react.LifecycleState;
17
+import com.facebook.react.ReactInstanceManager;
18
+import com.facebook.react.ReactPackage;
19
+import com.facebook.react.ReactRootView;
20
+import com.facebook.react.common.ReactConstants;
21
+import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
22
+import com.facebook.react.shell.MainReactPackage;
23
+import com.reactnativenavigation.core.RctManager;
24
+import com.reactnativenavigation.packages.RCCPackage;
25
+import com.reactnativenavigation.utils.ContextProvider;
26
+
27
+import java.util.Arrays;
28
+import java.util.List;
29
+
30
+import javax.annotation.Nullable;
31
+
32
+/**
33
+ * Base Activity for React Native applications.
34
+ */
35
+public abstract class BaseReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
36
+
37
+    private static final String REDBOX_PERMISSION_MESSAGE =
38
+            "Overlay permissions needs to be granted in order for react native apps to run in dev mode";
39
+    private static final String TAG = "ReactActivity";
40
+
41
+    protected  @Nullable ReactInstanceManager mReactInstanceManager;
42
+    private LifecycleState mLifecycleState = LifecycleState.BEFORE_RESUME;
43
+    private boolean mDoRefresh = false;
44
+
45
+    /**
46
+     * Returns the name of the bundle in assets. If this is null, and no file path is specified for
47
+     * the bundle, the app will only work with {@code getUseDeveloperSupport} enabled and will
48
+     * always try to load the JS bundle from the packager server.
49
+     * e.g. "index.android.bundle"
50
+     */
51
+    protected @Nullable String getBundleAssetName() {
52
+        return "index.android.bundle";
53
+    };
54
+
55
+    /**
56
+     * Returns a custom path of the bundle file. This is used in cases the bundle should be loaded
57
+     * from a custom path. By default it is loaded from Android assets, from a path specified
58
+     * by {getBundleAssetName}.
59
+     * e.g. "file://sdcard/myapp_cache/index.android.bundle"
60
+     */
61
+    protected @Nullable String getJSBundleFile() {
62
+        return null;
63
+    }
64
+
65
+    /**
66
+     * Returns the name of the main module. Determines the URL used to fetch the JS bundle
67
+     * from the packager server. It is only used when dev support is enabled.
68
+     * This is the first file to be executed once the {@link ReactInstanceManager} is created.
69
+     * e.g. "index.android"
70
+     */
71
+    protected String getJSMainModuleName() {
72
+        return "index.android";
73
+    }
74
+
75
+    /**
76
+     * Returns the launchOptions which will be passed to the {@link ReactInstanceManager}
77
+     * when the application is started. By default, this will return null and an empty
78
+     * object will be passed to your top level component as its initial props.
79
+     * If your React Native application requires props set outside of JS, override
80
+     * this method to return the Android.os.Bundle of your desired initial props.
81
+     */
82
+    protected @Nullable Bundle getLaunchOptions() {
83
+        return null;
84
+    }
85
+
86
+    /**
87
+     * Returns the name of the main component registered from JavaScript.
88
+     * This is used to schedule rendering of the component.
89
+     * e.g. "MoviesApp"
90
+     */
91
+    protected abstract String getMainComponentName();
92
+
93
+    /**
94
+     * Returns whether dev mode should be enabled. This enables e.g. the dev menu.
95
+     */
96
+    protected abstract boolean getUseDeveloperSupport();
97
+
98
+    /**
99
+     * Returns a list of {@link ReactPackage} used by the app.
100
+     * You'll most likely want to return at least the {@code MainReactPackage}.
101
+     * If your app uses additional views or modules besides the default ones,
102
+     * you'll want to include more packages here.
103
+     */
104
+    protected List<ReactPackage> getPackages() {
105
+        return Arrays.asList(
106
+                new MainReactPackage(),
107
+                new RCCPackage()
108
+        );
109
+    }
110
+
111
+    /**
112
+     * A subclass may override this method if it needs to use a custom {@link ReactRootView}.
113
+     */
114
+    protected ReactRootView createRootView() {
115
+        return new ReactRootView(this);
116
+    }
117
+
118
+    @Override
119
+    protected void onCreate(Bundle savedInstanceState) {
120
+        super.onCreate(savedInstanceState);
121
+        mReactInstanceManager = createReactInstanceManager();
122
+        handleOnCreate();
123
+    }
124
+
125
+    /**
126
+     * A subclass may override this method if it needs to use a custom instance.
127
+     */
128
+    protected ReactInstanceManager createReactInstanceManager() {
129
+        return getReactInstanceManager();
130
+    }
131
+
132
+    protected ReactInstanceManager getReactInstanceManager() {
133
+        RctManager rctManager = RctManager.getInstance();
134
+        if (!rctManager.isInitialized()) {
135
+            rctManager.init(this, getMainComponentName(), getPackages());
136
+        }
137
+        return rctManager.getReactInstanceManager();
138
+    }
139
+
140
+    protected void handleOnCreate() {
141
+        if (getUseDeveloperSupport() && Build.VERSION.SDK_INT >= 23) {
142
+            // Get permission to show redbox in dev builds.
143
+            if (!Settings.canDrawOverlays(this)) {
144
+                Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
145
+                startActivity(serviceIntent);
146
+                FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);
147
+                Toast.makeText(this, REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show();
148
+            }
149
+        }
150
+
151
+        ReactRootView mReactRootView = createRootView();
152
+        mReactRootView.startReactApplication(mReactInstanceManager, getMainComponentName(), getLaunchOptions());
153
+        setContentView(mReactRootView);
154
+    }
155
+
156
+    @Override
157
+    protected void onResume() {
158
+        super.onResume();
159
+        ContextProvider.setActivityContext(this);
160
+
161
+        mLifecycleState = LifecycleState.RESUMED;
162
+
163
+        if (mReactInstanceManager != null) {
164
+            mReactInstanceManager.onResume(this, this);
165
+        }
166
+    }
167
+
168
+    @Override
169
+    protected void onPause() {
170
+        super.onPause();
171
+
172
+        mLifecycleState = LifecycleState.BEFORE_RESUME;
173
+
174
+        if (mReactInstanceManager != null) {
175
+            mReactInstanceManager.onPause();
176
+        }
177
+
178
+        ContextProvider.clearActivityContext();
179
+    }
180
+
181
+    @Override
182
+    protected void onDestroy() {
183
+        super.onDestroy();
184
+
185
+        // Destroy react instance manager only if there are no resumed react activities
186
+        Activity activity = ContextProvider.getActivityContext();
187
+        if (mReactInstanceManager != null && !(activity instanceof BaseReactActivity)) {
188
+            Log.i(TAG, "Destroying ReactInstanceManager");
189
+            mReactInstanceManager.onDestroy();
190
+        } else {
191
+            Log.d(TAG, "Not destroying ReactInstanceManager");
192
+        }
193
+    }
194
+
195
+    @Override
196
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
197
+        if (mReactInstanceManager != null) {
198
+            mReactInstanceManager.onActivityResult(requestCode, resultCode, data);
199
+        }
200
+    }
201
+
202
+    @Override
203
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
204
+        if (mReactInstanceManager != null &&
205
+            mReactInstanceManager.getDevSupportManager().getDevSupportEnabled()) {
206
+            if (keyCode == KeyEvent.KEYCODE_MENU) {
207
+                mReactInstanceManager.showDevOptionsDialog();
208
+                return true;
209
+            }
210
+            if (keyCode == KeyEvent.KEYCODE_R && !(getCurrentFocus() instanceof EditText)) {
211
+                // Enable double-tap-R-to-reload
212
+                if (mDoRefresh) {
213
+                    mReactInstanceManager.getDevSupportManager().handleReloadJS();
214
+                    mDoRefresh = false;
215
+                } else {
216
+                    mDoRefresh = true;
217
+                    new Handler().postDelayed(
218
+                            new Runnable() {
219
+                                @Override
220
+                                public void run() {
221
+                                    mDoRefresh = false;
222
+                                }
223
+                            },
224
+                            200);
225
+                }
226
+            }
227
+        }
228
+        return super.onKeyUp(keyCode, event);
229
+    }
230
+
231
+    @Override
232
+    public void onBackPressed() {
233
+        if (mReactInstanceManager != null) {
234
+            mReactInstanceManager.onBackPressed();
235
+        } else {
236
+            super.onBackPressed();
237
+        }
238
+    }
239
+
240
+    @Override
241
+    public void invokeDefaultOnBackPressed() {
242
+        super.onBackPressed();
243
+    }
244
+}

+ 21
- 0
android/app/src/main/java/com/reactnativenavigation/activities/CompoundReactActivity.java Näytä tiedosto

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

+ 84
- 0
android/app/src/main/java/com/reactnativenavigation/activities/RctActivity.java Näytä tiedosto

@@ -0,0 +1,84 @@
1
+package com.reactnativenavigation.activities;
2
+
3
+import android.content.Intent;
4
+import android.os.Bundle;
5
+import android.util.Log;
6
+
7
+import com.facebook.react.ReactInstanceManager;
8
+import com.facebook.react.ReactRootView;
9
+import com.reactnativenavigation.R;
10
+import com.reactnativenavigation.core.RctManager;
11
+
12
+/**
13
+ *
14
+ * Created by guyc on 10/03/16.
15
+ */
16
+public class RctActivity extends BaseReactActivity {
17
+    public static final String EXTRA_COMPONENT_NAME = "componentName";
18
+    private static final String TAG = "RctActivity";
19
+
20
+    private String mComponentName = "";
21
+
22
+    public void setComponentName(String componentName) {
23
+        mComponentName = componentName;
24
+    }
25
+
26
+    @Override
27
+    public void onCreate(Bundle savedInstanceState) {
28
+        Log.v(TAG, "onCreate");
29
+        if (mComponentName == null) {
30
+            Intent intent = getIntent();
31
+            assert intent != null;
32
+            mComponentName = intent.getStringExtra(EXTRA_COMPONENT_NAME);
33
+            assert mComponentName != null;
34
+        }
35
+        Log.v(TAG, "mComponentName: " + mComponentName);
36
+
37
+        super.onCreate(savedInstanceState);
38
+    }
39
+
40
+    @Override
41
+    protected String getMainComponentName() {
42
+        return mComponentName;
43
+    }
44
+
45
+    @Override
46
+    protected ReactRootView createRootView() {
47
+        ReactRootView rootView = super.createRootView();
48
+        rootView.setId(R.id.react_root_view);
49
+        return rootView;
50
+    }
51
+
52
+    /**
53
+     * Returns whether dev mode should be enabled.
54
+     * This enables e.g. the dev menu.
55
+     */
56
+    @Override
57
+    protected boolean getUseDeveloperSupport() {
58
+        return false;
59
+    }
60
+
61
+    @Override
62
+    protected ReactInstanceManager createReactInstanceManager() {
63
+        return getReactInstanceManager();
64
+    }
65
+
66
+    protected ReactInstanceManager getReactInstanceManager() {
67
+        RctManager rctManager = RctManager.getInstance();
68
+        if (!rctManager.isInitialized()) {
69
+            rctManager.init(this, mComponentName, getPackages());
70
+        }
71
+        return rctManager.getReactInstanceManager();
72
+    }
73
+
74
+    @Override
75
+    protected void onResume() {
76
+        Log.v(TAG, "onResume component: " + mComponentName);
77
+        super.onResume();
78
+    }
79
+
80
+    @Override
81
+    protected void onPause() {
82
+        super.onPause();
83
+    }
84
+}

+ 84
- 0
android/app/src/main/java/com/reactnativenavigation/activities/TabActivity.java Näytä tiedosto

@@ -0,0 +1,84 @@
1
+package com.reactnativenavigation.activities;
2
+
3
+import android.os.Bundle;
4
+import android.support.design.widget.TabLayout;
5
+import android.support.v4.view.ViewPager;
6
+import android.support.v7.widget.Toolbar;
7
+import android.util.Log;
8
+
9
+import com.reactnativenavigation.R;
10
+import com.reactnativenavigation.adapters.Page;
11
+import com.reactnativenavigation.adapters.ViewPagerAdapter;
12
+import com.reactnativenavigation.core.RctManager;
13
+
14
+import java.util.ArrayList;
15
+
16
+/**
17
+ * Created by guyc on 02/04/16.
18
+ */
19
+public class TabActivity extends CompoundReactActivity {
20
+    private static final String TAG = "TabActivity";
21
+    public static final String EXTRA_TABS = "extraTabs";
22
+
23
+    private Toolbar mToolbar;
24
+    private TabLayout mTabLayout;
25
+    private ViewPager mViewPager;
26
+
27
+    @Override
28
+    public void onCreate(Bundle savedInstanceState) {
29
+        Log.v(TAG, "onCreate");
30
+        super.onCreate(savedInstanceState);
31
+    }
32
+
33
+    @Override
34
+    protected void handleOnCreate() {
35
+        mReactInstanceManager = RctManager.getInstance().getReactInstanceManager();
36
+
37
+        setContentView(R.layout.tab_activity);
38
+        mToolbar = (Toolbar) findViewById(R.id.toolbar);
39
+        mTabLayout = (TabLayout) findViewById(R.id.tabLayout);
40
+        mViewPager = (ViewPager) findViewById(R.id.viewPager);
41
+
42
+        setupToolbar();
43
+        setupViews();
44
+    }
45
+
46
+
47
+    private void setupToolbar() {
48
+        setSupportActionBar(mToolbar);
49
+    }
50
+    private void setupViews() {
51
+        ArrayList<Page> pages = (ArrayList<Page>) getIntent().getSerializableExtra(EXTRA_TABS);
52
+        ViewPagerAdapter adapter = new ViewPagerAdapter(this, pages);
53
+        mViewPager.setAdapter(adapter);
54
+        mTabLayout.setupWithViewPager(mViewPager);
55
+        adapter.notifyDataSetChanged();
56
+    }
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
+}

+ 24
- 0
android/app/src/main/java/com/reactnativenavigation/adapters/Page.java Näytä tiedosto

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

+ 70
- 0
android/app/src/main/java/com/reactnativenavigation/adapters/ViewPagerAdapter.java Näytä tiedosto

@@ -0,0 +1,70 @@
1
+package com.reactnativenavigation.adapters;
2
+
3
+import android.support.v4.view.PagerAdapter;
4
+import android.util.Log;
5
+import android.view.View;
6
+import android.view.ViewGroup;
7
+
8
+import com.facebook.react.ReactInstanceManager;
9
+import com.facebook.react.bridge.ReadableArray;
10
+import com.reactnativenavigation.activities.BaseReactActivity;
11
+import com.reactnativenavigation.core.RctManager;
12
+import com.reactnativenavigation.views.RctView;
13
+
14
+import java.util.ArrayList;
15
+
16
+/**
17
+ *
18
+ * Created by guyc on 02/04/16.
19
+ */
20
+public class ViewPagerAdapter extends PagerAdapter {
21
+
22
+    private static final String TAG = "ViewPagerAdapter";
23
+    private BaseReactActivity mContext;
24
+    private final ArrayList<Page> mPages;
25
+    private final ReactInstanceManager mReactInstanceManager;
26
+
27
+    public ViewPagerAdapter(BaseReactActivity context, ArrayList<Page> pages) {
28
+        mContext = context;
29
+        mPages = pages;
30
+        mReactInstanceManager = RctManager.getInstance().getReactInstanceManager();
31
+    }
32
+
33
+    @Override
34
+    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);
38
+        container.addView(view);
39
+        return view;
40
+
41
+    }
42
+
43
+    @Override
44
+    public void destroyItem(ViewGroup container, int position, Object view) {
45
+        container.removeView((View) view);
46
+    }
47
+
48
+    @Override
49
+    public int getCount() {
50
+        return mPages.size();
51
+    }
52
+
53
+    @Override
54
+    public boolean isViewFromObject(View view, Object object) {
55
+        return view == object;
56
+    }
57
+
58
+    @Override
59
+    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;
69
+    }
70
+}

+ 85
- 0
android/app/src/main/java/com/reactnativenavigation/core/RctManager.java Näytä tiedosto

@@ -0,0 +1,85 @@
1
+package com.reactnativenavigation.core;
2
+
3
+import android.app.Application;
4
+import android.content.Context;
5
+import android.util.Log;
6
+
7
+import com.facebook.react.LifecycleState;
8
+import com.facebook.react.ReactInstanceManager;
9
+import com.facebook.react.ReactPackage;
10
+
11
+import java.util.List;
12
+
13
+/**
14
+ * Created by guyc on 22/02/16.
15
+ */
16
+public class RctManager {
17
+    private static final String TAG = "RctManager";
18
+    private static RctManager sInstance;
19
+
20
+    private ReactInstanceManager mReactManager;
21
+    private boolean mUseLocalDevServer = true;
22
+
23
+    private RctManager() {
24
+        // Singleton
25
+    }
26
+
27
+    public static synchronized RctManager getInstance() {
28
+        if (sInstance == null) {
29
+            sInstance = new RctManager();
30
+        }
31
+        return sInstance;
32
+    }
33
+
34
+    public ReactInstanceManager getReactInstanceManager() {
35
+        return mReactManager;
36
+    }
37
+
38
+    public void useLocalDevServer(boolean useLocalDevServer) {
39
+        mUseLocalDevServer = useLocalDevServer;
40
+    }
41
+
42
+    public boolean isInitialized() {
43
+        return mReactManager != null;
44
+    }
45
+
46
+    public void init(Context context, String componentName, List<ReactPackage> packages) {
47
+        Log.i(TAG, "Initializing RctManager");
48
+        createReactInstanceManager(context, componentName, packages);
49
+    }
50
+
51
+    /**
52
+     * Creates a React Instance Manager associated with this component name
53
+     * @param context
54
+     * @param jsBundleName
55
+     * @param packages
56
+     */
57
+    public ReactInstanceManager createReactInstanceManager(Context context, String jsBundleName, List<ReactPackage> packages) {
58
+        // Get component name
59
+        ReactInstanceManager.Builder builder = ReactInstanceManager.builder()
60
+                .setApplication((Application) context.getApplicationContext())
61
+                .setUseDeveloperSupport(true)
62
+                .setInitialLifecycleState(LifecycleState.BEFORE_RESUME);
63
+        for (ReactPackage reactPackage : packages) {
64
+            builder.addPackage(reactPackage);
65
+        }
66
+        if (mUseLocalDevServer) {
67
+            // Set module name to be loaded from local node server
68
+            builder.setJSMainModuleName("index.android");
69
+            builder.setBundleAssetName("index.android.bundle");
70
+        } else {
71
+            throw new RuntimeException("Implement me!");
72
+            //            // Get the bundle uri
73
+            //            String confResourceName = AssetManager.getConfUrlResourceName(jsBundleName);
74
+            //            Context context = AppDelegate.sharedApplication().getApplicationContext();
75
+            //            Uri uri =
76
+            //                    AssetManager.sharedAssetManager().getConfResourceUrl(confResourceName, context);
77
+            //            // Load bundled jsBundle
78
+            //            builder.setJSBundleFile(uri.getPath());
79
+        }
80
+
81
+        mReactManager = builder.build();
82
+        return mReactManager;
83
+    }
84
+}
85
+

+ 42
- 0
android/app/src/main/java/com/reactnativenavigation/events/TabSelectedEvent.java Näytä tiedosto

@@ -0,0 +1,42 @@
1
+package com.reactnativenavigation.events;
2
+
3
+import android.os.SystemClock;
4
+import android.util.Log;
5
+
6
+import com.facebook.react.bridge.Arguments;
7
+import com.facebook.react.bridge.WritableMap;
8
+import com.facebook.react.uimanager.events.Event;
9
+import com.facebook.react.uimanager.events.RCTEventEmitter;
10
+
11
+/**
12
+ *
13
+ * Created by guyc on 07/03/16.
14
+ */
15
+public class TabSelectedEvent extends Event<TabSelectedEvent> {
16
+    public static final String EVENT_NAME = "tabSelected";
17
+    private static final String KEY_POSITION = "position";
18
+
19
+    private int mPosition;
20
+
21
+    public TabSelectedEvent(int viewTag, int position) {
22
+        super(viewTag, SystemClock.uptimeMillis());
23
+        mPosition = position;
24
+    }
25
+
26
+    @Override
27
+    public String getEventName() {
28
+        return EVENT_NAME;
29
+    }
30
+
31
+    @Override
32
+    public void dispatch(RCTEventEmitter rctEventEmitter) {
33
+        Log.d("GUY", "DIspatching event: " + getViewTag());
34
+        rctEventEmitter.receiveEvent(getViewTag(), EVENT_NAME, serializeData());
35
+    }
36
+
37
+    private WritableMap serializeData() {
38
+        WritableMap data = Arguments.createMap();
39
+        data.putInt(KEY_POSITION, mPosition);
40
+        return data;
41
+    }
42
+}

+ 70
- 0
android/app/src/main/java/com/reactnativenavigation/layouts/ReactTabLayout.java Näytä tiedosto

@@ -0,0 +1,70 @@
1
+package com.reactnativenavigation.layouts;
2
+
3
+import android.content.Context;
4
+import android.support.design.widget.TabLayout;
5
+
6
+import java.util.ArrayList;
7
+import java.util.List;
8
+import java.util.UUID;
9
+
10
+/**
11
+ *
12
+ * Created by guyc on 06/03/16.
13
+ */
14
+public class ReactTabLayout extends TabLayout {
15
+
16
+    public enum InitialState {
17
+        TAB_POSITION_UNSET,
18
+        TAB_POSITION_SET,
19
+        TAB_SELECTED
20
+    }
21
+
22
+    private List<Tab> mTabs = new ArrayList<>();
23
+    private List<Integer> mIds = new ArrayList<>();
24
+    private InitialState mInitialState = InitialState.TAB_POSITION_UNSET;
25
+    private int mInitialTabPosition;
26
+
27
+    public ReactTabLayout(Context context) {
28
+        super(context);
29
+    }
30
+
31
+
32
+    @Override
33
+    public void addTab(Tab tab) {
34
+        super.addTab(tab);
35
+        mTabs.add(tab);
36
+        mIds.add(UUID.randomUUID().hashCode());
37
+    }
38
+
39
+    public int getId(int index) {
40
+        return mIds.get(index);
41
+    }
42
+
43
+    public int indexOf(Tab tab) {
44
+        return mTabs.indexOf(tab);
45
+    }
46
+
47
+    @Override
48
+    public void removeAllTabs() {
49
+        mTabs.clear();
50
+        mIds.clear();
51
+        super.removeAllTabs();
52
+    }
53
+
54
+    public InitialState getInitialState() {
55
+        return mInitialState;
56
+    }
57
+
58
+    public int getInitialTabPosition() {
59
+        return mInitialTabPosition;
60
+    }
61
+
62
+    public void setInitialState(InitialState initialState) {
63
+        mInitialState = initialState;
64
+    }
65
+
66
+    public void setInitialTabPosition(int initialTabPosition) {
67
+        mInitialTabPosition = initialTabPosition;
68
+    }
69
+}
70
+

+ 109
- 0
android/app/src/main/java/com/reactnativenavigation/managers/AppBarLayoutManager.java Näytä tiedosto

@@ -0,0 +1,109 @@
1
+package com.reactnativenavigation.managers;
2
+
3
+import android.support.design.widget.AppBarLayout;
4
+import android.view.View;
5
+
6
+import com.facebook.infer.annotation.Assertions;
7
+import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
8
+import com.facebook.react.bridge.ReadableArray;
9
+import com.facebook.react.bridge.ReadableMap;
10
+import com.facebook.react.common.MapBuilder;
11
+import com.facebook.react.uimanager.ThemedReactContext;
12
+import com.facebook.react.uimanager.ViewGroupManager;
13
+import com.facebook.react.uimanager.annotations.ReactProp;
14
+
15
+import java.util.Map;
16
+
17
+/**
18
+ * Created by guyc on 08/03/16.
19
+ */
20
+public class AppBarLayoutManager extends ViewGroupManager<AppBarLayout> {
21
+    private static final String REACT_CLASS = "AppbarLayout";
22
+    private static final int COMMAND_SET_CHILDREN_SCROLL_FLAGS = 1;
23
+
24
+    @Override
25
+    public String getName() {
26
+        return REACT_CLASS;
27
+    }
28
+
29
+    @Override
30
+    protected AppBarLayout createViewInstance(ThemedReactContext reactContext) {
31
+        AppBarLayout appBarLayout = new AppBarLayout(reactContext);
32
+        appBarLayout.setFitsSystemWindows(true);
33
+        return appBarLayout;
34
+    }
35
+
36
+    @Override
37
+    public boolean needsCustomLayoutForChildren() {
38
+        return true;
39
+    }
40
+
41
+    @Override
42
+    public Map<String,Integer> getCommandsMap() {
43
+        return MapBuilder.of(
44
+                "setChildrenScrollFlags", COMMAND_SET_CHILDREN_SCROLL_FLAGS);
45
+    }
46
+
47
+    @Override
48
+    public void receiveCommand(AppBarLayout view, int commandType, ReadableArray args) {
49
+        Assertions.assertNotNull(view);
50
+        Assertions.assertNotNull(args);
51
+
52
+        switch (commandType) {
53
+            case COMMAND_SET_CHILDREN_SCROLL_FLAGS: {
54
+                ReadableArray options = args.getArray(0);
55
+                setChildrenScrollFlags(view, options);
56
+                return;
57
+            }
58
+
59
+            default:
60
+                throw new JSApplicationIllegalArgumentException(String.format(
61
+                        "Unsupported command %d received by %s.",
62
+                        commandType,
63
+                        getClass().getSimpleName()));
64
+        }
65
+    }
66
+
67
+    @ReactProp(name = "childrenScrollFlags")
68
+    public void setScrollFlags(AppBarLayout view, ReadableArray options) {
69
+        setChildrenScrollFlags(view, options);
70
+    }
71
+
72
+    private void setChildrenScrollFlags(AppBarLayout view, ReadableArray options) {
73
+        try {
74
+            int optionSize = options.size();
75
+            for (int i=0; i<optionSize; i++) {
76
+
77
+                ReadableMap optionMap = options.getMap(i);
78
+                ReadableArray scrollFlags = optionMap.getArray("scrollFlags");
79
+
80
+                int scrollFlagsSize = scrollFlags.size();
81
+                int scrollFlagsInteger = 0;
82
+
83
+                for (int j=0; j<scrollFlagsSize; j++) {
84
+                    String scrollFlagString = scrollFlags.getString(j);
85
+
86
+                    if ("enterAlways".equals(scrollFlagString)) {
87
+                        scrollFlagsInteger = scrollFlagsInteger | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS;
88
+                    } else if ("enterAlwaysCollapsed".equals(scrollFlagString)) {
89
+                        scrollFlagsInteger = scrollFlagsInteger | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED;
90
+                    } else if ("exitUntilCollapsed".equals(scrollFlagString)) {
91
+                        scrollFlagsInteger = scrollFlagsInteger | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED;
92
+                    } else if ("scroll".equals(scrollFlagString)) {
93
+                        scrollFlagsInteger = scrollFlagsInteger | AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL;
94
+                    } else if ("snap".equals(scrollFlagString)) {
95
+                        scrollFlagsInteger = scrollFlagsInteger | AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP;
96
+                    }
97
+                }
98
+
99
+                View childView = view.getChildAt(optionMap.getInt("index"));
100
+                AppBarLayout.LayoutParams param = (AppBarLayout.LayoutParams) childView.getLayoutParams();
101
+
102
+                //noinspection ResourceType
103
+                param.setScrollFlags(scrollFlagsInteger);
104
+            }
105
+        } catch (Exception e) {
106
+            // TODO: Handle Exception
107
+        }
108
+    }
109
+}

+ 48
- 0
android/app/src/main/java/com/reactnativenavigation/managers/CoordinatorLayoutManager.java Näytä tiedosto

@@ -0,0 +1,48 @@
1
+package com.reactnativenavigation.managers;
2
+
3
+import android.support.design.widget.CoordinatorLayout;
4
+import android.view.View;
5
+
6
+import com.facebook.react.common.MapBuilder;
7
+import com.facebook.react.uimanager.ThemedReactContext;
8
+import com.facebook.react.uimanager.ViewGroupManager;
9
+
10
+import java.util.Map;
11
+
12
+/**
13
+ * Created by guyc on 19/03/16.
14
+ */
15
+public class CoordinatorLayoutManager extends ViewGroupManager<CoordinatorLayout> {
16
+    private static final String REACT_CLASS = "CoordinatorLayout";
17
+    private static final String COMMAND_CHILD_FLAGS = "setChildFlags";
18
+    private static final int COMMAND_SET_CHILD_FLAGS_TYPE = 1;
19
+
20
+    @Override
21
+    public String getName() {
22
+        return REACT_CLASS;
23
+    }
24
+
25
+    @Override
26
+    public boolean needsCustomLayoutForChildren() {
27
+        return true;
28
+    }
29
+
30
+    @Override
31
+    protected CoordinatorLayout createViewInstance(ThemedReactContext reactContext) {
32
+        CoordinatorLayout coordinatorLayout = new CoordinatorLayout(reactContext);
33
+        coordinatorLayout.setFitsSystemWindows(true);
34
+        return coordinatorLayout;
35
+    }
36
+
37
+
38
+    @Override
39
+    public void addView(CoordinatorLayout parent, View child, int index) {
40
+        child.setFitsSystemWindows(true);
41
+        super.addView(parent, child, index);
42
+    }
43
+
44
+    @Override
45
+    public Map<String, Integer> getCommandsMap() {
46
+        return MapBuilder.of(COMMAND_CHILD_FLAGS, COMMAND_SET_CHILD_FLAGS_TYPE);
47
+    }
48
+}

+ 293
- 0
android/app/src/main/java/com/reactnativenavigation/managers/TabLayoutManager.java Näytä tiedosto

@@ -0,0 +1,293 @@
1
+package com.reactnativenavigation.managers;
2
+
3
+import android.content.Context;
4
+import android.graphics.drawable.Drawable;
5
+import android.support.design.widget.TabLayout;
6
+import android.support.v4.view.ViewPager;
7
+import android.util.Log;
8
+import android.view.View;
9
+import android.view.ViewGroup;
10
+
11
+import com.facebook.infer.annotation.Assertions;
12
+import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
13
+import com.facebook.react.bridge.ReadableArray;
14
+import com.facebook.react.bridge.ReadableMap;
15
+import com.facebook.react.common.MapBuilder;
16
+import com.facebook.react.uimanager.ThemedReactContext;
17
+import com.facebook.react.uimanager.UIManagerModule;
18
+import com.facebook.react.uimanager.ViewGroupManager;
19
+import com.facebook.react.uimanager.annotations.ReactProp;
20
+import com.facebook.react.uimanager.events.EventDispatcher;
21
+import com.reactnativenavigation.events.TabSelectedEvent;
22
+import com.reactnativenavigation.layouts.ReactTabLayout;
23
+import com.reactnativenavigation.layouts.ReactTabLayout.InitialState;
24
+import com.reactnativenavigation.utils.ResourceUtils;
25
+
26
+import java.util.Map;
27
+
28
+import static android.support.design.widget.TabLayout.Tab;
29
+
30
+/**
31
+ *
32
+ * Created by guyc on 06/03/16.
33
+ */
34
+public class TabLayoutManager extends ViewGroupManager<ReactTabLayout> {
35
+    private static final String REACT_CLASS = "TabLayout";
36
+    public static final int COMMAND_SET_VIEW_PAGER_TYPE = 1;
37
+    public static final String PARAM_ICON = "icon";
38
+    public static final String PARAM_TEXT = "text";
39
+    public static final String REGISTRATION_NAME = "registrationName";
40
+    public static final String EVENT_ON_TAB_SELECTED = "onTabSelected";
41
+    public static final String COMMAND_SET_VIEW_PAGER = "setViewPager";
42
+    private static final String TAG = TabLayoutManager.class.getSimpleName();
43
+
44
+    private enum TabMode {
45
+        SCROLLABLE(TabLayout.MODE_SCROLLABLE),
46
+        FIXED(TabLayout.MODE_FIXED);
47
+
48
+        int mode;
49
+
50
+        TabMode(int mode) {
51
+            this.mode = mode;
52
+        }
53
+
54
+        public static TabMode fromString(String text) {
55
+            return text != null ? Enum.valueOf(TabMode.class, text.trim().toUpperCase()) : null;
56
+        }
57
+    }
58
+
59
+    private enum TabGravity {
60
+        FILL(TabLayout.GRAVITY_FILL),
61
+        CENTER(TabLayout.GRAVITY_CENTER);
62
+
63
+        int gravity;
64
+
65
+        TabGravity(int gravity) {
66
+            this.gravity = gravity;
67
+        }
68
+
69
+        public static TabGravity fromString(String text) {
70
+            return text != null ? Enum.valueOf(TabGravity.class, text.trim().toUpperCase()) : null;
71
+        }
72
+    }
73
+
74
+    private EventDispatcher mDispatcher;
75
+
76
+    @Override
77
+    public String getName() {
78
+        return REACT_CLASS;
79
+    }
80
+
81
+    @Override
82
+    protected ReactTabLayout createViewInstance(ThemedReactContext reactContext) {
83
+        ReactTabLayout tabLayout = new ReactTabLayout(reactContext);
84
+//        setupWithViewPager(tabLayout);
85
+        return tabLayout;
86
+    }
87
+
88
+    private void setupWithViewPager(final ReactTabLayout tabLayout, final ReadableArray tabs) {
89
+        tabLayout.post(new Runnable() {
90
+            @Override
91
+            public void run() {
92
+                if (tabLayout.getParent() == null) {
93
+                    Log.e(TAG, "Tried to setupViewPager but parent is null");
94
+                    return;
95
+                }
96
+                
97
+                ViewGroup parent = (ViewGroup) tabLayout.getParent().getParent();
98
+                if (parent == null) {
99
+                    return;
100
+                }
101
+
102
+                for (int i = 0; i < parent.getChildCount(); i++) {
103
+                    View child = parent.getChildAt(i);
104
+                    if (child instanceof ViewPager) {
105
+                        // Setup TabLayout with ViewPager
106
+                        ViewPager viewPager = (ViewPager) child;
107
+                        tabLayout.setupWithViewPager(viewPager);
108
+
109
+                        // Add tabs
110
+                        if (tabs != null) {
111
+                            tabLayout.removeAllTabs();
112
+                            populateTabLayoutWithTabs(tabLayout, tabs);
113
+                            tabLayout.setOnTabSelectedListener(new OnTabSelectedListener(viewPager, tabLayout, TabLayoutManager.this));
114
+                        }
115
+                    }
116
+                }
117
+
118
+                Log.i("GUY", "childCount" + parent.getChildCount());
119
+                for (int i = 0; i < parent.getChildCount(); i++) {
120
+                    Log.d("GUY", "[" + 1 + "] " + parent.getChildAt(i).getClass().getSimpleName());
121
+                }
122
+            }
123
+        });
124
+
125
+    }
126
+
127
+    @Override
128
+    public void addView(ReactTabLayout tabLayout, View child, int index) {
129
+        Tab tab = tabLayout.newTab();
130
+        tabLayout.addTab(tab);
131
+
132
+        // when initial position was stored, update tab selection
133
+        if (tabLayout.getInitialState() == InitialState.TAB_POSITION_SET &&
134
+            tabLayout.getInitialTabPosition() == index) {
135
+            tabLayout.setInitialState(InitialState.TAB_SELECTED);
136
+            tab.select();
137
+        }
138
+    }
139
+
140
+    @ReactProp(name = "tabs")
141
+    public void setTabs(ReactTabLayout tabLayout, ReadableArray tabs) {
142
+        setupWithViewPager(tabLayout, tabs);
143
+    }
144
+
145
+
146
+    @ReactProp(name = "selectedTab", defaultInt = 0)
147
+    public void setSelectedTab(ReactTabLayout view, int selectedTab) {
148
+        selectTab(view, selectedTab);
149
+    }
150
+
151
+    private void selectTab(ReactTabLayout tabLayout, int position) {
152
+        if (position < 0 || position >= tabLayout.getTabCount()) {
153
+            Log.w(REACT_CLASS, "Tried to select tab " + position + " but index is out of bounds");
154
+            return;
155
+        }
156
+
157
+        Tab tab = tabLayout.getTabAt(position);
158
+        if (tab != null) {
159
+            tab.select();
160
+        }
161
+    }
162
+
163
+    @ReactProp(name = "selectedTabIndicatorColor")
164
+    public void setSelectedTabIndicatorColor(ReactTabLayout view, int indicatorColor) {
165
+        view.setSelectedTabIndicatorColor(indicatorColor);
166
+    }
167
+
168
+    @ReactProp(name = "tabMode")
169
+    public void setTabMode(ReactTabLayout view, String mode) {
170
+        TabMode tabMode = TabMode.fromString(mode);
171
+        if (tabMode == null) {
172
+            Log.w(REACT_CLASS, "Invalid tabMode [" + tabMode + "]");
173
+        } else {
174
+            view.setTabMode(tabMode.mode);
175
+        }
176
+    }
177
+
178
+    @ReactProp(name = "tabGravity")
179
+    public void setTabGravity(ReactTabLayout view, String gravity) {
180
+        TabGravity tabGravity = TabGravity.fromString(gravity);
181
+        if (tabGravity == null) {
182
+            Log.w(REACT_CLASS, "Invalid tabGravity [" + gravity + "]");
183
+        } else {
184
+            view.setTabGravity(tabGravity.gravity);
185
+        }
186
+    }
187
+
188
+    @Override
189
+    public boolean needsCustomLayoutForChildren() {
190
+        return true;
191
+    }
192
+
193
+    @Override
194
+    protected void addEventEmitters(ThemedReactContext reactContext, ReactTabLayout view) {
195
+        mDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
196
+    }
197
+
198
+//    @Override
199
+//    public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
200
+//        return MapBuilder.of(
201
+//                TabSelectedEvent.EVENT_NAME, (Object) MapBuilder.of(REGISTRATION_NAME, EVENT_ON_TAB_SELECTED)
202
+//        );
203
+//    }
204
+
205
+    /*
206
+    * This method allows us to expose an interface which we can use from react.
207
+    * If we obtain a reference to this native view, we can call `setViewPager` method and handle
208
+    * the call in `receiveCommand`
209
+    * */
210
+    @Override
211
+    public Map<String, Integer> getCommandsMap() {
212
+        return MapBuilder.of(COMMAND_SET_VIEW_PAGER, COMMAND_SET_VIEW_PAGER_TYPE);
213
+    }
214
+
215
+    @Override
216
+    public void receiveCommand(ReactTabLayout tabLayout, int commandType, ReadableArray args) {
217
+        Assertions.assertNotNull(tabLayout);
218
+        Assertions.assertNotNull(args);
219
+
220
+        switch (commandType) {
221
+            case COMMAND_SET_VIEW_PAGER_TYPE: {
222
+                // Setup TabLayout with ViewPager
223
+                int viewPagerId = args.getInt(0);
224
+                ViewPager viewPager = (ViewPager) tabLayout.getRootView().findViewById(viewPagerId);
225
+                tabLayout.setupWithViewPager(viewPager);
226
+
227
+                // Add tabs
228
+                ReadableArray tabs = args.getArray(1);
229
+                if (tabs != null) {
230
+                    tabLayout.removeAllTabs();
231
+                    this.populateTabLayoutWithTabs(tabLayout, tabs);
232
+//                    tabLayout.setOnTabSelectedListener(new OnTabSelectedListener(viewPager, tabLayout, this));
233
+                }
234
+
235
+                return;
236
+            }
237
+
238
+            default:
239
+                throw new JSApplicationIllegalArgumentException(String.format(
240
+                        "Unsupported command %d received by %s.", commandType, REACT_CLASS));
241
+        }
242
+    }
243
+
244
+    private void populateTabLayoutWithTabs(ReactTabLayout tabLayout, ReadableArray tabs) {
245
+        for (int i = 0; i < tabs.size(); i++) {
246
+            ReadableMap tabMap = tabs.getMap(i);
247
+            TabLayout.Tab tab = tabLayout.newTab();
248
+
249
+            // Set tab text
250
+            if (tabMap.hasKey(PARAM_TEXT)) {
251
+                tab.setText(tabMap.getString(PARAM_TEXT));
252
+            }
253
+
254
+            // Set tab icon
255
+            if (tabMap.hasKey(PARAM_ICON)) {
256
+                Context ctx = tabLayout.getContext();
257
+                Drawable icon = ResourceUtils.getDrawable(ctx, tabMap.getString(PARAM_ICON));
258
+                if (icon != null) {
259
+                    tab.setIcon(icon);
260
+                }
261
+            }
262
+
263
+            tabLayout.addTab(tab);
264
+        }
265
+    }
266
+
267
+    private static class OnTabSelectedListener extends TabLayout.ViewPagerOnTabSelectedListener {
268
+        private final ReactTabLayout mTabLayout;
269
+        private TabLayoutManager mTabLayoutManager;
270
+
271
+        public OnTabSelectedListener(ViewPager viewPager, ReactTabLayout tabLayout, TabLayoutManager manager) {
272
+            super(viewPager);
273
+            mTabLayout = tabLayout;
274
+            mTabLayoutManager = manager;
275
+        }
276
+
277
+        @Override
278
+        public void onTabSelected(Tab tab) {
279
+            super.onTabSelected(tab);
280
+            int position = mTabLayout.indexOf(tab);
281
+            mTabLayoutManager.mDispatcher.dispatchEvent(new TabSelectedEvent(mTabLayout.getId(position), position));
282
+            mTabLayoutManager.mDispatcher.dispatchEvent(new TabSelectedEvent(mTabLayout.getId(), position));
283
+        }
284
+
285
+        @Override
286
+        public void onTabUnselected(Tab tab) {
287
+        }
288
+
289
+        @Override
290
+        public void onTabReselected(Tab tab) {
291
+        }
292
+    }
293
+}

+ 40
- 0
android/app/src/main/java/com/reactnativenavigation/managers/ToolbarManager.java Näytä tiedosto

@@ -0,0 +1,40 @@
1
+package com.reactnativenavigation.managers;
2
+
3
+import android.content.Context;
4
+import android.support.v7.widget.Toolbar;
5
+import android.view.LayoutInflater;
6
+
7
+import com.facebook.react.uimanager.ThemedReactContext;
8
+import com.facebook.react.uimanager.ViewGroupManager;
9
+import com.facebook.react.uimanager.annotations.ReactProp;
10
+import com.reactnativenavigation.R;
11
+
12
+/**
13
+ *
14
+ * Created by guyc on 19/03/16.
15
+ */
16
+public class ToolbarManager extends ViewGroupManager<Toolbar> {
17
+    private static final String REACT_CLASS = "Toolbar";
18
+
19
+    @Override
20
+    public String getName() {
21
+        return REACT_CLASS;
22
+    }
23
+
24
+    @Override
25
+    public boolean needsCustomLayoutForChildren() {
26
+        return true;
27
+    }
28
+
29
+    @Override
30
+    protected Toolbar createViewInstance(ThemedReactContext reactContext) {
31
+        return (Toolbar)
32
+                ((LayoutInflater) reactContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
33
+                .inflate(R.layout.toolbar, null, false);
34
+    }
35
+
36
+    @ReactProp(name = "title")
37
+    public void setTitle(Toolbar view, String title) {
38
+        view.setTitle(title);
39
+    }
40
+}

+ 62
- 0
android/app/src/main/java/com/reactnativenavigation/modules/RctActivityModule.java Näytä tiedosto

@@ -0,0 +1,62 @@
1
+package com.reactnativenavigation.modules;
2
+
3
+import android.app.Activity;
4
+import android.content.Intent;
5
+import android.os.Bundle;
6
+import android.util.Log;
7
+
8
+import com.facebook.react.bridge.ReactApplicationContext;
9
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
10
+import com.facebook.react.bridge.ReactMethod;
11
+import com.facebook.react.bridge.ReadableArray;
12
+import com.reactnativenavigation.activities.RctActivity;
13
+import com.reactnativenavigation.activities.TabActivity;
14
+import com.reactnativenavigation.adapters.ViewPagerAdapter;
15
+import com.reactnativenavigation.utils.ContextProvider;
16
+
17
+/**
18
+ *
19
+ * Created by guyc on 10/03/16.
20
+ */
21
+public class RctActivityModule extends ReactContextBaseJavaModule {
22
+    public static final String REACT_CLASS = "RctActivity";
23
+
24
+    public RctActivityModule(ReactApplicationContext reactContext) {
25
+        super(reactContext);
26
+    }
27
+
28
+    @Override
29
+    public String getName() {
30
+        return REACT_CLASS;
31
+    }
32
+
33
+    @ReactMethod
34
+    public void startActivity(String componentName) {
35
+        Activity context = ContextProvider.getActivityContext();
36
+        if (context != null && !context.isFinishing()) {
37
+            Intent rctActivityIntent = new Intent(context, RctActivity.class);
38
+            rctActivityIntent.putExtra(RctActivity.EXTRA_COMPONENT_NAME, componentName);
39
+            context.startActivity(rctActivityIntent);
40
+        }
41
+    }
42
+
43
+    @ReactMethod
44
+    public void startTabBasedApp(ReadableArray tabs) {
45
+        Log.v(REACT_CLASS, "Starting tab based app\n" + tabs);
46
+
47
+
48
+        Activity context = ContextProvider.getActivityContext();
49
+        if (context != null && !context.isFinishing()) {
50
+            // Create the intent
51
+            Intent intent = new Intent(context, TabActivity.class);
52
+
53
+
54
+            // Set extras
55
+            Bundle extras = new Bundle();
56
+            extras.putSerializable(TabActivity.EXTRA_TABS, ViewPagerAdapter.createDataSet(tabs));
57
+            intent.putExtras(extras);
58
+
59
+            context.startActivity(intent);
60
+        }
61
+    }
62
+}

+ 36
- 0
android/app/src/main/java/com/reactnativenavigation/modules/RctLayoutManager.java Näytä tiedosto

@@ -0,0 +1,36 @@
1
+package com.reactnativenavigation.modules;
2
+
3
+import android.app.Activity;
4
+import android.content.Intent;
5
+
6
+import com.facebook.react.bridge.ReactApplicationContext;
7
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
8
+import com.facebook.react.bridge.ReactMethod;
9
+import com.reactnativenavigation.activities.RctActivity;
10
+import com.reactnativenavigation.utils.ContextProvider;
11
+
12
+/**
13
+ * Created by guyc on 20/03/16.
14
+ */
15
+public class RctLayoutManager extends ReactContextBaseJavaModule {
16
+    public static final String REACT_CLASS = "RctLayoutManager";
17
+
18
+    public RctLayoutManager(ReactApplicationContext reactContext) {
19
+        super(reactContext);
20
+    }
21
+
22
+    @Override
23
+    public String getName() {
24
+        return REACT_CLASS;
25
+    }
26
+
27
+    @ReactMethod
28
+    public void setLayout(String componentName) {
29
+        Activity context = ContextProvider.getActivityContext();
30
+        if (context != null && !context.isFinishing()) {
31
+            Intent rctActivityIntent = new Intent(context, RctActivity.class);
32
+            rctActivityIntent.putExtra(RctActivity.EXTRA_COMPONENT_NAME, componentName);
33
+            context.startActivity(rctActivityIntent);
34
+        }
35
+    }
36
+}

+ 45
- 0
android/app/src/main/java/com/reactnativenavigation/packages/RCCPackage.java Näytä tiedosto

@@ -0,0 +1,45 @@
1
+package com.reactnativenavigation.packages;
2
+
3
+import com.facebook.react.ReactPackage;
4
+import com.facebook.react.bridge.JavaScriptModule;
5
+import com.facebook.react.bridge.NativeModule;
6
+import com.facebook.react.bridge.ReactApplicationContext;
7
+import com.facebook.react.uimanager.ViewManager;
8
+import com.reactnativenavigation.managers.AppBarLayoutManager;
9
+import com.reactnativenavigation.managers.CoordinatorLayoutManager;
10
+import com.reactnativenavigation.managers.TabLayoutManager;
11
+import com.reactnativenavigation.managers.ToolbarManager;
12
+import com.reactnativenavigation.modules.RctActivityModule;
13
+
14
+import java.util.Arrays;
15
+import java.util.Collections;
16
+import java.util.List;
17
+
18
+/**
19
+ *
20
+ * Created by guyc on 07/03/16.
21
+ */
22
+public class RCCPackage implements ReactPackage {
23
+
24
+    @Override
25
+    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
26
+        return Arrays.<NativeModule>asList(
27
+                new RctActivityModule(reactContext)
28
+        );
29
+    }
30
+
31
+    @Override
32
+    public List<Class<? extends JavaScriptModule>> createJSModules() {
33
+        return Collections.emptyList();
34
+    }
35
+
36
+    @Override
37
+    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
38
+        return Arrays.<ViewManager>asList(
39
+                new TabLayoutManager(),
40
+                new AppBarLayoutManager(),
41
+                new CoordinatorLayoutManager(),
42
+                new ToolbarManager()
43
+        );
44
+    }
45
+}

+ 30
- 0
android/app/src/main/java/com/reactnativenavigation/utils/ContextProvider.java Näytä tiedosto

@@ -0,0 +1,30 @@
1
+package com.reactnativenavigation.utils;
2
+
3
+import android.app.Activity;
4
+
5
+import java.lang.ref.WeakReference;
6
+
7
+/**
8
+ *
9
+ * Created by guyc on 10/03/16.
10
+ */
11
+public class ContextProvider {
12
+    private static WeakReference<Activity> sActivityWR;
13
+
14
+    public static void setActivityContext(Activity activity) {
15
+        if (sActivityWR == null) {
16
+            sActivityWR = new WeakReference<>(activity);
17
+        }
18
+    }
19
+
20
+    public static Activity getActivityContext() {
21
+        return sActivityWR != null ? sActivityWR.get() : null;
22
+    }
23
+
24
+    public static void clearActivityContext() {
25
+        if (sActivityWR != null) {
26
+            sActivityWR.clear();
27
+        }
28
+        sActivityWR = null;
29
+    }
30
+}

+ 21
- 0
android/app/src/main/java/com/reactnativenavigation/utils/ResourceUtils.java Näytä tiedosto

@@ -0,0 +1,21 @@
1
+package com.reactnativenavigation.utils;
2
+
3
+import android.content.Context;
4
+import android.content.res.Resources;
5
+import android.graphics.drawable.Drawable;
6
+import android.support.v4.content.res.ResourcesCompat;
7
+
8
+/**
9
+ * Created by guyc on 17/03/16.
10
+ */
11
+public class ResourceUtils {
12
+
13
+    public static final String TYPE_DRAWABLE = "drawable";
14
+
15
+    public static Drawable getDrawable(Context context, String resourceName) {
16
+        Resources resources = context.getResources();
17
+        int id =  resources.getIdentifier(resourceName, TYPE_DRAWABLE, context.getPackageName());
18
+        return id > 0 ? ResourcesCompat.getDrawable(resources, id, context.getTheme()) : null;
19
+    }
20
+
21
+}

+ 28
- 0
android/app/src/main/java/com/reactnativenavigation/views/RctView.java Näytä tiedosto

@@ -0,0 +1,28 @@
1
+package com.reactnativenavigation.views;
2
+
3
+import android.widget.FrameLayout;
4
+
5
+import com.facebook.react.ReactInstanceManager;
6
+import com.facebook.react.ReactRootView;
7
+import com.reactnativenavigation.activities.BaseReactActivity;
8
+
9
+
10
+/**
11
+ *
12
+ * Created by guyc on 10/03/16.
13
+ */
14
+public class RctView extends FrameLayout {
15
+
16
+    public RctView(BaseReactActivity ctx, ReactInstanceManager rctInstanceManager, String componentName) {
17
+        super(ctx);
18
+        setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
19
+
20
+        ReactRootView root = new ReactRootView(ctx);
21
+        root.setLayoutParams(new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
22
+        root.startReactApplication(rctInstanceManager, componentName, null);
23
+        addView(root);
24
+
25
+        rctInstanceManager.onResume(ctx, ctx);
26
+    }
27
+}
28
+

+ 37
- 0
android/app/src/main/res/layout/tab_activity.xml Näytä tiedosto

@@ -0,0 +1,37 @@
1
+<?xml version="1.0" encoding="utf-8"?>
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">
9
+
10
+    <android.support.design.widget.CoordinatorLayout
11
+        android:id="@+id/coordinator_layout"
12
+        android:layout_width="match_parent"
13
+        android:layout_height="wrap_content">
14
+        <android.support.design.widget.AppBarLayout
15
+            android:id="@+id/appbar"
16
+            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>
31
+
32
+    <android.support.v4.view.ViewPager
33
+        android:id="@+id/viewPager"
34
+        app:layout_behavior="@string/appbar_scrolling_view_behavior"
35
+        android:layout_width="match_parent"
36
+        android:layout_height="match_parent"/>
37
+</LinearLayout>

+ 8
- 0
android/app/src/main/res/layout/toolbar.xml Näytä tiedosto

@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<app:android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
3
+    xmlns:app="http://schemas.android.com/apk/res-auto"
4
+    android:id="@+id/toolbar"
5
+    android:layout_width="match_parent"
6
+    android:layout_height="?attr/actionBarSize"
7
+    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
8
+    app:layout_collapseMode="pin"/>

+ 4
- 0
android/app/src/main/res/values/ids.xml Näytä tiedosto

@@ -0,0 +1,4 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<resources>
3
+    <item name="react_root_view" type="id"/>
4
+</resources>

+ 24
- 0
android/build.gradle Näytä tiedosto

@@ -0,0 +1,24 @@
1
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
2
+
3
+buildscript {
4
+    repositories {
5
+        jcenter()
6
+    }
7
+    dependencies {
8
+        classpath 'com.android.tools.build:gradle:1.3.1'
9
+
10
+        // NOTE: Do not place your application dependencies here; they belong
11
+        // in the individual module build.gradle files
12
+    }
13
+}
14
+
15
+allprojects {
16
+    repositories {
17
+        mavenLocal()
18
+        jcenter()
19
+        maven {
20
+            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
21
+            url "$projectDir/../../node_modules/react-native/android"
22
+        }
23
+    }
24
+}

+ 20
- 0
android/gradle.properties Näytä tiedosto

@@ -0,0 +1,20 @@
1
+# Project-wide Gradle settings.
2
+
3
+# IDE (e.g. Android Studio) users:
4
+# Gradle settings configured through the IDE *will override*
5
+# any settings specified in this file.
6
+
7
+# For more details on how to configure your build environment visit
8
+# http://www.gradle.org/docs/current/userguide/build_environment.html
9
+
10
+# Specifies the JVM arguments used for the daemon process.
11
+# The setting is particularly useful for tweaking memory settings.
12
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
13
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14
+
15
+# When configured, Gradle will run in incubating parallel mode.
16
+# This option should only be used with decoupled projects. More details, visit
17
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18
+# org.gradle.parallel=true
19
+
20
+android.useDeprecatedNdk=true

+ 134
- 0
android/react-native-navigation.iml Näytä tiedosto

@@ -0,0 +1,134 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<module external.linked.project.id=":react-native-navigation" external.linked.project.path="$MODULE_DIR$/app" external.root.project.path="$MODULE_DIR$/../../../android" external.system.id="GRADLE" external.system.module.group="example" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
3
+  <component name="FacetManager">
4
+    <facet type="java-gradle" name="Java-Gradle">
5
+      <configuration>
6
+        <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
7
+        <option name="BUILDABLE" value="false" />
8
+      </configuration>
9
+    </facet>
10
+    <facet type="android-gradle" name="Android-Gradle">
11
+      <configuration>
12
+        <option name="GRADLE_PROJECT_PATH" value=":react-native-navigation" />
13
+      </configuration>
14
+    </facet>
15
+    <facet type="android" name="Android">
16
+      <configuration>
17
+        <option name="SELECTED_BUILD_VARIANT" value="libraryDebug" />
18
+        <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
19
+        <option name="ASSEMBLE_TASK_NAME" value="assembleLibraryDebug" />
20
+        <option name="COMPILE_JAVA_TASK_NAME" value="compileLibraryDebugSources" />
21
+        <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleLibraryDebugAndroidTest" />
22
+        <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileLibraryDebugAndroidTestSources" />
23
+        <afterSyncTasks>
24
+          <task>generateLibraryDebugAndroidTestSources</task>
25
+          <task>generateLibraryDebugSources</task>
26
+        </afterSyncTasks>
27
+        <option name="ALLOW_USER_CONFIGURATION" value="false" />
28
+        <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
29
+        <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
30
+        <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/app/src/main/res" />
31
+        <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
32
+        <option name="LIBRARY_PROJECT" value="true" />
33
+      </configuration>
34
+    </facet>
35
+  </component>
36
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
37
+    <output url="file://$MODULE_DIR$/app/build/intermediates/classes/library/debug" />
38
+    <output-test url="file://$MODULE_DIR$/app/build/intermediates/classes/androidTest/library/debug" />
39
+    <exclude-output />
40
+    <content url="file://$MODULE_DIR$/app">
41
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/source/r/library/debug" isTestSource="false" generated="true" />
42
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/source/aidl/library/debug" isTestSource="false" generated="true" />
43
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/source/buildConfig/library/debug" isTestSource="false" generated="true" />
44
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/source/rs/library/debug" isTestSource="false" generated="true" />
45
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/res/rs/library/debug" type="java-resource" />
46
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/res/resValues/library/debug" type="java-resource" />
47
+      <sourceFolder url="file://$MODULE_DIR$/app/src/libraryDebug/res" type="java-resource" />
48
+      <sourceFolder url="file://$MODULE_DIR$/app/src/libraryDebug/resources" type="java-resource" />
49
+      <sourceFolder url="file://$MODULE_DIR$/app/src/libraryDebug/assets" type="java-resource" />
50
+      <sourceFolder url="file://$MODULE_DIR$/app/src/libraryDebug/aidl" isTestSource="false" />
51
+      <sourceFolder url="file://$MODULE_DIR$/app/src/libraryDebug/java" isTestSource="false" />
52
+      <sourceFolder url="file://$MODULE_DIR$/app/src/libraryDebug/jni" isTestSource="false" />
53
+      <sourceFolder url="file://$MODULE_DIR$/app/src/libraryDebug/rs" isTestSource="false" />
54
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/source/r/androidTest/library/debug" isTestSource="true" generated="true" />
55
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/source/aidl/androidTest/library/debug" isTestSource="true" generated="true" />
56
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/source/buildConfig/androidTest/library/debug" isTestSource="true" generated="true" />
57
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/source/rs/androidTest/library/debug" isTestSource="true" generated="true" />
58
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/res/rs/androidTest/library/debug" type="java-test-resource" />
59
+      <sourceFolder url="file://$MODULE_DIR$/app/build/generated/res/resValues/androidTest/library/debug" type="java-test-resource" />
60
+      <sourceFolder url="file://$MODULE_DIR$/app/src/library/res" type="java-resource" />
61
+      <sourceFolder url="file://$MODULE_DIR$/app/src/library/resources" type="java-resource" />
62
+      <sourceFolder url="file://$MODULE_DIR$/app/src/library/assets" type="java-resource" />
63
+      <sourceFolder url="file://$MODULE_DIR$/app/src/library/aidl" isTestSource="false" />
64
+      <sourceFolder url="file://$MODULE_DIR$/app/src/library/java" isTestSource="false" />
65
+      <sourceFolder url="file://$MODULE_DIR$/app/src/library/jni" isTestSource="false" />
66
+      <sourceFolder url="file://$MODULE_DIR$/app/src/library/rs" isTestSource="false" />
67
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTestLibrary/res" type="java-test-resource" />
68
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTestLibrary/resources" type="java-test-resource" />
69
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTestLibrary/assets" type="java-test-resource" />
70
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTestLibrary/aidl" isTestSource="true" />
71
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTestLibrary/java" isTestSource="true" />
72
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTestLibrary/jni" isTestSource="true" />
73
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTestLibrary/rs" isTestSource="true" />
74
+      <sourceFolder url="file://$MODULE_DIR$/app/src/debug/res" type="java-resource" />
75
+      <sourceFolder url="file://$MODULE_DIR$/app/src/debug/resources" type="java-resource" />
76
+      <sourceFolder url="file://$MODULE_DIR$/app/src/debug/assets" type="java-resource" />
77
+      <sourceFolder url="file://$MODULE_DIR$/app/src/debug/aidl" isTestSource="false" />
78
+      <sourceFolder url="file://$MODULE_DIR$/app/src/debug/java" isTestSource="false" />
79
+      <sourceFolder url="file://$MODULE_DIR$/app/src/debug/jni" isTestSource="false" />
80
+      <sourceFolder url="file://$MODULE_DIR$/app/src/debug/rs" isTestSource="false" />
81
+      <sourceFolder url="file://$MODULE_DIR$/app/src/main/res" type="java-resource" />
82
+      <sourceFolder url="file://$MODULE_DIR$/app/src/main/resources" type="java-resource" />
83
+      <sourceFolder url="file://$MODULE_DIR$/app/src/main/assets" type="java-resource" />
84
+      <sourceFolder url="file://$MODULE_DIR$/app/src/main/aidl" isTestSource="false" />
85
+      <sourceFolder url="file://$MODULE_DIR$/app/src/main/java" isTestSource="false" />
86
+      <sourceFolder url="file://$MODULE_DIR$/app/src/main/jni" isTestSource="false" />
87
+      <sourceFolder url="file://$MODULE_DIR$/app/src/main/rs" isTestSource="false" />
88
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTest/res" type="java-test-resource" />
89
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTest/resources" type="java-test-resource" />
90
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTest/assets" type="java-test-resource" />
91
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTest/aidl" isTestSource="true" />
92
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTest/java" isTestSource="true" />
93
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTest/jni" isTestSource="true" />
94
+      <sourceFolder url="file://$MODULE_DIR$/app/src/androidTest/rs" isTestSource="true" />
95
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/annotations" />
96
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/assets" />
97
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/bundles" />
98
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/classes" />
99
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/dependency-cache" />
100
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/exploded-aar/com.facebook.react/react-native/0.20.1/jars" />
101
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/incremental" />
102
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/lint" />
103
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/res" />
104
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/rs" />
105
+      <excludeFolder url="file://$MODULE_DIR$/app/build/intermediates/symbols" />
106
+      <excludeFolder url="file://$MODULE_DIR$/app/build/outputs" />
107
+      <excludeFolder url="file://$MODULE_DIR$/app/build/tmp" />
108
+    </content>
109
+    <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
110
+    <orderEntry type="sourceFolder" forTests="false" />
111
+    <orderEntry type="library" exported="" name="support-annotations-23.1.1" level="project" />
112
+    <orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
113
+    <orderEntry type="library" exported="" name="design-23.1.1" level="project" />
114
+    <orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
115
+    <orderEntry type="library" exported="" name="imagepipeline-0.8.1" level="project" />
116
+    <orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
117
+    <orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
118
+    <orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
119
+    <orderEntry type="library" exported="" name="recyclerview-v7-23.1.1" level="project" />
120
+    <orderEntry type="library" exported="" name="react-native-0.20.1" level="project" />
121
+    <orderEntry type="library" exported="" name="support-v4-23.1.1" level="project" />
122
+    <orderEntry type="library" exported="" name="appcompat-v7-23.1.1" level="project" />
123
+    <orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
124
+    <orderEntry type="library" exported="" name="okhttp-ws-2.5.0" level="project" />
125
+    <orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
126
+    <orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
127
+    <orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
128
+    <orderEntry type="library" exported="" name="drawee-0.8.1" level="project" />
129
+    <orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
130
+    <orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
131
+    <orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
132
+    <orderEntry type="library" exported="" name="library-2.4.0" level="project" />
133
+  </component>
134
+</module>

+ 19
- 0
android/react-navtive-navigation.iml Näytä tiedosto

@@ -0,0 +1,19 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<module external.linked.project.id="react-navtive-navigation" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
3
+  <component name="FacetManager">
4
+    <facet type="java-gradle" name="Java-Gradle">
5
+      <configuration>
6
+        <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
7
+        <option name="BUILDABLE" value="false" />
8
+      </configuration>
9
+    </facet>
10
+  </component>
11
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
12
+    <exclude-output />
13
+    <content url="file://$MODULE_DIR$">
14
+      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
15
+    </content>
16
+    <orderEntry type="inheritedJdk" />
17
+    <orderEntry type="sourceFolder" forTests="false" />
18
+  </component>
19
+</module>