Browse Source

Implement setStyle on Android (#1168)

Guy Carmeli 7 years ago
parent
commit
9bdec359cd
18 changed files with 164 additions and 14 deletions
  1. 5
    0
      android/app/src/main/java/com/reactnativenavigation/bridge/NavigationReactModule.java
  2. 5
    0
      android/app/src/main/java/com/reactnativenavigation/controllers/Modal.java
  3. 7
    0
      android/app/src/main/java/com/reactnativenavigation/controllers/ModalController.java
  4. 5
    0
      android/app/src/main/java/com/reactnativenavigation/controllers/NavigationActivity.java
  5. 13
    0
      android/app/src/main/java/com/reactnativenavigation/controllers/NavigationCommandsHandler.java
  6. 8
    0
      android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java
  7. 3
    0
      android/app/src/main/java/com/reactnativenavigation/layouts/Layout.java
  8. 6
    0
      android/app/src/main/java/com/reactnativenavigation/layouts/SingleScreenLayout.java
  9. 5
    0
      android/app/src/main/java/com/reactnativenavigation/params/StyleParams.java
  10. 1
    2
      android/app/src/main/java/com/reactnativenavigation/params/TitleBarButtonParams.java
  11. 7
    2
      android/app/src/main/java/com/reactnativenavigation/params/parsers/StyleParamsParser.java
  12. 19
    2
      android/app/src/main/java/com/reactnativenavigation/screens/Screen.java
  13. 18
    0
      android/app/src/main/java/com/reactnativenavigation/screens/ScreenStack.java
  14. 45
    2
      android/app/src/main/java/com/reactnativenavigation/views/TitleBar.java
  15. 4
    0
      android/app/src/main/java/com/reactnativenavigation/views/TopBar.java
  16. 1
    5
      src/Screen.js
  17. 6
    0
      src/deprecated/platformSpecificDeprecated.android.js
  18. 6
    1
      src/platformSpecific.android.js

+ 5
- 0
android/app/src/main/java/com/reactnativenavigation/bridge/NavigationReactModule.java View File

@@ -96,6 +96,11 @@ public class NavigationReactModule extends ReactContextBaseJavaModule {
96 96
         NavigationCommandsHandler.setScreenFab(screenInstanceId, navigatorEventId, fabParams);
97 97
     }
98 98
 
99
+    @ReactMethod
100
+    public void setScreenStyle(String screenInstanceId, ReadableMap style) {
101
+        NavigationCommandsHandler.setScreenStyle(screenInstanceId, BundleConverter.toBundle(style));
102
+    }
103
+
99 104
     @ReactMethod
100 105
     public void setBottomTabBadgeByIndex(Integer index, String badge) {
101 106
         NavigationCommandsHandler.setBottomTabBadgeByIndex(index, badge);

+ 5
- 0
android/app/src/main/java/com/reactnativenavigation/controllers/Modal.java View File

@@ -3,6 +3,7 @@ package com.reactnativenavigation.controllers;
3 3
 import android.app.Dialog;
4 4
 import android.content.DialogInterface;
5 5
 import android.os.Build;
6
+import android.os.Bundle;
6 7
 import android.support.v7.app.AppCompatActivity;
7 8
 import android.view.Window;
8 9
 import android.view.WindowManager;
@@ -56,6 +57,10 @@ public class Modal extends Dialog implements DialogInterface.OnDismissListener,
56 57
         layout.setFab(screenInstanceId, navigatorEventId, fab);
57 58
     }
58 59
 
60
+    void updateScreenStyle(String screenInstanceId, Bundle styleParams) {
61
+        layout.updateScreenStyle(screenInstanceId, styleParams);
62
+    }
63
+
59 64
     public void showContextualMenu(String screenInstanceId, ContextualMenuParams params, Callback onButtonClicked) {
60 65
         layout.showContextualMenu(screenInstanceId, params, onButtonClicked);
61 66
     }

+ 7
- 0
android/app/src/main/java/com/reactnativenavigation/controllers/ModalController.java View File

@@ -1,5 +1,6 @@
1 1
 package com.reactnativenavigation.controllers;
2 2
 
3
+import android.os.Bundle;
3 4
 import android.support.v7.app.AppCompatActivity;
4 5
 import android.view.Window;
5 6
 
@@ -130,6 +131,12 @@ class ModalController implements ScreenStackContainer, Modal.OnModalDismissedLis
130 131
         }
