ソースを参照

Bottom tabs visible (#2779)

* Rename BottomTabOptionsPresenter

* Set currentTabIndex in BottomTabsPresenter

* implement BottomTabs visible
Guy Carmeli 6 年 前
コミット
5fec0182ec
No account linked to committer's email address

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java ファイルの表示

@@ -6,7 +6,7 @@ import com.facebook.react.ReactInstanceManager;
6 6
 import com.reactnativenavigation.utils.ImageLoader;
7 7
 import com.reactnativenavigation.utils.NoOpPromise;
8 8
 import com.reactnativenavigation.utils.TypefaceLoader;
9
-import com.reactnativenavigation.viewcontrollers.BottomTabsController;
9
+import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
10 10
 import com.reactnativenavigation.viewcontrollers.ComponentViewController;
11 11
 import com.reactnativenavigation.viewcontrollers.SideMenuController;
12 12
 import com.reactnativenavigation.viewcontrollers.StackController;

lib/android/app/src/main/java/com/reactnativenavigation/presentation/BottomTabOptionsPresenter.java → lib/android/app/src/main/java/com/reactnativenavigation/presentation/BottomTabsOptionsPresenter.java ファイルの表示

@@ -1,30 +1,31 @@
1 1
 package com.reactnativenavigation.presentation;
2 2
 
3
-import android.support.annotation.IntRange;
4
-
5 3
 import com.reactnativenavigation.parse.BottomTabOptions;
6 4
 import com.reactnativenavigation.parse.BottomTabsOptions;
7 5
 import com.reactnativenavigation.parse.Options;
6
+import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabFinder;
8 7
 import com.reactnativenavigation.views.BottomTabs;
9 8
 
10
-public class BottomTabOptionsPresenter {
9
+public class BottomTabsOptionsPresenter {
11 10
     private BottomTabs bottomTabs;
11
+    private BottomTabFinder bottomTabFinder;
12 12
 
13
-    public BottomTabOptionsPresenter(BottomTabs bottomTabs) {
13
+    public BottomTabsOptionsPresenter(BottomTabs bottomTabs, BottomTabFinder bottomTabFinder) {
14 14
         this.bottomTabs = bottomTabs;
15
+        this.bottomTabFinder = bottomTabFinder;
15 16
     }
16 17
 
17 18
     public void present(Options options) {
18 19
         applyBottomTabsOptions(options.bottomTabsOptions);
19 20
     }
20 21
 
21
-    public void present(Options options, @IntRange(from = 0) int bottomTabIndex) {
22
-        applyBottomTabOptions(options.bottomTabOptions, bottomTabIndex);
22
+    public void present(Options options, int tabIndex) {
23
+        applyBottomTabOptions(options.bottomTabOptions, tabIndex);
23 24
     }
24 25
 
25
-    private void applyBottomTabOptions(BottomTabOptions options, int bottomTabIndex) {
26
+    private void applyBottomTabOptions(BottomTabOptions options, int tabIndex) {
26 27
         if (options.badge.hasValue()) {
27
-            bottomTabs.setBadge(bottomTabIndex, options.badge);
28
+            bottomTabs.setBadge(tabIndex, options.badge);
28 29
         }
29 30
     }
30 31
 
@@ -44,5 +45,15 @@ public class BottomTabOptionsPresenter {
44 45
         if (options.tabColor.hasValue()) {
45 46
             bottomTabs.setInactiveColor(options.tabColor.get());
46 47
         }
48
+        if (options.currentTabId.hasValue()) {
49
+            int tabIndex = bottomTabFinder.findByControllerId(options.currentTabId.get());
50
+            if (tabIndex >= 0) bottomTabs.setCurrentItem(tabIndex);
51
+        }
52
+        if (options.visible.isTrueOrUndefined()) {
53
+            bottomTabs.restoreBottomNavigation(options.animate.isTrueOrUndefined());
54
+        }
55
+        if (options.visible.isFalse()) {
56
+            bottomTabs.hideBottomNavigation(options.animate.isTrueOrUndefined());
57
+        }
47 58
     }
48 59
 }

+ 36
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabFinder.java ファイルの表示

@@ -0,0 +1,36 @@
1
+package com.reactnativenavigation.viewcontrollers.bottomtabs;
2
+
3
+import android.support.annotation.IntRange;
4
+
5
+import com.reactnativenavigation.viewcontrollers.ViewController;
6
+import com.reactnativenavigation.views.ReactComponent;
7
+
8
+import java.util.List;
9
+
10
+public class BottomTabFinder {
11
+    private List<ViewController> tabs;
12
+
13
+    @IntRange(from = -1)
14
+    public int findByComponent(ReactComponent component) {
15
+        for (int i = 0; i < tabs.size(); i++) {
16
+            if (tabs.get(i).containsComponent(component)) {
17
+                return i;
18
+            }
19
+        }
20
+        return -1;
21
+    }
22
+
23
+    @IntRange(from = -1)
24
+    public int findByControllerId(String id) {
25
+        for (int i = 0; i < tabs.size(); i++) {
26
+            if (tabs.get(i).findControllerById(id) != null) {
27
+                return i;
28
+            }
29
+        }
30
+        return -1;
31
+    }
32
+
33
+    void setTabs(List<ViewController> tabs) {
34
+        this.tabs = tabs;
35
+    }
36
+}

lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/BottomTabsController.java → lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/bottomtabs/BottomTabsController.java ファイルの表示

@@ -1,8 +1,7 @@
1
-package com.reactnativenavigation.viewcontrollers;
1
+package com.reactnativenavigation.viewcontrollers.bottomtabs;
2 2
 
3 3
 import android.app.Activity;
4 4
 import android.graphics.drawable.Drawable;
5
-import android.support.annotation.IntRange;
6 5
 import android.support.annotation.NonNull;
7 6
 import android.view.ViewGroup;
8 7
 import android.widget.RelativeLayout;
@@ -11,10 +10,11 @@ import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
11 10
 import com.aurelhubert.ahbottomnavigation.AHBottomNavigationItem;
12 11
 import com.reactnativenavigation.parse.BottomTabOptions;
13 12
 import com.reactnativenavigation.parse.Options;
14
-import com.reactnativenavigation.parse.params.Text;
15
-import com.reactnativenavigation.presentation.BottomTabOptionsPresenter;
13
+import com.reactnativenavigation.presentation.BottomTabsOptionsPresenter;
16 14
 import com.reactnativenavigation.presentation.NavigationOptionsListener;
17 15
 import com.reactnativenavigation.utils.ImageLoader;
16
+import com.reactnativenavigation.viewcontrollers.ParentController;
17
+import com.reactnativenavigation.viewcontrollers.ViewController;
18 18
 import com.reactnativenavigation.views.BottomTabs;
19 19
 import com.reactnativenavigation.views.ReactComponent;
20 20
 
@@ -31,6 +31,7 @@ public class BottomTabsController extends ParentController implements AHBottomNa
31 31
 	private BottomTabs bottomTabs;
32 32
 	private List<ViewController> tabs = new ArrayList<>();
33 33
     private ImageLoader imageLoader;
34
+    private BottomTabFinder bottomTabFinder = new BottomTabFinder();
34 35
 
35 36
     public BottomTabsController(final Activity activity, ImageLoader imageLoader, final String id, Options initialOptions) {
36 37
 		super(activity, id, initialOptions);
@@ -52,14 +53,14 @@ public class BottomTabsController extends ParentController implements AHBottomNa
52 53
     @Override
53 54
     public void applyOptions(Options options) {
54 55
         super.applyOptions(options);
55
-        new BottomTabOptionsPresenter(bottomTabs).present(options);
56
+        new BottomTabsOptionsPresenter(bottomTabs, bottomTabFinder).present(options);
56 57
     }
57 58
 
58 59
     @Override
59 60
     public void applyOptions(Options options, ReactComponent childComponent) {
60 61
         super.applyOptions(options, childComponent);
61
-        int tabIndex = findTabContainingComponent(childComponent);
62
-        if (tabIndex >= 0) new BottomTabOptionsPresenter(bottomTabs).present(options, tabIndex);
62
+        int tabIndex = bottomTabFinder.findByComponent(childComponent);
63
+        if (tabIndex >= 0) new BottomTabsOptionsPresenter(bottomTabs, bottomTabFinder).present(this.options, tabIndex);
63 64
         applyOnParentController(parentController ->
64 65
                 ((ParentController) parentController).applyOptions(this.options.copy().clearBottomTabsOptions().clearBottomTabOptions(), childComponent)
65 66
         );
@@ -91,7 +92,8 @@ public class BottomTabsController extends ParentController implements AHBottomNa
91 92
 			throw new RuntimeException("Too many tabs!");
92 93
 		}
93 94
 		this.tabs = tabs;
94
-		getView();
95
+        bottomTabFinder.setTabs(tabs);
96
+        getView();
95 97
 		for (int i = 0; i < tabs.size(); i++) {
96 98
 		    tabs.get(i).setParentController(this);
97 99
 			createTab(i, tabs.get(i).options.bottomTabOptions);
@@ -121,7 +123,7 @@ public class BottomTabsController extends ParentController implements AHBottomNa
121 123
         params.addRule(ABOVE, bottomTabs.getId());
122 124
 	}
123 125
 
124
-    int getSelectedIndex() {
126
+    public int getSelectedIndex() {
125 127
 		return bottomTabs.getCurrentItem();
126 128
 	}
127 129
 
@@ -134,25 +136,10 @@ public class BottomTabsController extends ParentController implements AHBottomNa
134 136
 	@Override
135 137
 	public void mergeOptions(Options options) {
136 138
         this.options = this.options.mergeWith(options);
137
-        if (options.bottomTabsOptions.currentTabIndex.hasValue()) {
138
-            selectTabAtIndex(options.bottomTabsOptions.currentTabIndex.get());
139
-        }
140
-        if (options.bottomTabsOptions.currentTabId.hasValue()) {
141
-            Text id = options.bottomTabsOptions.currentTabId;
142
-            for (ViewController controller : tabs) {
143
-                if (controller.getId().equals(id.get())) {
144
-                    selectTabAtIndex(tabs.indexOf(controller));
145
-                }
146
-                if (controller instanceof StackController) {
147
-                    if (hasControlWithId((StackController) controller, id.get())) {
148
-                        selectTabAtIndex(tabs.indexOf(controller));
149
-                    }
150
-                }
151
-            }
152
-        }
139
+        new BottomTabsOptionsPresenter(bottomTabs, bottomTabFinder).present(this.options);
153 140
     }
154 141
 
155
-    void selectTabAtIndex(final int newIndex) {
142
+    public void selectTabAtIndex(final int newIndex) {
156 143
         getView().removeView(getCurrentView());
157 144
         bottomTabs.setCurrentItem(newIndex, false);
158 145
         getView().addView(getCurrentView());
@@ -162,26 +149,4 @@ public class BottomTabsController extends ParentController implements AHBottomNa
162 149
     private ViewGroup getCurrentView() {
163 150
         return tabs.get(bottomTabs.getCurrentItem()).getView();
164 151
     }
165
-
166
-    private boolean hasControlWithId(StackController controller, String id) {
167
-		for (ViewController child : controller.getChildControllers()) {
168
-			if (id.equals(child.getId())) {
169
-				return true;
170
-			}
171
-			if (child instanceof StackController) {
172
-				return hasControlWithId((StackController) child, id);
173
-			}
174
-		}
175
-		return false;
176
-	}
177
-
178
-	@IntRange(from = -1)
179
-    private int findTabContainingComponent(ReactComponent component) {
180
-        for (int i = 0; i < tabs.size(); i++) {
181
-            if (tabs.get(i).containsComponent(component)) {
182
-                return i;
183
-            }
184
-        }
185
-        return -1;
186
-    }
187 152
 }

+ 6
- 0
lib/android/app/src/main/java/com/reactnativenavigation/views/BottomTabs.java ファイルの表示

@@ -2,6 +2,7 @@ package com.reactnativenavigation.views;
2 2
 
3 3
 import android.annotation.SuppressLint;
4 4
 import android.content.Context;
5
+import android.support.annotation.IntRange;
5 6
 
6 7
 import com.aurelhubert.ahbottomnavigation.AHBottomNavigation;
7 8
 import com.reactnativenavigation.parse.params.Text;
@@ -24,4 +25,9 @@ public class BottomTabs extends AHBottomNavigation {
24 25
     public void setBadge(int bottomTabIndex, Text badge) {
25 26
         setNotification(badge.get(), bottomTabIndex);
26 27
     }
28
+
29
+    @Override
30
+    public void setCurrentItem(@IntRange(from = 0) int position) {
31
+        super.setCurrentItem(position);
32
+    }
27 33
 }

+ 15
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/BottomTabsControllerTest.java ファイルの表示

@@ -10,8 +10,10 @@ import com.reactnativenavigation.mocks.MockPromise;
10 10
 import com.reactnativenavigation.mocks.SimpleViewController;
11 11
 import com.reactnativenavigation.parse.params.Color;
12 12
 import com.reactnativenavigation.parse.Options;
13
+import com.reactnativenavigation.parse.params.Number;
13 14
 import com.reactnativenavigation.utils.ImageLoader;
14 15
 import com.reactnativenavigation.utils.OptionHelper;
16
+import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
15 17
 import com.reactnativenavigation.views.BottomTabs;
16 18
 import com.reactnativenavigation.views.ReactComponent;
17 19
 
@@ -44,7 +46,7 @@ public class BottomTabsControllerTest extends BaseTest {
44 46
     public void beforeEach() {
45 47
         super.beforeEach();
46 48
         activity = newActivity();
47
-        uut = new BottomTabsController(activity, imageLoaderMock, "uut", new Options());
49
+        uut = spy(new BottomTabsController(activity, imageLoaderMock, "uut", new Options()));
48 50
         child1 = spy(new SimpleViewController(activity, "child1", tabOptions));
49 51
         child2 = spy(new SimpleViewController(activity, "child2", tabOptions));
50 52
         child3 = spy(new SimpleViewController(activity, "child3", tabOptions));
@@ -140,6 +142,18 @@ public class BottomTabsControllerTest extends BaseTest {
140 142
         assertThat(optionsCaptor.getValue().bottomTabsOptions.tabColor.hasValue()).isFalse();
141 143
     }
142 144
 
145
+    @Test
146
+    public void mergeOptions_currentTabIndex() throws Exception {
147
+        List<ViewController> tabs = createTabs();
148
+        uut.setTabs(tabs);
149
+        uut.ensureViewIsCreated();
150
+
151
+        Options options = new Options();
152
+        options.bottomTabsOptions.currentTabIndex = new Number(1);
153
+        uut.mergeOptions(options);
154
+        verify(uut, times(1)).selectTabAtIndex(1);
155
+    }
156
+
143 157
     @Test
144 158
     public void buttonPressInvokedOnCurrentTab() throws Exception {
145 159
         uut.setTabs(createTabs());

+ 1
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/NavigatorTest.java ファイルの表示

@@ -13,6 +13,7 @@ import com.reactnativenavigation.parse.params.Text;
13 13
 import com.reactnativenavigation.utils.CompatUtils;
14 14
 import com.reactnativenavigation.utils.ImageLoader;
15 15
 import com.reactnativenavigation.utils.OptionHelper;
16
+import com.reactnativenavigation.viewcontrollers.bottomtabs.BottomTabsController;
16 17
 
17 18
 import org.junit.Test;
18 19