Browse Source

FragmentScreen

Daniel Zlotin 8 years ago
parent
commit
5016c3cc44

+ 4
- 4
android/app/src/main/java/com/reactnativenavigation/controllers/Modal.java View File

@@ -1,8 +1,8 @@
1 1
 package com.reactnativenavigation.controllers;
2 2
 
3
-import android.app.Activity;
4 3
 import android.app.Dialog;
5 4
 import android.content.DialogInterface;
5
+import android.support.v7.app.AppCompatActivity;
6 6
 import android.view.Window;
7 7
 
8 8
 import com.reactnativenavigation.R;
@@ -13,7 +13,7 @@ import com.reactnativenavigation.params.ScreenParams;
13 13
 
14 14
 public class Modal extends Dialog implements DialogInterface.OnDismissListener, ScreenStackContainer {
15 15
 
16
-    private final Activity activity;
16
+    private final AppCompatActivity activity;
17 17
     private final OnModalDismissedListener onModalDismissedListener;
18 18
 
19 19
     public interface OnModalDismissedListener {
@@ -23,7 +23,7 @@ public class Modal extends Dialog implements DialogInterface.OnDismissListener,
23 23
     private final ScreenParams screenParams;
24 24
     private Layout layout;
25 25
 
26
-    public Modal(Activity activity, OnModalDismissedListener onModalDismissedListener, ScreenParams screenParams) {
26
+    public Modal(AppCompatActivity activity, OnModalDismissedListener onModalDismissedListener, ScreenParams screenParams) {
27 27
         super(activity, R.style.Modal);
28 28
         this.activity = activity;
29 29
         this.onModalDismissedListener = onModalDismissedListener;
@@ -31,7 +31,7 @@ public class Modal extends Dialog implements DialogInterface.OnDismissListener,
31 31
         createContent();
32 32
     }
33 33
 
34
-    public Activity getActivity() {
34
+    public AppCompatActivity getActivity() {
35 35
         return activity;
36 36
     }
37 37
 

+ 3
- 3
android/app/src/main/java/com/reactnativenavigation/controllers/ModalController.java View File

@@ -1,6 +1,6 @@
1 1
 package com.reactnativenavigation.controllers;
2 2
 
3
-import android.app.Activity;
3
+import android.support.v7.app.AppCompatActivity;
4 4
 
5 5
 import com.reactnativenavigation.layouts.ScreenStackContainer;
6 6
 import com.reactnativenavigation.params.ScreenParams;
@@ -8,10 +8,10 @@ import com.reactnativenavigation.params.ScreenParams;
8 8
 import java.util.Stack;
9 9
 
10 10
 public class ModalController implements ScreenStackContainer, Modal.OnModalDismissedListener {
11
-    private final Activity activity;
11
+    private final AppCompatActivity activity;
12 12
     private Stack<Modal> stack = new Stack<>();
13 13
 
14
-    public ModalController(Activity activity) {
14
+    public ModalController(AppCompatActivity activity) {
15 15
         this.activity = activity;
16 16
     }
17 17
 

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

@@ -1,11 +1,11 @@
1 1
 package com.reactnativenavigation.layouts;
2 2
 
3
-import android.app.Activity;
3
+import android.support.v7.app.AppCompatActivity;
4 4
 
5 5
 import com.reactnativenavigation.params.ActivityParams;
6 6
 
7 7
 public class LayoutFactory {
8
-    public static Layout create(Activity activity, ActivityParams params) {
8
+    public static Layout create(AppCompatActivity activity, ActivityParams params) {
9 9
         switch (params.type) {
10 10
             case TabBased:
11 11
                 return createBottomTabsScreenLayout(activity, params);
@@ -15,7 +15,7 @@ public class LayoutFactory {
15 15
         }
16 16
     }
17 17
 
18
-    private static Layout createSingleScreenLayout(Activity activity, ActivityParams params) {
18
+    private static Layout createSingleScreenLayout(AppCompatActivity activity, ActivityParams params) {
19 19
         return new SingleScreenLayout(activity, params.screenParams);
20 20
     }
21 21
 

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

@@ -1,6 +1,6 @@
1 1
 package com.reactnativenavigation.layouts;
2 2
 
3
-import android.app.Activity;
3
+import android.support.v7.app.AppCompatActivity;
4 4
 import android.view.View;
5 5
 import android.widget.FrameLayout;
6 6
 
@@ -15,11 +15,13 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
15 15
 
16 16
 public class SingleScreenLayout extends FrameLayout implements Layout {
17 17
 
18
+    private final AppCompatActivity activity;
18 19
     private final ScreenParams screenParams;
19 20
     private ScreenStack stack;
20 21
 
21
-    public SingleScreenLayout(Activity activity, ScreenParams screenParams) {
22
+    public SingleScreenLayout(AppCompatActivity activity, ScreenParams screenParams) {
22 23
         super(activity);
24
+        this.activity = activity;
23 25
         this.screenParams = screenParams;
24 26
         createStack();
25 27
     }
@@ -29,7 +31,7 @@ public class SingleScreenLayout extends FrameLayout implements Layout {
29 31
             stack.destroy();
30 32
             removeView(stack);
31 33
         }
32
-        stack = new ScreenStack(getContext(), screenParams);
34
+        stack = new ScreenStack(activity, screenParams);
33 35
         addView(stack, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
34 36
     }
35 37
 

+ 8
- 0
android/app/src/main/java/com/reactnativenavigation/params/ScreenParams.java View File

@@ -13,6 +13,10 @@ public class ScreenParams {
13 13
     public String title;
14 14
     public ScreenStyleParams styleParams;
15 15
     public List<TopTabParams> topTabParams;
16
+    public String fragmentCreatorClassName;
17
+
18
+    //    public String tabLabel; TODO when tabs are supported move to TabParams
19
+    //    public Drawable tabIcon;
16 20
     public String tabLabel;
17 21
     public Drawable tabIcon;
18 22
 
@@ -24,4 +28,8 @@ public class ScreenParams {
24 28
     public boolean hasTopTabs() {
25 29
         return topTabParams != null && !topTabParams.isEmpty();
26 30
     }
31
+
32
+    public boolean isFragmentScreen() {
33
+        return fragmentCreatorClassName != null;
34
+    }
27 35
 }

+ 5
- 1
android/app/src/main/java/com/reactnativenavigation/params/parsers/ScreenParamsParser.java View File

@@ -18,7 +18,8 @@ public class ScreenParamsParser extends Parser {
18 18
     private static final String KEY_RIGHT_BUTTONS = "rightButtons";
19 19
     private static final String KEY_LEFT_BUTTON = "leftButton";
20 20
     private static final String STYLE_PARAMS = "styleParams";
21
-    public static final String TOP_TABS = "topTabs";
21
+    private static final String TOP_TABS = "topTabs";
22
+    private static final String FRAGMENT_CREATOR_CLASS_NAME = "fragmentCreatorClassName";
22 23
 
23 24
     @SuppressWarnings("ConstantConditions")
24 25
     public static ScreenParams parse(Bundle params) {
@@ -41,6 +42,9 @@ public class ScreenParamsParser extends Parser {
41 42
         if (hasKey(params, TOP_TABS)) {
42 43
             result.topTabParams = TopTabParamsParser.parse(params.getBundle(TOP_TABS));
43 44
         }
45
+        if (hasKey(params, FRAGMENT_CREATOR_CLASS_NAME)) {
46
+            result.fragmentCreatorClassName = params.getString(FRAGMENT_CREATOR_CLASS_NAME);
47
+        }
44 48
         if (hasKey(params, "label")) {
45 49
             result.tabLabel = params.getString("label");
46 50
         }

+ 107
- 0
android/app/src/main/java/com/reactnativenavigation/screens/FragmentScreen.java View File

@@ -0,0 +1,107 @@
1
+package com.reactnativenavigation.screens;
2
+
3
+import android.app.Fragment;
4
+import android.app.FragmentManager;
5
+import android.app.FragmentTransaction;
6
+import android.os.Bundle;
7
+import android.support.annotation.Nullable;
8
+import android.support.v7.app.AppCompatActivity;
9
+import android.widget.FrameLayout;
10
+
11
+import com.reactnativenavigation.params.ScreenParams;
12
+import com.reactnativenavigation.utils.ViewUtils;
13
+import com.reactnativenavigation.views.TitleBarBackButtonListener;
14
+
15
+import java.lang.reflect.InvocationTargetException;
16
+import java.lang.reflect.Method;
17
+
18
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
19
+
20
+@SuppressWarnings("ResourceType")
21
+public class FragmentScreen extends Screen {
22
+
23
+    private static final String CONTRACT_GET_FRAGMENT = "getFragment";
24
+    private static final String CONTRACT_GET_SUPPORT_FRAGMENT = "getSupportFragment";
25
+    private final AppCompatActivity activity;
26
+    private FrameLayout content;
27
+
28
+    public FragmentScreen(AppCompatActivity activity, ScreenParams screenParams, TitleBarBackButtonListener titleBarBackButtonListener) {
29
+        super(activity, screenParams, titleBarBackButtonListener);
30
+        this.activity = activity;
31
+    }
32
+
33
+    @Override
34
+    protected void createContent() {
35
+        content = new FrameLayout(getContext());
36
+        content.setId(ViewUtils.generateViewId());
37
+        addView(content, MATCH_PARENT, MATCH_PARENT);
38
+        addFragment();
39
+    }
40
+
41
+    private void addFragment() {
42
+        try {
43
+            Fragment fragment = tryGetFragment();
44
+            if (fragment != null) {
45
+                addFragment(fragment);
46
+                return;
47
+            }
48
+
49
+            android.support.v4.app.Fragment supportFragment = tryGetSupportFragment();
50
+            if (supportFragment != null) {
51
+                addSupportFragment(supportFragment);
52
+                return;
53
+            }
54
+            throw new RuntimeException("must provide public static method " + CONTRACT_GET_FRAGMENT + " or " + CONTRACT_GET_SUPPORT_FRAGMENT);
55
+        } catch (Exception e) {
56
+            throw new RuntimeException(e);
57
+        }
58
+    }
59
+
60
+    private void addFragment(Fragment fragment) {
61
+        FragmentManager fm = activity.getFragmentManager();
62
+        FragmentTransaction transaction = fm.beginTransaction();
63
+        transaction.add(content.getId(), fragment);
64
+        transaction.commit();
65
+    }
66
+
67
+    private void addSupportFragment(android.support.v4.app.Fragment supportFragment) {
68
+        android.support.v4.app.FragmentManager fm = activity.getSupportFragmentManager();
69
+        android.support.v4.app.FragmentTransaction transaction = fm.beginTransaction();
70
+        transaction.add(content.getId(), supportFragment);
71
+        transaction.commit();
72
+    }
73
+
74
+    @Nullable
75
+    private Fragment tryGetFragment() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException {
76
+        try {
77
+            String className = screenParams.fragmentCreatorClassName;
78
+            Class<?> fragmentCreatorClass = Class.forName(className);
79
+            Method method = fragmentCreatorClass.getMethod(CONTRACT_GET_FRAGMENT, Bundle.class);
80
+            return (android.app.Fragment) method.invoke(null, screenParams.passProps);
81
+        } catch (NoSuchMethodException noSuchMethod) {
82
+            return null;
83
+        }
84
+    }
85
+
86
+    @Nullable
87
+    private android.support.v4.app.Fragment tryGetSupportFragment() throws ClassNotFoundException, IllegalAccessException, InvocationTargetException {
88
+        try {
89
+            String className = screenParams.fragmentCreatorClassName;
90
+            Class<?> fragmentCreatorClass = Class.forName(className);
91
+            Method method = fragmentCreatorClass.getMethod(CONTRACT_GET_SUPPORT_FRAGMENT, Bundle.class);
92
+            return (android.support.v4.app.Fragment) method.invoke(null, screenParams.passProps);
93
+        } catch (NoSuchMethodException noSuchMethod) {
94
+            return null;
95
+        }
96
+    }
97
+
98
+    @Override
99
+    public void ensureUnmountOnDetachedFromWindow() {
100
+        // nothing
101
+    }
102
+
103
+    @Override
104
+    public void preventUnmountOnDetachedFromWindow() {
105
+        // nothing
106
+    }
107
+}

+ 1
- 1
android/app/src/main/java/com/reactnativenavigation/screens/Screen.java View File

@@ -28,8 +28,8 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
28 28
 public abstract class Screen extends RelativeLayout implements ScrollDirectionListener.OnScrollChanged {
29 29
 
30 30
     protected final ScreenParams screenParams;
31
-    private final TitleBarBackButtonListener titleBarBackButtonListener;
32 31
     protected TopBar topBar;
32
+    private final TitleBarBackButtonListener titleBarBackButtonListener;
33 33
     private VisibilityAnimator topBarVisibilityAnimator;
34 34
 
35 35
     public Screen(Context context, ScreenParams screenParams, TitleBarBackButtonListener titleBarBackButtonListener) {

+ 7
- 5
android/app/src/main/java/com/reactnativenavigation/screens/ScreenFactory.java View File

@@ -1,18 +1,20 @@
1 1
 package com.reactnativenavigation.screens;
2 2
 
3
-import android.content.Context;
3
+import android.support.v7.app.AppCompatActivity;
4 4
 
5 5
 import com.reactnativenavigation.params.ScreenParams;
6 6
 import com.reactnativenavigation.views.TitleBarBackButtonListener;
7 7
 
8 8
 public class ScreenFactory {
9
-    public static Screen create(Context context,
9
+    public static Screen create(AppCompatActivity activity,
10 10
                                 ScreenParams screenParams,
11 11
                                 TitleBarBackButtonListener titleBarBackButtonListener) {
12
-        if (screenParams.hasTopTabs()) {
13
-            return new TabbedScreen(context, screenParams, titleBarBackButtonListener);
12
+        if (screenParams.isFragmentScreen()) {
13
+            return new FragmentScreen(activity, screenParams, titleBarBackButtonListener);
14
+        } else if (screenParams.hasTopTabs()) {
15
+            return new TabbedScreen(activity, screenParams, titleBarBackButtonListener);
14 16
         } else {
15
-            return new SingleScreen(context, screenParams, titleBarBackButtonListener);
17
+            return new SingleScreen(activity, screenParams, titleBarBackButtonListener);
16 18
         }
17 19
     }
18 20
 }

+ 6
- 4
android/app/src/main/java/com/reactnativenavigation/screens/ScreenStack.java View File

@@ -1,7 +1,7 @@
1 1
 package com.reactnativenavigation.screens;
2 2
 
3 3
 import android.animation.LayoutTransition;
4
-import android.content.Context;
4
+import android.support.v7.app.AppCompatActivity;
5 5
 import android.widget.FrameLayout;
6 6
 
7 7
 import com.reactnativenavigation.params.ScreenParams;
@@ -16,10 +16,12 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
16 16
 
17 17
 // TODO there's really no reason for ScreenStack to extend FrameLayout. All screens can be added to parent.
18 18
 public class ScreenStack extends FrameLayout implements TitleBarBackButtonListener {
19
+    private final AppCompatActivity activity;
19 20
     private Stack<Screen> stack = new Stack<>();
20 21
 
21
-    public ScreenStack(Context context, ScreenParams initialScreenParams) {
22
-        super(context);
22
+    public ScreenStack(AppCompatActivity activity, ScreenParams initialScreenParams) {
23
+        super(activity);
24
+        this.activity = activity;
23 25
         setLayoutTransition(new LayoutTransition());
24 26
         pushInitialScreen(initialScreenParams);
25 27
     }
@@ -35,7 +37,7 @@ public class ScreenStack extends FrameLayout implements TitleBarBackButtonListen
35 37
     }
36 38
 
37 39
     private void addScreen(ScreenParams screenParams) {
38
-        Screen screen = ScreenFactory.create(getContext(), screenParams, this);
40
+        Screen screen = ScreenFactory.create(activity, screenParams, this);
39 41
         addView(screen, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
40 42
         stack.push(screen);
41 43
     }