Browse Source

Android: Set bottom tabs layout over tabs content

Amit Davidi 7 years ago
parent
commit
d1e31ee437

+ 7
- 7
android/app/deprecated/java/com/reactnativenavigation/utils/ViewUtils.java View File

57
         return pixels * scaledDensity;
57
         return pixels * scaledDensity;
58
     }
58
     }
59
 
59
 
60
+    public static float getScreenHeight() {
61
+        WindowManager wm = (WindowManager) NavigationApplication.instance.getSystemService(Context.WINDOW_SERVICE);
62
+        DisplayMetrics metrics = new DisplayMetrics();
63
+        wm.getDefaultDisplay().getMetrics(metrics);
64
+        return metrics.heightPixels;
65
+    }
66
+
60
     public static int generateViewId() {
67
     public static int generateViewId() {
61
         if (Build.VERSION.SDK_INT >= 17) {
68
         if (Build.VERSION.SDK_INT >= 17) {
62
             return View.generateViewId();
69
             return View.generateViewId();
65
         }
72
         }
66
     }
73
     }
67
 
74
 
68
-    public static float getScreenHeight() {
69
-        WindowManager wm = (WindowManager) NavigationApplication.instance.getSystemService(Context.WINDOW_SERVICE);
70
-        DisplayMetrics metrics = new DisplayMetrics();
71
-        wm.getDefaultDisplay().getMetrics(metrics);
72
-        return metrics.heightPixels;
73
-    }
74
-
75
     private static int compatGenerateViewId() {
75
     private static int compatGenerateViewId() {
76
         for (; ; ) {
76
         for (; ; ) {
77
             final int result = viewId.get();
77
             final int result = viewId.get();

+ 39
- 3
android/app/src/main/java/com/reactnativenavigation/layout/bottomtabs/BottomTabs.java View File

1
 package com.reactnativenavigation.layout.bottomtabs;
1
 package com.reactnativenavigation.layout.bottomtabs;
2
 
2
 
3
+import android.graphics.Color;
4
+import android.os.Build;
3
 import android.support.design.widget.BottomNavigationView;
5
 import android.support.design.widget.BottomNavigationView;
6
+import android.view.View;
7
+import android.view.ViewGroup;
4
 import android.widget.RelativeLayout;
8
 import android.widget.RelativeLayout;
9
+import android.widget.RelativeLayout.LayoutParams;
10
+
11
+import java.util.concurrent.atomic.AtomicInteger;
5
 
12
 
6
 import static android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM;
13
 import static android.widget.RelativeLayout.ALIGN_PARENT_BOTTOM;
7
 
14
 
8
 public class BottomTabs {
15
 public class BottomTabs {
9
 
16
 
17
+    private static final AtomicInteger viewId = new AtomicInteger(1);
18
+
10
     private BottomNavigationView bottomNavigationView;
19
     private BottomNavigationView bottomNavigationView;
11
 
20
 
12
     public void attach(RelativeLayout parentLayout) {
21
     public void attach(RelativeLayout parentLayout) {
13
         bottomNavigationView = new BottomNavigationView(parentLayout.getContext());
22
         bottomNavigationView = new BottomNavigationView(parentLayout.getContext());
23
+        bottomNavigationView.setId(generateViewId());
24
+        bottomNavigationView.setBackgroundColor(Color.DKGRAY);
14
 
25
 
15
-        RelativeLayout.LayoutParams lp =
16
-                new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
26
+        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
17
         lp.addRule(ALIGN_PARENT_BOTTOM);
27
         lp.addRule(ALIGN_PARENT_BOTTOM);
18
         bottomNavigationView.setLayoutParams(lp);
28
         bottomNavigationView.setLayoutParams(lp);
19
         parentLayout.addView(bottomNavigationView, lp);
29
         parentLayout.addView(bottomNavigationView, lp);
20
     }
30
     }
21
 
31
 
22
-    public void addTab(String label) {
32
+    public void addTab(String label, View tabContent) {
23
         bottomNavigationView.getMenu().add(label);
33
         bottomNavigationView.getMenu().add(label);
34
+
35
+        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
36
+        params.addRule(RelativeLayout.ABOVE, bottomNavigationView.getId());
37
+
38
+        ViewGroup parent = (ViewGroup) bottomNavigationView.getParent();
39
+        parent.addView(tabContent, params);
40
+    }
41
+
42
+    private int generateViewId() {
43
+        if (Build.VERSION.SDK_INT >= 17) {
44
+            return View.generateViewId();
45
+        } else {
46
+            return compatGenerateViewId();
47
+        }
48
+    }
49
+
50
+    private int compatGenerateViewId() {
51
+        while(true) {
52
+            final int result = viewId.get();
53
+            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
54
+            int newValue = result + 1;
55
+            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
56
+            if (viewId.compareAndSet(result, newValue)) {
57
+                return result;
58
+            }
59
+        }
24
     }
60
     }
25
 }
61
 }

+ 2
- 5
android/app/src/main/java/com/reactnativenavigation/layout/bottomtabs/BottomTabsContainer.java View File

13
         createBottomTabs(bottomTabsCreator);
13
         createBottomTabs(bottomTabsCreator);
14
     }
14
     }
15
 
15
 
16
-    public void setTabContent(View tab) {
17
-        bottomTabs.addTab("#0");
18
-
19
-        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
20
-        addView(tab, lp);
16
+    public void setTabContent(View tabContent) {
17
+        bottomTabs.addTab("#0", tabContent);
21
     }
18
     }
22
 
19
 
23
     private void createBottomTabs(BottomTabsCreator bottomTabsCreator) {
20
     private void createBottomTabs(BottomTabsCreator bottomTabsCreator) {

+ 21
- 12
android/app/src/test/java/com/reactnativenavigation/LayoutFactoryTest.java View File

5
 import android.view.View;
5
 import android.view.View;
6
 import android.view.ViewGroup;
6
 import android.view.ViewGroup;
7
 
7
 
8
-import com.reactnativenavigation.layout.bottomtabs.BottomTabs;
9
-import com.reactnativenavigation.layout.bottomtabs.BottomTabsContainer;
10
 import com.reactnativenavigation.layout.Container;
8
 import com.reactnativenavigation.layout.Container;
11
 import com.reactnativenavigation.layout.ContainerStack;
9
 import com.reactnativenavigation.layout.ContainerStack;
12
 import com.reactnativenavigation.layout.LayoutFactory;
10
 import com.reactnativenavigation.layout.LayoutFactory;
13
 import com.reactnativenavigation.layout.LayoutNode;
11
 import com.reactnativenavigation.layout.LayoutNode;
12
+import com.reactnativenavigation.layout.bottomtabs.BottomTabs;
13
+import com.reactnativenavigation.layout.bottomtabs.BottomTabsContainer;
14
 import com.reactnativenavigation.layout.bottomtabs.BottomTabsCreator;
14
 import com.reactnativenavigation.layout.bottomtabs.BottomTabsCreator;
15
 
15
 
16
 import org.junit.Before;
16
 import org.junit.Before;
26
 import java.util.List;
26
 import java.util.List;
27
 
27
 
28
 import static org.assertj.core.api.Java6Assertions.assertThat;
28
 import static org.assertj.core.api.Java6Assertions.assertThat;
29
+import static org.mockito.ArgumentMatchers.any;
30
+import static org.mockito.ArgumentMatchers.anyString;
29
 import static org.mockito.ArgumentMatchers.eq;
31
 import static org.mockito.ArgumentMatchers.eq;
30
 import static org.mockito.Mockito.mock;
32
 import static org.mockito.Mockito.mock;
33
+import static org.mockito.Mockito.verify;
31
 import static org.mockito.Mockito.when;
34
 import static org.mockito.Mockito.when;
32
 
35
 
33
 @RunWith(RobolectricTestRunner.class)
36
 @RunWith(RobolectricTestRunner.class)
62
     }
65
     }
63
 
66
 
64
     @Test
67
     @Test
65
-    public void returnsContainerStack() throws Exception  {
68
+    public void returnsContainerStack() throws Exception {
66
         when(rootViewCreator.createRootView(eq(VIEW_ID), eq(VIEW_NAME))).thenReturn(mockView);
69
         when(rootViewCreator.createRootView(eq(VIEW_ID), eq(VIEW_NAME))).thenReturn(mockView);
67
         final LayoutNode containerNode = createContainerNode();
70
         final LayoutNode containerNode = createContainerNode();
68
         final LayoutNode stackNode = getContainerStackNode(containerNode);
71
         final LayoutNode stackNode = getContainerStackNode(containerNode);
75
     }
78
     }
76
 
79
 
77
     @Test
80
     @Test
78
-    public void returnsContainerStackWithMultipleViews() throws Exception  {
81
+    public void returnsContainerStackWithMultipleViews() throws Exception {
79
         final View mockView1 = mock(View.class);
82
         final View mockView1 = mock(View.class);
80
         final View mockView2 = mock(View.class);
83
         final View mockView2 = mock(View.class);
81
         when(rootViewCreator.createRootView(eq(VIEW_ID), eq(VIEW_NAME))).thenReturn(mockView1);
84
         when(rootViewCreator.createRootView(eq(VIEW_ID), eq(VIEW_NAME))).thenReturn(mockView1);
97
 
100
 
98
     @Test
101
     @Test
99
     public void returnsSingleTabContent() throws Exception {
102
     public void returnsSingleTabContent() throws Exception {
103
+        BottomTabs bottomTabsMock = mock(BottomTabs.class);
100
         when(rootViewCreator.createRootView(eq(VIEW_ID), eq(VIEW_NAME))).thenReturn(mockView);
104
         when(rootViewCreator.createRootView(eq(VIEW_ID), eq(VIEW_NAME))).thenReturn(mockView);
101
         final LayoutNode containerNode = createContainerNode();
105
         final LayoutNode containerNode = createContainerNode();
102
         final LayoutNode tabNode = createTabNode(containerNode);
106
         final LayoutNode tabNode = createTabNode(containerNode);
103
 
107
 
104
-        final View result = createLayoutFactory().create(tabNode);
108
+        final View result = createLayoutFactory(bottomTabsMock).create(tabNode);
105
 
109
 
106
         assertThat(result).isInstanceOf(BottomTabsContainer.class);
110
         assertThat(result).isInstanceOf(BottomTabsContainer.class);
107
-        View containerView = assertViewChildrenCount((BottomTabsContainer) result, 1).get(0);
108
-        assertThat(containerView).isInstanceOf(Container.class);
109
-        assertViewChildren((Container) containerView, mockView);
111
+        verify(bottomTabsMock).addTab(eq("#0"), any(Container.class));
110
     }
112
     }
111
 
113
 
112
     @Test(expected = IllegalArgumentException.class)
114
     @Test(expected = IllegalArgumentException.class)
113
-    public void throwsExceptionForUnknownType() throws Exception  {
115
+    public void throwsExceptionForUnknownType() throws Exception {
114
         when(rootViewCreator.createRootView(eq(VIEW_ID), eq(VIEW_NAME))).thenReturn(mockView);
116
         when(rootViewCreator.createRootView(eq(VIEW_ID), eq(VIEW_NAME))).thenReturn(mockView);
115
         final LayoutNode node = new LayoutNode(VIEW_ID, "***unknownType***", Collections.<String, Object>emptyMap());
117
         final LayoutNode node = new LayoutNode(VIEW_ID, "***unknownType***", Collections.<String, Object>emptyMap());
116
 
118
 
118
     }
120
     }
119
 
121
 
120
     private LayoutFactory createLayoutFactory() {
122
     private LayoutFactory createLayoutFactory() {
121
-        BottomTabs bottomTabs = mock(BottomTabs.class);
122
-        BottomTabsCreator bottomTabsCreator = mock(BottomTabsCreator.class);
123
-        when(bottomTabsCreator.create()).thenReturn(bottomTabs);
123
+        return createLayoutFactory(null);
124
+    }
125
+
126
+    private LayoutFactory createLayoutFactory(BottomTabs bottomTabs) {
127
+        BottomTabsCreator bottomTabsCreator = null;
128
+        if (bottomTabs != null) {
129
+            bottomTabsCreator = mock(BottomTabsCreator.class);
130
+            when(bottomTabsCreator.create()).thenReturn(bottomTabs);
131
+        }
132
+
124
         return new LayoutFactory(activity, rootViewCreator, bottomTabsCreator);
133
         return new LayoutFactory(activity, rootViewCreator, bottomTabsCreator);
125
     }
134
     }
126
 
135