Browse Source

initial android subtitle impl

Guy Carmeli 6 years ago
parent
commit
9679c44203

+ 16
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/Alignment.java View File

@@ -0,0 +1,16 @@
1
+package com.reactnativenavigation.parse;
2
+
3
+public enum Alignment {
4
+    Center, Fill, Default;
5
+
6
+    public static Alignment fromString(String alignment) {
7
+        switch (alignment) {
8
+            case "center":
9
+                return Center;
10
+            case "fill":
11
+                return Fill;
12
+            default:
13
+                return Default;
14
+        }
15
+    }
16
+}

+ 56
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/SubtitleOptions.java View File

@@ -0,0 +1,56 @@
1
+package com.reactnativenavigation.parse;
2
+
3
+import android.graphics.Typeface;
4
+import android.support.annotation.Nullable;
5
+
6
+import com.reactnativenavigation.parse.params.Color;
7
+import com.reactnativenavigation.parse.params.Fraction;
8
+import com.reactnativenavigation.parse.params.NullColor;
9
+import com.reactnativenavigation.parse.params.NullFraction;
10
+import com.reactnativenavigation.parse.params.NullText;
11
+import com.reactnativenavigation.parse.params.Text;
12
+import com.reactnativenavigation.parse.parsers.ColorParser;
13
+import com.reactnativenavigation.parse.parsers.FractionParser;
14
+import com.reactnativenavigation.parse.parsers.TextParser;
15
+import com.reactnativenavigation.utils.TypefaceLoader;
16
+
17
+import org.json.JSONObject;
18
+
19
+public class SubtitleOptions {
20
+    public static SubtitleOptions parse(TypefaceLoader typefaceManager, JSONObject json) {
21
+        final SubtitleOptions options = new SubtitleOptions();
22
+        if (json == null) {
23
+            return options;
24
+        }
25
+
26
+        options.text = TextParser.parse(json, "text");
27
+        options.color = ColorParser.parse(json, "color");
28
+        options.fontSize = FractionParser.parse(json, "fontSize");
29
+        options.fontFamily = typefaceManager.getTypeFace(json.optString("fontFamily", ""));
30
+        options.alignment = Alignment.fromString(TextParser.parse(json, "alignment").get(""));
31
+
32
+        return options;
33
+    }
34
+
35
+    public Text text = new NullText();
36
+    public Color color = new NullColor();
37
+    public Fraction fontSize = new NullFraction();
38
+    @Nullable public Typeface fontFamily;
39
+    public Alignment alignment = Alignment.Default;
40
+
41
+    void mergeWith(final SubtitleOptions other) {
42
+        if (other.text.hasValue()) text = other.text;
43
+        if (other.color.hasValue()) color = other.color;
44
+        if (other.fontSize.hasValue()) fontSize = other.fontSize;
45
+        if (other.fontFamily != null) fontFamily = other.fontFamily;
46
+        if (other.alignment != Alignment.Default) alignment = other.alignment;
47
+    }
48
+
49
+    void mergeWithDefault(SubtitleOptions defaultOptions) {
50
+        if (!text.hasValue()) text = defaultOptions.text;
51
+        if (!color.hasValue()) color = defaultOptions.color;
52
+        if (!fontSize.hasValue()) fontSize = defaultOptions.fontSize;
53
+        if (fontFamily == null) fontFamily = defaultOptions.fontFamily;
54
+        if (alignment == Alignment.Default) alignment = defaultOptions.alignment;
55
+    }
56
+}

+ 0
- 14
lib/android/app/src/main/java/com/reactnativenavigation/parse/TitleOptions.java View File

@@ -19,20 +19,6 @@ import com.reactnativenavigation.utils.TypefaceLoader;
19 19
 import org.json.JSONObject;
20 20
 
