Parcourir la source

Additional work on BottomTabs

Guy Carmeli il y a 8 ans
Parent
révision
80b11fb522

+ 42
- 31
android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java Voir le fichier

@@ -6,7 +6,6 @@ import android.view.View;
6 6
 import android.widget.RelativeLayout;
7 7
 
8 8
 import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
9
-import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
10 9
 import com.reactnativenavigation.params.ActivityParams;
11 10
 import com.reactnativenavigation.params.ScreenParams;
12 11
 import com.reactnativenavigation.params.TitleBarButtonParams;
@@ -25,14 +24,14 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
25 24
     private final AppCompatActivity activity;
26 25
     private ActivityParams params;
27 26
     private BottomTabs bottomTabs;
28
-    private ArrayList<ScreenStack> screenStacks;
27
+    private ScreenStack[] screenStacks;
29 28
     private int currentStackIndex = 0;
30 29
 
31 30
     public BottomTabsLayout(AppCompatActivity activity, ActivityParams params) {
32 31
         super(activity);
33 32
         this.activity = activity;
34 33
         this.params = params;
35
-        screenStacks = new ArrayList<>();
34
+        screenStacks = new ScreenStack[(params.tabParams.size())];
36 35
         createLayout();
37 36
     }
38 37
 
@@ -45,7 +44,7 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
45 44
     private void createBottomTabs() {
46 45
         bottomTabs = new BottomTabs(getContext());
47 46
         setBottomTabsStyle();
48
-        addTabs();
47
+        bottomTabs.addTabs(params.tabParams, this);
49 48
     }
50 49
 
51 50
     private void addBottomTabsToScreen() {
@@ -55,7 +54,7 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
55 54
     }
56 55
 
57 56
     private void addInitialScreen() {
58
-        addView(getFirstScreenStack());
57
+        createAndAddScreenStack(0);
59 58
     }
60 59
 
61 60
     private void setBottomTabsStyle() {
@@ -66,18 +65,6 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
66 65
 //        bottomTabs.setAccentColor(getColor(style, TAB_STYLE_SELECTED_COLOR, DEFAULT_TAB_SELECTED_COLOR));
67 66
     }
68 67
 
69
-    private void addTabs() {
70
-        for (ScreenParams screenParams : params.tabParams) {
71
-            ScreenStack stack = new ScreenStack(activity, screenParams);
72
-            screenStacks.add(stack);
73
-
74
-            AHBottomNavigationItem item = new AHBottomNavigationItem(screenParams.title, screenParams.tabIcon,
75
-                    Color.GRAY);
76
-            bottomTabs.addItem(item);
77
-            bottomTabs.setOnTabSelectedListener(this);
78
-        }
79
-    }
80
-
81 68
     @Override
