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

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

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

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

1
 package com.reactnativenavigation.layouts;
1
 package com.reactnativenavigation.layouts;
2
 
2
 
3
-import android.app.Activity;
3
+import android.support.v7.app.AppCompatActivity;
4
 
4
 
5
 import com.reactnativenavigation.params.ActivityParams;
5
 import com.reactnativenavigation.params.ActivityParams;
6
 
6
 
7
 public class LayoutFactory {
7
 public class LayoutFactory {
8
-    public static Layout create(Activity activity, ActivityParams params) {
8
+    public static Layout create(AppCompatActivity activity, ActivityParams params) {
9
         switch (params.type) {
9
         switch (params.type) {
10
             case TabBased:
10
             case TabBased:
11
                 return createBottomTabsScreenLayout(activity, params);
11
                 return createBottomTabsScreenLayout(activity, params);
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
         return new SingleScreenLayout(activity, params.screenParams);
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
 package com.reactnativenavigation.layouts;
1
 package com.reactnativenavigation.layouts;
2
 
2
 
3
-import android.app.Activity;
3
+import android.support.v7.app.AppCompatActivity;
4
 import android.view.View;
4
 import android.view.View;
5
 import android.widget.FrameLayout;
5
 import android.widget.FrameLayout;
6
 
6
 
15
 
15
 
16
 public class SingleScreenLayout extends FrameLayout implements Layout {
16
 public class SingleScreenLayout extends FrameLayout implements Layout {
17
 
17
 
18
+    private final AppCompatActivity activity;
18
     private final ScreenParams screenParams;
19
     private final ScreenParams screenParams;
19
     private ScreenStack stack;
20
     private ScreenStack stack;
20
 
21
 
21
-    public SingleScreenLayout(Activity activity, ScreenParams screenParams) {
22
+    public SingleScreenLayout(AppCompatActivity activity, ScreenParams screenParams) {
22
         super(activity);
23
         super(activity);
24
+        this.activity = activity;
23
         this.screenParams = screenParams;
25
         this.screenParams = screenParams;
24
         createStack();
26
         createStack();
25
     }
27
     }
29
             stack.destroy();
31
             stack.destroy();
30
             removeView(stack);
32
             removeView(stack);
31
         }
33
         }
32
-        stack = new ScreenStack(getContext(), screenParams);
34
+        stack = new ScreenStack(activity, screenParams);
33
         addView(stack, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
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
     public String title;
13
     public String title;
14
     public ScreenStyleParams styleParams;
14
     public ScreenStyleParams styleParams;
15
     public List<TopTabParams> topTabParams;
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
     public String tabLabel;
20
     public String tabLabel;
17
     public Drawable tabIcon;
21
     public Drawable tabIcon;
18
 
22
 
24
     public boolean hasTopTabs() {
28
     public boolean hasTopTabs() {
25
         return topTabParams != null && !topTabParams.isEmpty();
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
     private static final String KEY_RIGHT_BUTTONS = "rightButtons";
18
     private static final String KEY_RIGHT_BUTTONS = "rightButtons";
19
     private static final String KEY_LEFT_BUTTON = "leftButton";
19
     private static final String KEY_LEFT_BUTTON = "leftButton";
20
     private static final String STYLE_PARAMS = "styleParams";
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
     @SuppressWarnings("ConstantConditions")
24
     @SuppressWarnings("ConstantConditions")
24
     public static ScreenParams parse(Bundle params) {
25
     public static ScreenParams parse(Bundle params) {
41
         if (hasKey(params, TOP_TABS)) {
42
         if (hasKey(params, TOP_TABS)) {
42
             result.topTabParams = TopTabParamsParser.parse(params.getBundle(TOP_TABS));
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
         if (hasKey(params, "label")) {
48
         if (hasKey(params, "label")) {
45
             result.tabLabel = params.getString("label");
49
             result.tabLabel = params.getString("label");
46
         }
50
         }

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

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
 public abstract class Screen extends RelativeLayout implements ScrollDirectionListener.OnScrollChanged {
28
 public abstract class Screen extends RelativeLayout implements ScrollDirectionListener.OnScrollChanged {
29
 
29
 
30
     protected final ScreenParams screenParams;
30
     protected final ScreenParams screenParams;
31
-    private final TitleBarBackButtonListener titleBarBackButtonListener;
32
     protected TopBar topBar;
31
     protected TopBar topBar;
32
+    private final TitleBarBackButtonListener titleBarBackButtonListener;
33
     private VisibilityAnimator topBarVisibilityAnimator;
33
     private VisibilityAnimator topBarVisibilityAnimator;
34
 
34
 
35
     public Screen(Context context, ScreenParams screenParams, TitleBarBackButtonListener titleBarBackButtonListener) {
35
     public Screen(Context context, ScreenParams screenParams, TitleBarBackButtonListener titleBarBackButtonListener) {

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

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