21 21
 public class TitleOptions {
22
-    public enum Alignment {
23
-        Center, Fill, Default;
24
-
25
-        public static Alignment fromString(String alignment) {
26
-            switch (alignment) {
27
-                case "center":
28
-                    return Center;
29
-                case "fill":
30
-                    return Fill;
31
-                default:
32
-                    return Default;
33
-            }
34
-        }
35
-    }
36 22
 
37 23
     public static TitleOptions parse(TypefaceLoader typefaceManager, JSONObject json) {
38 24
         final TitleOptions options = new TitleOptions();

+ 4
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/TopBarOptions.java View File

@@ -23,6 +23,7 @@ public class TopBarOptions implements DEFAULT_VALUES {
23 23
         if (json == null) return options;
24 24
 
25 25
         options.title = TitleOptions.parse(typefaceManager, json.optJSONObject("title"));
26
+        options.subtitle = SubtitleOptions.parse(typefaceManager, json.optJSONObject("subtitle"));
26 27
         options.background = TopBarBackgroundOptions.parse(json.optJSONObject("background"));
27 28
         options.visible = BoolParser.parse(json, "visible");
28 29
         options.animate = BoolParser.parse(json,"animate");
@@ -36,6 +37,7 @@ public class TopBarOptions implements DEFAULT_VALUES {
36 37
     }
37 38
 
38 39
     public TitleOptions title = new TitleOptions();
40
+    public SubtitleOptions subtitle = new SubtitleOptions();
39 41
     public Text testId = new NullText();
40 42
     public TopBarBackgroundOptions background = new TopBarBackgroundOptions();
41 43
     public Bool visible = new NullBool();
@@ -47,6 +49,7 @@ public class TopBarOptions implements DEFAULT_VALUES {
47 49
 
48 50
     void mergeWith(final TopBarOptions other) {
49 51
         title.mergeWith(other.title);
52
+        subtitle.mergeWith(other.subtitle);
50 53
         background.mergeWith(other.background);
51 54
         if (other.testId.hasValue()) testId = other.testId;
52 55
         if (other.visible.hasValue()) visible = other.visible;
@@ -59,6 +62,7 @@ public class TopBarOptions implements DEFAULT_VALUES {
59 62
 
60 63
     void mergeWithDefault(TopBarOptions defaultOptions) {
61 64
         title.mergeWithDefault(defaultOptions.title);
65
+        subtitle.mergeWithDefault(defaultOptions.subtitle);
62 66
         background.mergeWithDefault(defaultOptions.background);
63 67
         if (!visible.hasValue()) visible = defaultOptions.visible;
64 68
         if (!animate.hasValue()) animate = defaultOptions.animate;

+ 6
- 1
lib/android/app/src/main/java/com/reactnativenavigation/presentation/OptionsPresenter.java View File

@@ -38,6 +38,7 @@ public class OptionsPresenter {
38 38
 
39 39
     private void applyTopBarOptions(TopBarOptions options, AnimationsOptions animationOptions, Component component) {
40 40
         if (options.title.text.hasValue()) topBar.setTitle(options.title.text.get());
41
+        if (options.subtitle.text.hasValue()) topBar.setSubtitle(options.subtitle.text.get());
41 42
         if (options.title.component.hasValue()) topBar.setTitleComponent(options.title.component.get(), options.title.alignment);
42 43
         topBar.setBackgroundColor(options.background.color);
43 44
         topBar.setBackgroundComponent(options.background.component);
@@ -122,9 +123,13 @@ public class OptionsPresenter {
122 123
     private void mergeTopBarOptions(TopBarOptions options, AnimationsOptions animationsOptions, Component component) {
123 124
         if (options.title.text.hasValue()) topBar.setTitle(options.title.text.get());
124 125
         if (options.title.component.hasValue()) topBar.setTitleComponent(options.title.component.get(), options.title.alignment);
125
-        if (options.background.color.hasValue()) topBar.setBackgroundColor(options.background.color);
126 126
         if (options.title.color.hasValue()) topBar.setTitleTextColor(options.title.color);
127 127
         if (options.title.fontSize.hasValue()) topBar.setTitleFontSize(options.title.fontSize);
128
+
129
+        if (options.subtitle.text.hasValue()) topBar.setSubtitle(options.subtitle.text.get());
130
+
131
+        if (options.background.color.hasValue()) topBar.setBackgroundColor(options.background.color);
132
+
128 133
         if (options.testId.hasValue()) topBar.setTestId(options.testId.get());
129 134
 
130 135
         if (options.title.fontFamily != null) topBar.setTitleTypeface(options.title.fontFamily);

+ 4
- 4
lib/android/app/src/main/java/com/reactnativenavigation/views/titlebar/TitleBar.java View File

@@ -12,7 +12,7 @@ import android.view.View;
12 12
 import android.view.ViewGroup;
13 13
 import android.widget.TextView;
14 14
 
15
-import com.reactnativenavigation.parse.TitleOptions;
15
+import com.reactnativenavigation.parse.Alignment;
16 16
 import com.reactnativenavigation.parse.params.Button;
17 17
 import com.reactnativenavigation.parse.params.Color;
18 18
 import com.reactnativenavigation.parse.params.Fraction;
@@ -58,7 +58,7 @@ public class TitleBar extends Toolbar {
58 58
         if (color.hasValue()) setTitleTextColor(color.get());
59 59
     }
60 60
 
61
-    public void setComponent(String componentName, TitleOptions.Alignment alignment) {
61
+    public void setComponent(String componentName, Alignment alignment) {
62 62
         clearTitle();
63 63
         reactViewController.setComponent(componentName);
64 64
         addView(reactViewController.getView(), getComponentLayoutParams(alignment));
@@ -164,9 +164,9 @@ public class TitleBar extends Toolbar {
164 164
         return null;
165 165
     }
166 166
 
167
-    public Toolbar.LayoutParams getComponentLayoutParams(TitleOptions.Alignment alignment) {
167
+    public Toolbar.LayoutParams getComponentLayoutParams(Alignment alignment) {
168 168
         LayoutParams lp = new LayoutParams(MATCH_PARENT, getHeight());
169
-        if (alignment == TitleOptions.Alignment.Center) {
169
+        if (alignment == Alignment.Center) {
170 170
             lp.gravity = Gravity.CENTER;
171 171
         }
172 172
         return lp;

+ 6
- 2
lib/android/app/src/main/java/com/reactnativenavigation/views/topbar/TopBar.java View File

@@ -16,8 +16,8 @@ import com.reactnativenavigation.anim.AnimationListener;
16 16
 import com.reactnativenavigation.anim.TopBarAnimator;
17 17
 import com.reactnativenavigation.anim.TopBarCollapseBehavior;
18 18
 import com.reactnativenavigation.interfaces.ScrollEventListener;
19
+import com.reactnativenavigation.parse.Alignment;
19 20
 import com.reactnativenavigation.parse.AnimationOptions;
20
-import com.reactnativenavigation.parse.TitleOptions;
21 21
 import com.reactnativenavigation.parse.params.Button;
22 22
 import com.reactnativenavigation.parse.params.Color;
23 23
 import com.reactnativenavigation.parse.params.Fraction;
@@ -79,6 +79,10 @@ public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAw
79 79
         return titleBar.getTitle();
80 80
     }
81 81
 
82
+    public void setSubtitle(String subtitle) {
83
+        titleBar.setSubtitle(subtitle);
84
+    }
85
+
82 86
     public void setTestId(String testId) {
83 87
         setTag(testId);
84 88
     }
@@ -95,7 +99,7 @@ public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAw
95 99
         titleBar.setTitleTypeface(typeface);
96 100
     }
97 101
 
98
-    public void setTitleComponent(String componentName, TitleOptions.Alignment alignment) {
102
+    public void setTitleComponent(String componentName, Alignment alignment) {
99 103
         titleBar.setComponent(componentName, alignment);
100 104
     }
101 105
 

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/parse/OptionsTest.java View File

@@ -84,7 +84,7 @@ public class OptionsTest extends BaseTest {
84 84
         assertThat(result.fabOptions.hideOnScroll.get()).isEqualTo(FAB_HIDE_ON_SCROLL);
85 85
         assertThat(result.fabOptions.alignVertically.get()).isEqualTo(FAB_ALIGN_VERTICALLY);
86 86
         assertThat(result.fabOptions.alignHorizontally.get()).isEqualTo(FAB_ALIGN_HORIZONTALLY);
87
-        assertThat(result.topBarOptions.title.alignment).isEqualTo(TitleOptions.Alignment.Center);
87
+        assertThat(result.topBarOptions.title.alignment).isEqualTo(Alignment.Center);
88 88
     }
89 89
 
90 90
     @NonNull

+ 2
- 2
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ExternalComponentViewControllerTest.java View File

@@ -52,13 +52,13 @@ public class ExternalComponentViewControllerTest extends BaseTest {
52 52
     }
53 53
 
54 54
     @Test
55
-    public void createView_returnsFrameLayout() throws Exception {
55
+    public void createView_returnsFrameLayout() {
56 56
         ExternalComponentLayout view = uut.getView();
57 57
         assertThat(FrameLayout.class.isAssignableFrom(view.getClass())).isTrue();
58 58
     }
59 59
 
60 60
     @Test
61
-    public void createView_createsExternalComponent() throws Exception {
61
+    public void createView_createsExternalComponent() {
62 62
         ExternalComponentLayout view = uut.getView();
63 63
         verify(componentCreator, times(1)).create((FragmentActivity) activity, reactInstanceManager, ec.passProps);
64 64
         assertThat(view.getChildCount()).isGreaterThan(0);

+ 14
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsApplyingTest.java View File

@@ -13,7 +13,9 @@ import com.reactnativenavigation.mocks.TestReactView;
13 13
 import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
14 14
 import com.reactnativenavigation.mocks.TopBarBackgroundViewCreatorMock;
15 15
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
16
+import com.reactnativenavigation.mocks.TypefaceLoaderMock;
16 17
 import com.reactnativenavigation.parse.Options;
18
+import com.reactnativenavigation.parse.SubtitleOptions;
17 19
 import com.reactnativenavigation.parse.TopBarBackgroundOptions;
18 20
 import com.reactnativenavigation.parse.params.Bool;
19 21
 import com.reactnativenavigation.parse.params.Fraction;
@@ -196,4 +198,16 @@ public class OptionsApplyingTest extends BaseTest {
196 198
         assertThat(((ColorDrawable) stackController.getTopBar().getTitleBar().getBackground()).getColor()).isEqualTo(Color.TRANSPARENT);
197 199
         assertThat(ViewUtils.findChildrenByClassRecursive(stackController.getTopBar(), TopBarBackgroundView.class)).isNotNull();
198 200
     }
201
+
202
+    @Test
203
+    public void appliesSubtitle() throws Exception {
204
+        JSONObject json = new JSONObject();
205
+        json.put("text", "sub");
206
+        uut.options.topBarOptions.subtitle = SubtitleOptions.parse(new TypefaceLoaderMock(), json);
207
+        uut.ensureViewIsCreated();
208
+        stackController.push(uut, new MockPromise());
209
+        uut.onViewAppeared();
210
+
211
+        assertThat(stackController.getTopBar().getTitleBar().getSubtitle()).isEqualTo("sub");
212
+    }
199 213
 }

+ 5
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsMergingTest.java View File

@@ -8,6 +8,7 @@ import com.reactnativenavigation.mocks.TestComponentLayout;
8 8
 import com.reactnativenavigation.mocks.TestReactView;
9 9
 import com.reactnativenavigation.parse.Options;
10 10
 import com.reactnativenavigation.parse.OrientationOptions;
11
+import com.reactnativenavigation.parse.SubtitleOptions;
11 12
 import com.reactnativenavigation.parse.TitleOptions;
12 13
 import com.reactnativenavigation.parse.params.Bool;
13 14
 import com.reactnativenavigation.parse.params.Color;
@@ -87,6 +88,9 @@ public class OptionsMergingTest extends BaseTest {
87 88
         titleOptions.fontSize = new Fraction(1.0f);
88 89
         titleOptions.fontFamily = Typeface.DEFAULT_BOLD;
89 90
         options.topBarOptions.title = titleOptions;
91
+        SubtitleOptions subtitleOptions = new SubtitleOptions();
92
+        subtitleOptions.text = new Text("Sub");
93
+        options.topBarOptions.subtitle = subtitleOptions;
90 94
         options.topBarOptions.background.color = new Color(0);
91 95
         options.topBarOptions.testId = new Text("test123");
92 96
         options.topBarOptions.animate = new Bool(false);
@@ -137,6 +141,7 @@ public class OptionsMergingTest extends BaseTest {
137 141
 
138 142
     private void assertTopBarOptions(int t) {
139 143
         verify(topBar, times(t)).setTitle(any());
144
+        verify(topBar, times(t)).setSubtitle(any());
140 145
         verify(topBar, times(t)).setTitleComponent(any(), any());
141 146
         verify(topBar, times(t)).setBackgroundColor(any());
142 147
         verify(topBar, times(t)).setTitleTextColor(any());

+ 7
- 7
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TitleBarTest.java View File

@@ -8,7 +8,7 @@ import android.view.ViewGroup;
8 8
 import com.reactnativenavigation.BaseTest;
9 9
 import com.reactnativenavigation.mocks.TitleBarReactViewCreatorMock;
10 10
 import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
11
-import com.reactnativenavigation.parse.TitleOptions;
11
+import com.reactnativenavigation.parse.Alignment;
12 12
 import com.reactnativenavigation.parse.params.Button;
13 13
 import com.reactnativenavigation.parse.params.Text;
14 14
 import com.reactnativenavigation.react.ReactView;
@@ -144,14 +144,14 @@ public class TitleBarTest extends BaseTest {
144 144
 
145 145
     @Test
146 146
     public void setComponent_addsComponentToTitleBar() {
147
-        uut.setComponent("com.rnn.CustomView", TitleOptions.Alignment.Center);
147
+        uut.setComponent("com.rnn.CustomView", Alignment.Center);
148 148
         verify(uut, times(1)).addView(any(TitleBarReactView.class), any(Toolbar.LayoutParams.class));
149 149
     }
150 150
 
151 151
     @Test
152 152
     public void setComponent_alignFill() {
153
-        uut.setComponent("com.rnn.CustomView", TitleOptions.Alignment.Fill);
154
-        verify(uut, times(1)).getComponentLayoutParams(TitleOptions.Alignment.Fill);
153
+        uut.setComponent("com.rnn.CustomView", Alignment.Fill);
154
+        verify(uut, times(1)).getComponentLayoutParams(Alignment.Fill);
155 155
         ArgumentCaptor<Toolbar.LayoutParams> lpCaptor = ArgumentCaptor.forClass(Toolbar.LayoutParams.class);
156 156
         verify(uut, times(1)).addView(any(TitleBarReactView.class), lpCaptor.capture());
157 157
         assertThat(lpCaptor.getValue().width == ViewGroup.LayoutParams.MATCH_PARENT);
@@ -159,8 +159,8 @@ public class TitleBarTest extends BaseTest {
159 159
 
160 160
     @Test
161 161
     public void setComponent_alignCenter() {
162
-        uut.setComponent("com.rnn.CustomView", TitleOptions.Alignment.Center);
163
-        verify(uut, times(1)).getComponentLayoutParams(TitleOptions.Alignment.Center);
162
+        uut.setComponent("com.rnn.CustomView", Alignment.Center);
163
+        verify(uut, times(1)).getComponentLayoutParams(Alignment.Center);
164 164
         ArgumentCaptor<Toolbar.LayoutParams> lpCaptor = ArgumentCaptor.forClass(Toolbar.LayoutParams.class);
165 165
         verify(uut, times(1)).addView(any(TitleBarReactView.class), lpCaptor.capture());
166 166
         assertThat(lpCaptor.getValue().width == ViewGroup.LayoutParams.WRAP_CONTENT);
@@ -169,7 +169,7 @@ public class TitleBarTest extends BaseTest {
169 169
 
170 170
     @Test
171 171
     public void clear() {
172
-        uut.setComponent("someComponent", TitleOptions.Alignment.Center);
172
+        uut.setComponent("someComponent", Alignment.Center);
173 173
         uut.clear();
174 174
         assertThat(uut.getTitle()).isNullOrEmpty();
175 175
         assertThat(uut.getMenu().size()).isZero();

+ 3
- 0
playground/src/screens/OptionsScreen.js View File

@@ -24,6 +24,9 @@ class OptionsScreen extends Component {
24 24
           fontFamily: 'HelveticaNeue-Italic',
25 25
           largeTitle: false
26 26
         },
27
+        subtitle: {
28
+          text: 'Static'
29
+        },
27 30
         background: {
28 31
           component: 'TopBarBackground'
29 32
         },