131 132
     }
132 133
 
134
+    void updateScreenStyle(String screenInstanceId, Bundle styleParams) {
135
+        for (Modal modal : stack) {
136
+            modal.updateScreenStyle(screenInstanceId, styleParams);
137
+        }
138
+    }
139
+
133 140
     public void showContextualMenu(String screenInstanceId, ContextualMenuParams params, Callback onButtonClicked) {
134 141
         for (Modal modal : stack) {
135 142
             modal.showContextualMenu(screenInstanceId, params, onButtonClicked);

+ 5
- 0
android/app/src/main/java/com/reactnativenavigation/controllers/NavigationActivity.java View File

@@ -291,6 +291,11 @@ public class NavigationActivity extends AppCompatActivity implements DefaultHard
291 291
         modalController.setFab(screenInstanceId, navigatorEventId, fab);
292 292
     }
293 293
 
294
+    public void setScreenStyle(String screenInstanceId, Bundle styleParams) {
295
+        layout.updateScreenStyle(screenInstanceId, styleParams);
296
+        modalController.updateScreenStyle(screenInstanceId, styleParams);
297
+    }
298
+
294 299
     public void toggleSideMenuVisible(boolean animated, Side side) {
295 300
         layout.toggleSideMenuVisible(animated, side);
296 301
     }

+ 13
- 0
android/app/src/main/java/com/reactnativenavigation/controllers/NavigationCommandsHandler.java View File

@@ -247,6 +247,19 @@ public class NavigationCommandsHandler {
247 247
         });
248 248
     }
249 249
 
250
+    public static void setScreenStyle(final String screenInstanceId, final Bundle styleParams) {
251
+        final NavigationActivity currentActivity = NavigationActivity.currentActivity;
252
+        if (currentActivity == null) {
253
+            return;
254
+        }
255
+        NavigationApplication.instance.runOnMainThread(new Runnable() {
256
+            @Override
257
+            public void run() {
258
+                currentActivity.setScreenStyle(screenInstanceId, styleParams);
259
+            }
260
+        });
261
+    }
262
+
250 263
     public static void dismissTopModal() {
251 264
         final NavigationActivity currentActivity = NavigationActivity.currentActivity;
252 265
         if (currentActivity == null) {

+ 8
- 0
android/app/src/main/java/com/reactnativenavigation/layouts/BottomTabsLayout.java View File

@@ -1,5 +1,6 @@
1 1
 package com.reactnativenavigation.layouts;
2 2
 
3
+import android.os.Bundle;
3 4
 import android.support.annotation.NonNull;
4 5
 import android.support.annotation.Nullable;
5 6
 import android.support.v7.app.AppCompatActivity;
@@ -195,6 +196,13 @@ public class BottomTabsLayout extends BaseLayout implements AHBottomNavigation.O
195 196
         }
196 197
     }
197 198
 
199
+    @Override
200
+    public void updateScreenStyle(String screenInstanceId, Bundle styleParams) {
201
+        for (int i = 0; i < bottomTabs.getItemsCount(); i++) {
202
+            screenStacks[i].updateScreenStyle(screenInstanceId, styleParams);
203
+        }
204
+    }
205
+
198 206
     @Override