82 69
     public View asView() {
83 70
         return this;
@@ -85,34 +72,39 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
85 72
 
86 73
     @Override
87 74
     public boolean onBackPressed() {
88
-        return false;
75
+        if (getCurrentScreenStack().canPop()) {
76
+            getCurrentScreenStack().pop();
77
+            return true;
78
+        } else {
79
+            return false;
80
+        }
89 81
     }
90 82
 
91 83
     @Override
92 84
     public void setTopBarVisible(String screenInstanceId, boolean hidden, boolean animated) {
93 85
         for (int i = 0; i < bottomTabs.getItemsCount(); i++) {
94
-            screenStacks.get(i).setTopBarVisible(screenInstanceId, hidden, animated);
86
+            screenStacks[i].setTopBarVisible(screenInstanceId, hidden, animated);
95 87
         }
96 88
     }
97 89
 
98 90
     @Override
99 91
     public void setTitleBarTitle(String screenInstanceId, String title) {
100 92
         for (int i = 0; i < bottomTabs.getItemsCount(); i++) {
101
-            screenStacks.get(i).setTitleBarTitle(screenInstanceId, title);
93
+            screenStacks[i].setTitleBarTitle(screenInstanceId, title);
102 94
         }
103 95
     }
104 96
 
105 97
     @Override
106 98
     public void setTitleBarRightButtons(String screenInstanceId, String navigatorEventId, List<TitleBarButtonParams> titleBarButtons) {
107 99
         for (int i = 0; i < bottomTabs.getItemsCount(); i++) {
108
-            screenStacks.get(i).setTitleBarRightButtons(screenInstanceId, navigatorEventId, titleBarButtons);
100
+            screenStacks[i].setTitleBarRightButtons(screenInstanceId, navigatorEventId, titleBarButtons);
109 101
         }
110 102
     }
111 103
 
112 104
     @Override
113 105
     public void setTitleBarLeftButton(String screenInstanceId, String navigatorEventId, TitleBarLeftButtonParams titleBarLeftButtonParams) {
114 106
         for (int i = 0; i < bottomTabs.getItemsCount(); i++) {
115
-            screenStacks.get(i).setTitleBarLeftButton(screenInstanceId, navigatorEventId, titleBarLeftButtonParams);
107
+            screenStacks[i].setTitleBarLeftButton(screenInstanceId, navigatorEventId, titleBarLeftButtonParams);
116 108
         }
117 109
     }
118 110
 
@@ -137,28 +129,47 @@ public class BottomTabsLayout extends RelativeLayout implements Layout, AHBottom
137 129
         currentScreenStack.destroy();
138 130
         removeView(currentScreenStack);
139 131
 
140
-        ScreenStack newStack = new ScreenStack(activity, params);
141
-        screenStacks.set(currentStackIndex, newStack);
132
+        ScreenStack newStack = new ScreenStack(getContext(), params);
133
+        screenStacks[currentStackIndex] = newStack;
142 134
         addView(newStack, 0, new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
143 135
     }
144 136
 
145 137
     @Override
146 138
     public void destroy() {
147
-
139
+        for (ScreenStack screenStack : screenStacks) {
140
+            screenStack.destroy();
141
+            removeView(screenStack);
142
+        }
143
+        screenStacks = null;
148 144
     }
149 145
 
150 146
     @Override
151 147
     public void onTabSelected(int position, boolean wasSelected) {
152
-        removeView(getCurrentScreenStack());
153
-        addView(screenStacks.get(position), 0, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
148
+        removeCurrentStack();
149
+
150
+        ScreenStack newStack = screenStacks[position];
151
+        if (newStack == null) {
152
+            createAndAddScreenStack(position);
153
+        } else {
154
+            addView(newStack, 0, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
155
+            newStack.preventMountAfterReatachedToWindow();
156
+        }
154 157
         currentStackIndex = position;
155 158
     }
156 159
 
157
-    private ScreenStack getCurrentScreenStack() {
158
-        return screenStacks.get(currentStackIndex);
160
+    private void createAndAddScreenStack(int position) {
161
+        ScreenStack newStack = new ScreenStack(getContext(), params.tabParams.get(position));
162
+        screenStacks[position] = newStack;
163
+        addView(newStack, 0, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
159 164
     }
160 165
 
161
-    private ScreenStack getFirstScreenStack() {
162
-        return screenStacks.get(0);
166
+    private void removeCurrentStack() {
167
+        ScreenStack currentScreenStack = getCurrentScreenStack();
168
+        currentScreenStack.preventUnmountOnDetachedFromWindow();
169
+        removeView(currentScreenStack);
170
+    }
171
+
172
+    private ScreenStack getCurrentScreenStack() {
173
+        return screenStacks[currentStackIndex];
163 174
     }
164 175
 }

+ 8
- 2
android/app/src/main/java/com/reactnativenavigation/react/ReactViewHacks.java Voir le fichier

@@ -10,11 +10,17 @@ public class ReactViewHacks {
10 10
     }
11 11
 
12 12
     /**
13
-     * Must be called before view is removed from screen inorder to ensure onDetachedFromScreen is properly
14
-     * executed and componentWillUnmount is called
13
+     * Side effect: prevents JS components constructor from being called
15 14
      */
16 15
     public static void ensureUnmountOnDetachedFromWindow(ReactRootView view) {
17 16
         ReflectionUtils.setField(view, "mAttachScheduled", false);
18 17
     }
19 18
 
19
+    /**
20
+     * Side effect: ensures unmount will be called
21
+     */
22
+    public static void preventMountAfterReattachedToWindow(ReactRootView view) {
23
+        ReflectionUtils.setField(view, "mAttachScheduled", false);
24
+    }
25
+
20 26
 }

+ 2
- 0
android/app/src/main/java/com/reactnativenavigation/screens/Screen.java Voir le fichier

@@ -131,6 +131,8 @@ public abstract class Screen extends RelativeLayout implements ScrollDirectionLi
131 131
 
132 132
     public abstract void preventUnmountOnDetachedFromWindow();
133 133
 
134
+    public abstract void preventMountAfterReattachedToWindow();
135
+
134 136
     public String getScreenInstanceId() {
135 137
         return screenParams.screenInstanceId;
136 138
     }

+ 18
- 0
android/app/src/main/java/com/reactnativenavigation/screens/ScreenStack.java Voir le fichier

@@ -135,4 +135,22 @@ public class ScreenStack extends FrameLayout implements TitleBarBackButtonListen
135 135
             pop();
136 136
         }
137 137
     }
138
+
139
+    public void preventUnmountOnDetachedFromWindow() {
140
+        for (Screen screen : stack) {
141
+            screen.preventUnmountOnDetachedFromWindow();
142
+        }
143
+    }
144
+
145
+    public void ensureUnmountOnDetachedFromWindow() {
146
+        for (Screen screen : stack) {
147
+            screen.ensureUnmountOnDetachedFromWindow();
148
+        }
149
+    }
150
+
151
+    public void preventMountAfterReatachedToWindow() {
152
+        for (Screen screen : stack) {
153
+            screen.preventMountAfterReattachedToWindow();
154
+        }
155
+    }
138 156
 }

+ 5
- 0
android/app/src/main/java/com/reactnativenavigation/screens/SingleScreen.java Voir le fichier

@@ -43,4 +43,9 @@ public class SingleScreen extends Screen {
43 43
     public void preventUnmountOnDetachedFromWindow() {
44 44
         contentView.preventUnmountOnDetachedFromWindow();
45 45
     }
46
+
47
+    @Override
48
+    public void preventMountAfterReattachedToWindow() {
49
+        contentView.preventMountAfterReattachedToWindow();
50
+    }
46 51
 }

+ 6
- 0
android/app/src/main/java/com/reactnativenavigation/screens/TabbedScreen.java Voir le fichier

@@ -75,6 +75,12 @@ public class TabbedScreen extends Screen {
75 75
         }
76 76
     }
