ソースを参照

More work on TopBar background component

Guy Carmeli 6 年 前
コミット
7fe85fa02f

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

@@ -19,6 +19,10 @@ public class TopBarBackgroundOptions {
19 19
         options.color = ColorParser.parse(json, "color");
20 20
         options.component = TextParser.parse(json, "component");
21 21
 
22
+        if (options.component.hasValue()) {
23
+            options.color = new Color(android.graphics.Color.TRANSPARENT);
24
+        }
25
+
22 26
         return options;
23 27
     }
24 28
 
@@ -27,9 +31,11 @@ public class TopBarBackgroundOptions {
27 31
 
28 32
     void mergeWith(final TopBarBackgroundOptions other) {
29 33
         if (other.color.hasValue()) color = other.color;
34
+        if (other.component.hasValue()) component = other.component;
30 35
     }
31 36
 
32 37
     void mergeWithDefault(TopBarBackgroundOptions defaultOptions) {
33 38
         if (!color.hasValue()) color = defaultOptions.color;
39
+        if (!component.hasValue()) component = defaultOptions.component;
34 40
     }
35 41
 }

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

@@ -40,6 +40,7 @@ public class OptionsPresenter {
40 40
         if (options.title.text.hasValue()) topBar.setTitle(options.title.text.get());
41 41
         if (options.title.component.hasValue()) topBar.setComponent(options.title.component.get(), options.title.alignment);
42 42
         topBar.setBackgroundColor(options.background.color);
43
+        topBar.setBackgroundComponent(options.background.component);
43 44
         topBar.setTitleTextColor(options.title.color);
44 45
         topBar.setTitleFontSize(options.title.fontSize);
45 46
         if (options.testId.hasValue()) topBar.setTestId(options.testId.get());

+ 12
- 7
lib/android/app/src/main/java/com/reactnativenavigation/views/TopBar.java ファイルの表示

@@ -13,18 +13,17 @@ import android.view.View;
13 13
 import android.widget.RelativeLayout;
14 14
 import android.widget.TextView;
15 15
 
16
-import com.reactnativenavigation.R;
17 16
 import com.reactnativenavigation.anim.AnimationListener;
18 17
 import com.reactnativenavigation.anim.TopBarAnimator;
19 18
 import com.reactnativenavigation.anim.TopBarCollapseBehavior;
20 19
 import com.reactnativenavigation.interfaces.ScrollEventListener;
21 20
 import com.reactnativenavigation.parse.AnimationOptions;
22 21
 import com.reactnativenavigation.parse.TitleOptions;
23
-import com.reactnativenavigation.parse.TopBarBackgroundOptions;
24 22
 import com.reactnativenavigation.parse.params.Button;
25 23
 import com.reactnativenavigation.parse.params.Color;
26 24
 import com.reactnativenavigation.parse.params.Fraction;
27 25
 import com.reactnativenavigation.parse.params.Number;
26
+import com.reactnativenavigation.parse.params.Text;
28 27
 import com.reactnativenavigation.utils.CompatUtils;
29 28
 import com.reactnativenavigation.viewcontrollers.ReactViewCreator;
30 29
 import com.reactnativenavigation.viewcontrollers.TitleBarReactViewController;
@@ -48,6 +47,7 @@ public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAw
48 47
     private RelativeLayout root;
49 48
     private StackLayout parentView;
50 49
     private TopBarBackgroundViewCreator topBarBackgroundViewCreator;
50
+    private TopBarBackgroundView backgroundView;
51 51
 
52 52
     public TopBar(final Context context, ReactViewCreator buttonCreator, TitleBarReactViewCreator titleBarReactViewCreator, TopBarBackgroundViewCreator topBarBackgroundViewCreator, TopBarButtonController.OnClickListener onClickListener, StackLayout parentView) {
53 53
         super(context);
@@ -104,11 +104,11 @@ public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAw
104 104
         titleBar.setComponent(componentName, alignment);
105 105
     }
106 106
 
107
-    public void setBackgroundComponent(TopBarBackgroundOptions options) {
108
-        if (options.component.hasValue()) {
109
-            TopBarBackgroundView background = topBarBackgroundViewCreator.create((Activity) getContext(), String.valueOf(CompatUtils.generateViewId()), options.component.get());
110
-            background.setId(R.id.topBarBackgroundComponent);
111
-            root.addView(background);
107
+    public void setBackgroundComponent(Text component) {
108
+        if (component.hasValue()) {
109
+            backgroundView = topBarBackgroundViewCreator.create((Activity) getContext(), String.valueOf(CompatUtils.generateViewId()), component.get());
110
+            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(MATCH_PARENT, getHeight());
111
+            root.addView(backgroundView, 0, lp);
112 112
         }
113 113
     }
114 114
 
@@ -202,6 +202,11 @@ public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAw
202 202
     }
203 203
 
204 204
     public void clear() {
205
+        if (backgroundView != null) {
206
+            backgroundView.destroy();
207
+            root.removeView(backgroundView);
208
+            backgroundView = null;
209
+        }
205 210
         titleBar.clear();
206 211
     }
207 212
 

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

@@ -55,6 +55,7 @@ public class TitleBar extends Toolbar {
55 55
         clearTitle();
56 56
         reactViewController.setComponent(componentName);
57 57
         addView(reactViewController.getView(), getComponentLayoutParams(alignment));
58
+        requestLayout();
58 59
     }
59 60
 
60 61
     public void setBackgroundColor(Color color) {

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

@@ -12,12 +12,4 @@ public class TopBarBackgroundView extends ReactView {
12 12
     public TopBarBackgroundView(Context context, ReactInstanceManager reactInstanceManager, String componentId, String componentName) {
13 13
         super(context, reactInstanceManager, componentId, componentName);
14 14
     }
15
-
16
-    @Override
17
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18
-        super.onMeasure(
19
-                getChildCount() > 0 ? MeasureSpec.makeMeasureSpec(getChildAt(0).getWidth(), MeasureSpec.EXACTLY) : widthMeasureSpec,
20
-                heightMeasureSpec
21
-        );
22
-    }
23 15
 }

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

@@ -14,10 +14,14 @@ import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
14 14
 import com.reactnativenavigation.mocks.TopBarBackgroundViewCreatorMock;
15 15
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
16 16
 import com.reactnativenavigation.parse.Options;
17
+import com.reactnativenavigation.parse.TopBarBackgroundOptions;
17 18
 import com.reactnativenavigation.parse.params.Bool;
18 19
 import com.reactnativenavigation.parse.params.Fraction;
19 20
 import com.reactnativenavigation.parse.params.Text;
21
+import com.reactnativenavigation.utils.ViewUtils;
22
+import com.reactnativenavigation.views.topbar.TopBarBackgroundView;
20 23
 
24
+import org.json.JSONObject;
21 25
 import org.junit.Test;
22 26
 
23 27
 import javax.annotation.Nullable;
@@ -177,4 +181,17 @@ public class OptionsApplyingTest extends BaseTest {
177 181
             }
178 182
         });