199 207
     public void selectTopTabByTabIndex(String screenInstanceId, int index) {
200 208
         for (int i = 0; i < bottomTabs.getItemsCount(); i++) {

+ 3
- 0
android/app/src/main/java/com/reactnativenavigation/layouts/Layout.java View File

@@ -1,5 +1,6 @@
1 1
 package com.reactnativenavigation.layouts;
2 2
 
3
+import android.os.Bundle;
3 4
 import android.view.View;
4 5
 
5 6
 import com.facebook.react.bridge.Callback;
@@ -61,4 +62,6 @@ public interface Layout extends ScreenStackContainer {
61 62
     void selectTopTabByTabIndex(String screenInstanceId, int index);
62 63
 
63 64
     void selectTopTabByScreen(String screenInstanceId);
65
+
66
+    void updateScreenStyle(String screenInstanceId, Bundle styleParams);
64 67
 }

+ 6
- 0
android/app/src/main/java/com/reactnativenavigation/layouts/SingleScreenLayout.java View File

@@ -1,5 +1,6 @@
1 1
 package com.reactnativenavigation.layouts;
2 2
 
3
+import android.os.Bundle;
3 4
 import android.support.annotation.Nullable;
4 5
 import android.support.v7.app.AppCompatActivity;
5 6
 import android.view.View;
@@ -260,6 +261,11 @@ public class SingleScreenLayout extends BaseLayout {
260 261
         stack.selectTopTabByScreen(screenInstanceId);
261 262
     }
262 263
 
264
+    @Override
265
+    public void updateScreenStyle(String screenInstanceId, Bundle styleParams) {
266
+        stack.updateScreenStyle(screenInstanceId, styleParams);
267
+    }
268
+
263 269
     @Override
264 270
     public void showSlidingOverlay(final SlidingOverlayParams params) {
265 271
         slidingOverlaysQueue.add(new SlidingOverlay(this, params));

+ 5
- 0
android/app/src/main/java/com/reactnativenavigation/params/StyleParams.java View File

@@ -7,6 +7,11 @@ import android.support.annotation.ColorInt;
7 7
 import com.reactnativenavigation.utils.TypefaceLoader;
8 8
 
9 9
 public class StyleParams {
10
+    public Bundle params;
11
+
12
+    public StyleParams(Bundle params) {
13
+        this.params = params;
14
+    }
10 15
     public static class Color {
11 16
         @ColorInt
12 17
         private Integer color = null;

+ 1
- 2
android/app/src/main/java/com/reactnativenavigation/params/TitleBarButtonParams.java View File

@@ -10,8 +10,7 @@ public class TitleBarButtonParams extends BaseTitleBarButtonParams {
10 10
         font = styleParams.titleBarTitleFont;
11 11
     }
12 12
 
13
-    public boolean hasFont()
14
-    {
13
+    public boolean hasFont() {
15 14
         return font != null && font.hasFont();
16 15
     }
17 16
 }

+ 7
- 2
android/app/src/main/java/com/reactnativenavigation/params/parsers/StyleParamsParser.java View File

@@ -14,12 +14,17 @@ public class StyleParamsParser {
14 14
         this.params = params;
15 15
     }
16 16
 
17
+    public StyleParamsParser merge(Bundle b) {
18
+        params.putAll(b);
19
+        return this;
20
+    }
21
+
17 22
     public StyleParams parse() {
18 23
         if (params == null) {
19 24
             return createDefaultStyleParams();
20 25
         }
21 26
 
22
-        StyleParams result = new StyleParams();
27
+        StyleParams result = new StyleParams(params);
23 28
         result.orientation = Orientation.fromString(params.getString("orientation", getDefaultOrientation()));
24 29
         result.statusBarColor = getColor("statusBarColor", getDefaultStatusBarColor());
25 30
         result.contextualMenuStatusBarColor = getColor("contextualMenuStatusBarColor", getDefaultContextualMenuStatusBarColor());
@@ -85,7 +90,7 @@ public class StyleParamsParser {
85 90
     }
86 91
 
87 92
     private StyleParams createDefaultStyleParams() {
88
-        StyleParams result = new StyleParams();
93
+        StyleParams result = new StyleParams(Bundle.EMPTY);
89 94
         result.titleBarDisabledButtonColor = getTitleBarDisabledButtonColor();
90 95
         result.topBarElevationShadowEnabled = true;
91 96
         result.titleBarHideOnScroll = false;

+ 19
- 2
android/app/src/main/java/com/reactnativenavigation/screens/Screen.java View File

@@ -4,6 +4,7 @@ import android.annotation.TargetApi;
4 4
 import android.app.Activity;
5 5
 import android.graphics.Color;
6 6
 import android.os.Build;
7
+import android.os.Bundle;
7 8
 import android.support.v7.app.AppCompatActivity;
8 9
 import android.view.Window;
9 10
 import android.widget.RelativeLayout;
@@ -25,6 +26,7 @@ import com.reactnativenavigation.params.ScreenParams;
25 26
 import com.reactnativenavigation.params.StyleParams;
26 27
 import com.reactnativenavigation.params.TitleBarButtonParams;
27 28
 import com.reactnativenavigation.params.TitleBarLeftButtonParams;
29
+import com.reactnativenavigation.params.parsers.StyleParamsParser;
28 30
 import com.reactnativenavigation.utils.ViewUtils;
29 31
 import com.reactnativenavigation.views.ContentView;
30 32
 import com.reactnativenavigation.views.LeftButtonOnClickListener;
@@ -50,7 +52,7 @@ public abstract class Screen extends RelativeLayout implements Subscriber {
50 52
     private final LeftButtonOnClickListener leftButtonOnClickListener;
51 53
     private VisibilityAnimator topBarVisibilityAnimator;
52 54
     private ScreenAnimator screenAnimator;
53
-    protected final StyleParams styleParams;
55
+    protected StyleParams styleParams;
54 56
     public final SharedElements sharedElements;
55 57
 
56 58
     public Screen(AppCompatActivity activity, ScreenParams screenParams, LeftButtonOnClickListener leftButtonOnClickListener) {
@@ -80,6 +82,21 @@ public abstract class Screen extends RelativeLayout implements Subscriber {
80 82
         }
81 83
     }
82 84
 
85
+    public void updateVisibleScreenStyle(Bundle styleParams) {
86
+        updateStyle(styleParams);
87
+        setStyle();
88
+    }
89
+
90
+    public void updateInvisibleScreenStyle(Bundle styleParams) {
91
+        updateStyle(styleParams);
92
+    }
93
+
94
+    private void updateStyle(Bundle styleParams) {
95
+        screenParams.styleParams = new StyleParamsParser(screenParams.styleParams.params).merge(styleParams).parse();
96
+        this.styleParams = screenParams.styleParams;
97
+        topBar.setButtonColor(this.styleParams);
98
+    }
99
+
83 100
     public void setStyle() {
84 101
         setStatusBarColor(styleParams.statusBarColor);
85 102
         setNavigationBarColor(styleParams.navigationBarColor);
@@ -233,7 +250,7 @@ public abstract class Screen extends RelativeLayout implements Subscriber {
233 250
         }
234 251
 
235 252
         for (TitleBarButtonParams titleBarButtonParam : titleBarButtonParams) {
236
-            titleBarButtonParam.setStyleFromScreen(screenParams.styleParams);
253
+            titleBarButtonParam.setStyleFromScreen(styleParams);
237 254
         }
238 255
     }
239 256
 

+ 18
- 0
android/app/src/main/java/com/reactnativenavigation/screens/ScreenStack.java View File

@@ -1,5 +1,6 @@
1 1
 package com.reactnativenavigation.screens;
2 2
 
3
+import android.os.Bundle;
3 4
 import android.support.annotation.Nullable;
4 5
 import android.support.v7.app.AppCompatActivity;
5 6
 import android.util.Log;
@@ -340,6 +341,23 @@ public class ScreenStack {
340 341
         });
341 342
     }
342 343
 
344
+    public void updateScreenStyle(String screenInstanceId, final Bundle styleParams) {
345
+        performOnScreen(screenInstanceId, new Task<Screen>() {
346
+            @Override
347
+            public void run(Screen screen) {
348
+                if (isScreenVisible(screen)) {
349
+                    screen.updateVisibleScreenStyle(styleParams);
350
+                } else {
351
+                    screen.updateInvisibleScreenStyle(styleParams);
352
+                }
353
+            }
354
+        });
355
+    }
356
+
357
+    private boolean isScreenVisible(Screen screen) {
358
+        return isStackVisible && peek() == screen;
359
+    }
360
+
343 361
     public void showContextualMenu(String screenInstanceId, final ContextualMenuParams params, final Callback onButtonClicked) {
344 362
         performOnScreen(screenInstanceId, new Task<Screen>() {
345 363
             @Override

+ 45
- 2
android/app/src/main/java/com/reactnativenavigation/views/TitleBar.java View File

@@ -25,6 +25,7 @@ public class TitleBar extends Toolbar {
25 25
     private static final int TITLE_VISIBILITY_ANIMATION_DURATION = 320;
26 26
     private LeftButton leftButton;
27 27
     private ActionMenuView actionMenuView;
28
+    private List<TitleBarButtonParams> rightButtons;
28 29
 
29 30
     public TitleBar(Context context) {
30 31
         super(context);
@@ -44,12 +45,13 @@ public class TitleBar extends Toolbar {
44 45
     }
45 46
 
46 47
     public void setRightButtons(List<TitleBarButtonParams> rightButtons, String navigatorEventId) {
48
+        this.rightButtons = rightButtons;
47 49
         Menu menu = getMenu();
48 50
         menu.clear();
49 51
         if (rightButtons == null) {
50 52
             return;
51 53
         }
52
-        addButtonsToTitleBar(rightButtons, navigatorEventId, menu);
54
+        addButtonsToTitleBar(navigatorEventId, menu);
53 55
     }
54 56
 
55 57
     public void setLeftButton(TitleBarLeftButtonParams leftButtonParams,
@@ -141,7 +143,7 @@ public class TitleBar extends Toolbar {
141 143
         }
142 144
     }
143 145
 
144
-    private void addButtonsToTitleBar(List<TitleBarButtonParams> rightButtons, String navigatorEventId, Menu menu) {
146
+    private void addButtonsToTitleBar(String navigatorEventId, Menu menu) {
145 147
         for (int i = 0; i < rightButtons.size(); i++) {
146 148
             final TitleBarButton button = ButtonFactory.create(menu, this, rightButtons.get(i), navigatorEventId);
147 149
             addButtonInReverseOrder(rightButtons, i, button);
@@ -245,4 +247,45 @@ public class TitleBar extends Toolbar {
245 247
             }
246 248
         });
247 249
     }
250
+
251
+    public void setButtonColor(StyleParams.Color titleBarButtonColor) {
252
+        if (!titleBarButtonColor.hasColor()) {
253
+            return;
254
+        }
255
+        updateButtonColor(titleBarButtonColor);
256
+        setButtonsIconColor();
257
+        setButtonTextColor();
258
+    }
259
+
260
+    private void updateButtonColor(StyleParams.Color titleBarButtonColor) {
261
+        for (TitleBarButtonParams rightButton : rightButtons) {
262
+            rightButton.color = titleBarButtonColor;
263
+        }
264
+    }
265
+
266
+    private void setButtonTextColor() {
267
+        final ActionMenuView buttonsContainer = ViewUtils.findChildByClass(this, ActionMenuView.class);
268
+        if (buttonsContainer != null) {
269
+            for (int i = 0; i < buttonsContainer.getChildCount(); i++) {
270
+                if (buttonsContainer.getChildAt(i) instanceof TextView) {
271
+                    ((TextView) buttonsContainer.getChildAt(i)).setTextColor(getButton(i).getColor().getColor());
272
+                }
273
+            }
274
+        }
275
+    }
276
+
277
+    private void setButtonsIconColor() {
278
+        final Menu menu = getMenu();
279
+        for (int i = 0; i < menu.size(); i++) {
280
+            if (menu.getItem(i).getIcon() != null) {
281
+                ViewUtils.tintDrawable(menu.getItem(i).getIcon(),
282
+                        getButton(i).getColor().getColor(),
283
+                        getButton(i).enabled);
284
+            }
285
+        }
286
+    }
287
+
288
+    BaseTitleBarButtonParams getButton(int index) {
289
+        return rightButtons.get(rightButtons.size() - index - 1);
290
+    }
248 291
 }

+ 4
- 0
android/app/src/main/java/com/reactnativenavigation/views/TopBar.java View File

@@ -66,6 +66,10 @@ public class TopBar extends AppBarLayout {
66 66
         titleBar.setSubtitle(subtitle);
67 67
     }
68 68
 
69
+    public void setButtonColor(StyleParams styleParams) {
70
+        titleBar.setButtonColor(styleParams.titleBarButtonColor);
71
+    }
72
+
69 73
     public void setStyle(StyleParams styleParams) {
70 74
         if (styleParams.topBarColor.hasColor()) {
71 75
             setBackgroundColor(styleParams.topBarColor.getColor());

+ 1
- 5
src/Screen.js View File

@@ -89,11 +89,7 @@ class Navigator {
89 89
   }
90 90
 
91 91
   setStyle(params = {}) {
92
-    if (Platform.OS === 'ios') {
93
-      return platformSpecific.navigatorSetStyle(this, params);
94
-    } else {
95
-      console.log(`Setting style isn\'t supported on ${Platform.OS} yet`);
96
-    }
92
+    return platformSpecific.navigatorSetStyle(this, params);
97 93
   }
98 94
 
99 95
   toggleDrawer(params = {}) {

+ 6
- 0
src/deprecated/platformSpecificDeprecated.android.js View File

@@ -342,6 +342,11 @@ function navigatorSetSubtitle(navigator, params) {
342 342
   newPlatformSpecific.setScreenTitleBarSubtitle(navigator.screenInstanceID, params.subtitle);
343 343
 }
344 344
 
345
+function navigatorSetStyle(navigator, params) {
346
+  const style = convertStyleParams(params);
347
+  newPlatformSpecific.setScreenStyle(navigator.screenInstanceID, style);
348
+}
349
+
345 350
 function navigatorSwitchToTab(navigator, params) {
346 351
   if (params.tabIndex >= 0) {
347 352
     newPlatformSpecific.selectBottomTabByTabIndex(params.tabIndex);
@@ -668,6 +673,7 @@ export default {
668 673
   navigatorSetTabBadge,
669 674
   navigatorSetTitle,
670 675
   navigatorSetSubtitle,
676
+  navigatorSetStyle,
671 677
   navigatorSwitchToTab,
672 678
   navigatorSwitchToTopTab,
673 679
   navigatorToggleDrawer,

+ 6
- 1
src/platformSpecific.android.js View File

@@ -161,6 +161,10 @@ function dismissContextualMenu(screenInstanceID) {
161 161
   NativeReactModule.dismissContextualMenu(screenInstanceID);
162 162
 }
163 163
 
164
+function setScreenStyle(screenInstanceId, style) {
165
+  NativeReactModule.setScreenStyle(screenInstanceId, style);
166
+}
167
+
164 168
 module.exports = {
165 169
   startApp,
166 170
   push,
@@ -190,5 +194,6 @@ module.exports = {
190 194
   showSnackbar,
191 195
   dismissSnackbar,
192 196
   showContextualMenu,
193
-  dismissContextualMenu
197
+  dismissContextualMenu,
198
+  setScreenStyle
194 199
 };