77 77
 
78
+    @Override
79
+    public void preventMountAfterReattachedToWindow() {
80
+        for (ContentView contentView : contentViews) {
81
+            contentView.preventMountAfterReattachedToWindow();
82
+        }
83
+    }
78 84
 
79 85
     public class ContentViewPagerAdapter extends PagerAdapter implements TabLayout.OnTabSelectedListener, ViewPager.OnPageChangeListener {
80 86
 

+ 14
- 0
android/app/src/main/java/com/reactnativenavigation/views/BottomTabs.java Voir le fichier

@@ -1,11 +1,25 @@
1 1
 package com.reactnativenavigation.views;
2 2
 
3 3
 import android.content.Context;
4
+import android.graphics.Color;
4 5
 
5 6
 import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
7
+import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
8
+import com.reactnativenavigation.params.ScreenParams;
9
+
10
+import java.util.List;
6 11
 
7 12
 public class BottomTabs extends AHBottomNavigation {
8 13
     public BottomTabs(Context context) {
9 14
         super(context);
10 15
     }
16
+
17
+    public void addTabs(List<ScreenParams> params, OnTabSelectedListener onTabSelectedListener) {
18
+        for (ScreenParams screenParams : params) {
19
+            AHBottomNavigationItem item = new AHBottomNavigationItem(screenParams.title, screenParams.tabIcon,
20
+                    Color.GRAY);
21
+            addItem(item);
22
+            setOnTabSelectedListener(onTabSelectedListener);
23
+        }
24
+    }
11 25
 }

+ 4
- 0
android/app/src/main/java/com/reactnativenavigation/views/ContentView.java Voir le fichier

@@ -49,4 +49,8 @@ public class ContentView extends ReactRootView {
49 49
     public void ensureUnmountOnDetachedFromWindow() {
50 50
         ReactViewHacks.ensureUnmountOnDetachedFromWindow(this);
51 51
     }
52
+
53
+    public void preventMountAfterReattachedToWindow() {
54
+        ReactViewHacks.preventMountAfterReattachedToWindow(this);
55
+    }
52 56
 }