179 183
     }
184
+
185
+    @Test
186
+    public void appliesTopBarComponent() throws Exception {
187
+        JSONObject json = new JSONObject();
188
+        json.put("component", "someComponent");
189
+        uut.options.topBarOptions.background = TopBarBackgroundOptions.parse(json);
190
+        uut.ensureViewIsCreated();
191
+        stackController.push(uut, new MockPromise());
192
+        uut.onViewAppeared();
193
+
194
+        assertThat(((ColorDrawable) stackController.getTopBar().getTitleBar().getBackground()).getColor()).isEqualTo(Color.TRANSPARENT);
195
+        assertThat(ViewUtils.findChildrenByClassRecursive(stackController.getTopBar(), TopBarBackgroundView.class)).isNotNull();
196
+    }
180 197
 }

+ 31
- 10
lib/android/app/src/test/java/com/reactnativenavigation/views/TopBarBackgroundComponentTest.java ファイルの表示

@@ -1,24 +1,29 @@
1 1
 package com.reactnativenavigation.views;
2 2
 
3
+import android.app.Activity;
3 4
 import android.util.Log;
5
+import android.view.ViewGroup;
4 6
 
5 7
 import com.reactnativenavigation.BaseTest;
6 8
 import com.reactnativenavigation.R;
7 9
 import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
8 10
 import com.reactnativenavigation.mocks.TopBarBackgroundViewCreatorMock;
9 11
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
10
-import com.reactnativenavigation.parse.TopBarBackgroundOptions;
11 12
 import com.reactnativenavigation.parse.params.Text;
12
-import com.reactnativenavigation.react.ReactView;
13
+import com.reactnativenavigation.utils.ViewUtils;
13 14
 import com.reactnativenavigation.viewcontrollers.TopBarButtonController;
15
+import com.reactnativenavigation.views.topbar.TopBarBackgroundView;
14 16
 
15 17
 import org.junit.Test;
16 18
 
17 19
 import static org.assertj.core.api.Java6Assertions.assertThat;
18 20
 import static org.mockito.Mockito.spy;
21
+import static org.mockito.Mockito.times;
22
+import static org.mockito.Mockito.verify;
19 23
 
20 24
 public class TopBarBackgroundComponentTest extends BaseTest {
21 25
     private TopBar uut;
26
+    private TopBarBackgroundView backgroundView;
22 27
 
23 28
     @SuppressWarnings("Convert2Lambda")
24 29
     @Override
@@ -29,23 +34,39 @@ public class TopBarBackgroundComponentTest extends BaseTest {
29 34
                 Log.i("TopBarTest", "onPress: " + buttonId);
30 35
             }
31 36
         });
32
-        StackLayout parent = new StackLayout(newActivity(), new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), onClickListener);
33
-        uut = new TopBar(newActivity(), new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), new TopBarBackgroundViewCreatorMock(), onClickListener, parent);
37
+        TopBarBackgroundViewCreatorMock backgroundViewCreator = new TopBarBackgroundViewCreatorMock() {
38
+            @Override
39
+            public TopBarBackgroundView create(Activity activity, String componentId, String componentName) {
40
+                backgroundView = spy(super.create(activity, componentId, componentName));
41
+                return backgroundView;
42
+            }
43
+        };
44
+        StackLayout parent = new StackLayout(newActivity(), new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), backgroundViewCreator, onClickListener);
45
+        uut = new TopBar(newActivity(), new TopBarButtonCreatorMock(), new TitleBarReactViewCreatorMock(), backgroundViewCreator, onClickListener, parent);
34 46
         parent.addView(uut);
35 47
     }
36 48
 
37 49
     @Test
38 50
     public void setBackgroundComponent() throws Exception {
39
-        TopBarBackgroundOptions options = new TopBarBackgroundOptions();
40
-        options.component = new Text("someComponent");
41
-        uut.setBackgroundComponent(options);
42
-        assertThat(ReactView.class.isAssignableFrom(uut.findViewById(R.id.topBarBackgroundComponent).getClass())).isTrue();
51
+        uut.getLayoutParams().height = 100;
52
+        uut.setBackgroundComponent(new Text("someComponent"));
53
+        TopBarBackgroundView background = (TopBarBackgroundView) ViewUtils.findChildrenByClassRecursive(uut, TopBarBackgroundView.class).get(0);
54
+        assertThat(background).isNotNull();
55
+        assertThat(background.getLayoutParams().width).isEqualTo(ViewGroup.LayoutParams.MATCH_PARENT);
56
+        assertThat(background.getLayoutParams().height).isEqualTo(uut.getHeight());
43 57
     }
44 58
 
45 59
     @Test
46 60
     public void setBackgroundComponent_doesNotSetIfNoComponentIsDefined() throws Exception {
47
-        TopBarBackgroundOptions options = new TopBarBackgroundOptions();
48
-        uut.setBackgroundComponent(options);
61
+        uut.setBackgroundComponent(new Text("someComponent"));
49 62
         assertThat(uut.findViewById(R.id.topBarBackgroundComponent)).isNull();
50 63
     }
64
+
65
+    @Test
66
+    public void clear_componentIsDestroyed() throws Exception {
67
+        uut.setBackgroundComponent(new Text("someComponent"));
68
+        uut.clear();
69
+        verify(backgroundView, times(1)).destroy();
70
+        assertThat(backgroundView.getParent()).isNull();
71
+    }
51 72
 }

+ 3
- 0
playground/src/screens/OptionsScreen.js ファイルの表示

@@ -24,6 +24,9 @@ class OptionsScreen extends Component {
24 24
           fontFamily: 'HelveticaNeue-Italic',
25 25
           largeTitle: false
26 26
         },
27
+        background: {
28
+          component: 'TopBarBackground'
29
+        },
27 30
         ...Platform.select({
28 31
           android: { drawBehind: true },
29 32
           ios: { drawBehind: false, }

+ 41
- 0
playground/src/screens/TopBarBackground.js ファイルの表示

@@ -0,0 +1,41 @@
1
+const React = require('react');
2
+const { Component } = require('react');
3
+const {
4
+  StyleSheet,
5
+  View
6
+} = require('react-native');
7
+
8
+class TopBarBackground extends Component {
9
+
10
+  constructor(props) {
11
+    super(props);
12
+    this.state = {};
13
+    this.dots = new Array(55).fill('').map((ignored, i) => <View key={'dot' + i} style={styles.dot}/>);
14
+  }
15
+
16
+  render() {
17
+    return (
18
+      <View style={styles.container}>
19
+        {this.dots}
20
+      </View>
21
+    );
22
+  }
23
+}
24
+
25
+module.exports = TopBarBackground;
26
+
27
+const styles = StyleSheet.create({
28
+  container: {
29
+    flex: 1,
30
+    flexDirection: 'row',
31
+    backgroundColor: '#e0e0e0',
32
+    flexWrap: 'wrap'
33
+  },
34
+  dot: {
35
+    height: 16,
36
+    width: 16,
37
+    borderRadius: 8,
38
+    margin: 4,
39
+    backgroundColor: '#bbdefb'
40
+  }
41
+});

+ 2
- 0
playground/src/screens/index.js ファイルの表示

@@ -21,6 +21,7 @@ const Alert = require('./Alert');
21 21
 const BackHandlerModalScreen = require('./BackHandlerModalScreen');
22 22
 const CustomTextButton = require('./CustomTextButton');
23 23
 const CustomRoundedButton = require('./CustomRoundedButton');
24
+const TopBarBackground = require('./TopBarBackground');
24 25
 
25 26
 function registerScreens() {
26 27
   Navigation.registerComponent(`navigation.playground.CustomTransitionDestination`, () => CustomTransitionDestination);
@@ -45,6 +46,7 @@ function registerScreens() {
45 46
   Navigation.registerComponent('navigation.playground.BackHandlerModalScreen', () => BackHandlerModalScreen);
46 47
   Navigation.registerComponent('CustomTextButton', () => CustomTextButton);
47 48
   Navigation.registerComponent('CustomRoundedButton', () => CustomRoundedButton);
49
+  Navigation.registerComponent('TopBarBackground', () => TopBarBackground);
48 50
 }
49 51
 
50 52
 module.exports = {