Guy Carmeli пре 8 година
родитељ
комит
5dabdc225b

+ 1
- 0
android/app/build.gradle Прегледај датотеку

@@ -50,6 +50,7 @@ dependencies {
50 50
     compile "com.android.support:appcompat-v7:23.0.1"
51 51
     compile 'com.android.support:design:23.1.1'
52 52
     compile "com.facebook.react:react-native:+"  // From node_modules
53
+    compile 'com.balysv.materialmenu:material-menu-toolbar:1.5.4'
53 54
 
54 55
     testCompile "junit:junit:4.12"
55 56
     testCompile "org.robolectric:robolectric:3.1.1"

+ 1
- 1
android/app/src/main/java/com/reactnativenavigation/bridge/NavigationReactModule.java Прегледај датотеку

@@ -45,7 +45,7 @@ public class NavigationReactModule extends ReactContextBaseJavaModule {
45 45
 
46 46
     @ReactMethod
47 47
     public void setScreenTitleBarButtons(String screenInstanceId, String navigatorEventId, ReadableArray buttons) {
48
-        List<TitleBarButtonParams> titleBarButtons = TitleBarButtonParamsParser.parse(BundleConverter.toBundle(buttons));
48
+        List<TitleBarButtonParams> titleBarButtons = TitleBarButtonParamsParser.parseButtons(BundleConverter.toBundle(buttons));
49 49
         NavigationCommandsHandler.setScreenTitleBarButtons(screenInstanceId, navigatorEventId, titleBarButtons);
50 50
     }
51 51
 

+ 2
- 1
android/app/src/main/java/com/reactnativenavigation/params/ScreenParams.java Прегледај датотеку

@@ -7,7 +7,8 @@ import java.util.List;
7 7
 public class ScreenParams {
8 8
     public String screenId;
9 9
     public Bundle passProps;
10
-    public List<TitleBarButtonParams> buttons;
10
+    public List<TitleBarButtonParams> rightButtons;
11
+    public TitleBarButtonParams leftButton;
11 12
     public String title;
12 13
     public ScreenStyleParams styleParams;
13 14
     public List<TopTabParams> topTabParams;

+ 8
- 2
android/app/src/main/java/com/reactnativenavigation/params/parsers/ScreenParamsParser.java Прегледај датотеку

@@ -11,7 +11,8 @@ public class ScreenParamsParser extends Parser {
11 11
     private static final String KEY_NAVIGATOR_EVENT_ID = "navigatorEventID";
12 12
     private static final String KEY_PROPS = "passProps";
13 13
     private static final String KEY_NAVIGATION_PARAMS = "navigationParams";
14
-    private static final String KEY_BUTTONS = "titleBarButtons";
14
+    private static final String KEY_RIGHT_BUTTONS = "rightButtons";
15
+    private static final String KEY_LEFT_BUTTON = "leftButton";
15 16
     private static final String STYLE_PARAMS = "styleParams";
16 17
     public static final String TOP_TABS = "topTabs";
17 18
 
@@ -25,7 +26,12 @@ public class ScreenParamsParser extends Parser {
25 26
         result.navigationParams = params.getBundle(KEY_NAVIGATION_PARAMS);
26 27
         result.navigatorEventId = result.navigationParams.getString(KEY_NAVIGATOR_EVENT_ID);
27 28
         result.screenInstanceId = result.navigationParams.getString(KEY_SCREEN_INSTANCE_ID);
28
-        result.buttons = TitleBarButtonParamsParser.parse(params.getBundle(KEY_BUTTONS));
29
+        if (hasKey(params, KEY_RIGHT_BUTTONS)) {
30
+            result.rightButtons = TitleBarButtonParamsParser.parseButtons(params.getBundle(KEY_RIGHT_BUTTONS));
31
+        }
32
+        if (hasKey(params, KEY_LEFT_BUTTON)) {
33
+            result.leftButton = TitleBarButtonParamsParser.parseSingleButton(params.getBundle(KEY_LEFT_BUTTON));
34
+        }
29 35
         result.title = params.getString(KEY_TITLE);
30 36
         result.styleParams = ScreenStyleParamsParser.parse(params.getBundle(STYLE_PARAMS));
31 37
         if (hasKey(params, TOP_TABS)) {

+ 3
- 6
android/app/src/main/java/com/reactnativenavigation/params/parsers/TitleBarButtonParamsParser.java Прегледај датотеку

@@ -10,19 +10,16 @@ import java.util.ArrayList;
10 10
 import java.util.List;
11 11
 
12 12
 public class TitleBarButtonParamsParser extends Parser {
13
-    public static List<TitleBarButtonParams> parse(Bundle params) {
13
+    public static List<TitleBarButtonParams> parseButtons(Bundle params) {
14 14
         List<TitleBarButtonParams> result = new ArrayList<>();
15
-        if (params == null) {
16
-            return result;
17
-        }
18 15
 
19 16
         for (String key : params.keySet()) {
20
-            result.add(parseItem(params.getBundle(key)));
17
+            result.add(parseSingleButton(params.getBundle(key)));
21 18
         }
22 19
         return result;
23 20
     }
24 21
 
25
-    private static TitleBarButtonParams parseItem(Bundle bundle) {
22
+    public static TitleBarButtonParams parseSingleButton(Bundle bundle) {
26 23
         TitleBarButtonParams result = new TitleBarButtonParams();
27 24
         result.label = bundle.getString("title");
28 25
         if (hasKey(bundle,"icon")) {

+ 6
- 2
android/app/src/main/java/com/reactnativenavigation/screens/Screen.java Прегледај датотеку

@@ -15,6 +15,7 @@ import com.reactnativenavigation.params.TitleBarButtonParams;
15 15
 import com.reactnativenavigation.utils.SdkSupports;
16 16
 import com.reactnativenavigation.utils.ViewUtils;
17 17
 import com.reactnativenavigation.views.ScrollDirectionListener;
18
+import com.reactnativenavigation.views.TitleBarBackButtonListener;
18 19
 import com.reactnativenavigation.views.TopBar;
19 20
 
20 21
 import java.util.List;
@@ -25,12 +26,14 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
25 26
 public abstract class Screen extends RelativeLayout implements ScrollDirectionListener.OnScrollChanged {
26 27
 
27 28
     protected final ScreenParams screenParams;
29
+    private final TitleBarBackButtonListener titleBarBackButtonListener;
28 30
     protected TopBar topBar;
29 31
     private VisibilityAnimator topBarVisibilityAnimator;
30 32
 
31
-    public Screen(Context context, ScreenParams screenParams) {
33
+    public Screen(Context context, ScreenParams screenParams, TitleBarBackButtonListener titleBarBackButtonListener) {
32 34
         super(context);
33 35
         this.screenParams = screenParams;
36
+        this.titleBarBackButtonListener = titleBarBackButtonListener;
34 37
 
35 38
         createViews();
36 39
         setStyle(screenParams.styleParams);
@@ -45,7 +48,8 @@ public abstract class Screen extends RelativeLayout implements ScrollDirectionLi
45 48
     protected abstract void createContent();
46 49
 
47 50
     private void createTitleBar() {
48
-        topBar.addTitleBarAndSetButtons(screenParams.buttons, screenParams.navigatorEventId);
51
+        topBar.addTitleBarAndSetButtons(screenParams.rightButtons, screenParams.leftButton,
52
+                titleBarBackButtonListener, screenParams.navigatorEventId);
49 53
         topBar.setTitle(screenParams.title);
50 54
     }
51 55
 

+ 5
- 2
android/app/src/main/java/com/reactnativenavigation/screens/ScreenFactory.java Прегледај датотеку

@@ -3,13 +3,16 @@ package com.reactnativenavigation.screens;
3 3
 import android.content.Context;
4 4
 
5 5
 import com.reactnativenavigation.params.ScreenParams;
6
+import com.reactnativenavigation.views.TitleBarBackButtonListener;
6 7
 
7 8
 public class ScreenFactory {
8
-    public static Screen create(Context context, ScreenParams screenParams) {
9
+    public static Screen create(Context context,
10
+                                ScreenParams screenParams,
11
+                                TitleBarBackButtonListener titleBarBackButtonListener) {
9 12
         if (screenParams.hasTopTabs()) {
10 13
             return new TabbedScreen(context, screenParams);
11 14
         } else {
12
-            return new SingleScreen(context, screenParams);
15
+            return new SingleScreen(context, screenParams, titleBarBackButtonListener);
13 16
         }
14 17
     }
15 18
 }

+ 17
- 14
android/app/src/main/java/com/reactnativenavigation/screens/ScreenStack.java Прегледај датотеку

@@ -6,6 +6,7 @@ import android.widget.FrameLayout;
6 6
 
7 7
 import com.reactnativenavigation.params.ScreenParams;
8 8
 import com.reactnativenavigation.params.TitleBarButtonParams;
9
+import com.reactnativenavigation.views.TitleBarBackButtonListener;
9 10
 
10 11
 import java.util.List;
11 12
 import java.util.Stack;
@@ -13,27 +14,27 @@ import java.util.Stack;
13 14
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
14 15
 
15 16
 // TODO there's really no reason for ScreenStack to extend FrameLayout. All screens can be added to parent.
16
-public class ScreenStack extends FrameLayout {
17
+public class ScreenStack extends FrameLayout implements TitleBarBackButtonListener {
17 18
     private Stack<Screen> stack = new Stack<>();
18 19
 
19 20
     public ScreenStack(Context context, ScreenParams initialScreenParams) {
20 21
         super(context);
21 22
         setLayoutTransition(new LayoutTransition());
22
-        push(initialScreenParams);
23
+        pushInitialScreen(initialScreenParams);
24
+    }
25
+
26
+    private void pushInitialScreen(ScreenParams initialScreenParams) {
27
+        addScreen(initialScreenParams);
23 28
     }
24 29
 
25 30
     public void push(ScreenParams screenParams) {
26
-        if (isEmpty()) {
27
-            addScreen(screenParams);
28
-        } else {
29
-            Screen previous = stack.peek();
30
-            addScreen(screenParams);
31
-            removePreviousWithoutUnmount(previous);
32
-        }
31
+        Screen previous = stack.peek();
32
+        addScreen(screenParams);
33
+        removePreviousWithoutUnmount(previous);
33 34
     }
34 35
 
35 36
     private void addScreen(ScreenParams screenParams) {
36
-        Screen screen = ScreenFactory.create(getContext(), screenParams);
37
+        Screen screen = ScreenFactory.create(getContext(), screenParams, this);
37 38
         addView(screen, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
38 39
         stack.push(screen);
39 40
     }
@@ -75,10 +76,6 @@ public class ScreenStack extends FrameLayout {
75 76
         stack.clear();
76 77
     }
77 78
 
78
-    public boolean isEmpty() {
79
-        return stack.isEmpty();
80
-    }
81
-
82 79
     public int getStackSize() {
83 80
         return stack.size();
84 81
     }
@@ -122,6 +119,12 @@ public class ScreenStack extends FrameLayout {
122 119
         }
123 120
     }
124 121
 
122
+    @Override
123
+    public void onTitleBarBackPress() {
124
+        if (canPop()) {
125
+            pop();
126
+        }
127
+    }
125 128
 
126 129
     //    /**
127 130
 //     * Remove the ScreenStack from {@code parent} while preventing all child react views from getting unmounted

+ 4
- 2
android/app/src/main/java/com/reactnativenavigation/screens/SingleScreen.java Прегледај датотеку

@@ -5,6 +5,7 @@ import android.support.annotation.NonNull;
5 5
 
6 6
 import com.reactnativenavigation.params.ScreenParams;
7 7
 import com.reactnativenavigation.views.ContentView;
8
+import com.reactnativenavigation.views.TitleBarBackButtonListener;
8 9
 
9 10
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
10 11
 
@@ -12,8 +13,9 @@ public class SingleScreen extends Screen {
12 13
 
13 14
     private ContentView contentView;
14 15
 
15
-    public SingleScreen(Context context, ScreenParams screenParams) {
16
-        super(context, screenParams);
16
+    public SingleScreen(Context context, ScreenParams screenParams,
17
+                        TitleBarBackButtonListener titleBarBarBackButtonListener) {
18
+        super(context, screenParams, titleBarBarBackButtonListener);
17 19
     }
18 20
 
19 21
     @Override

+ 68
- 0
android/app/src/main/java/com/reactnativenavigation/views/LeftButton.java Прегледај датотеку

@@ -0,0 +1,68 @@
1
+package com.reactnativenavigation.views;
2
+
3
+import android.content.Context;
4
+import android.graphics.Color;
5
+import android.view.View;
6
+
7
+import com.balysv.materialmenu.MaterialMenuDrawable;
8
+import com.reactnativenavigation.params.TitleBarButtonParams;
9
+
10
+// TODO: replace with vector menu drawable
11
+public class LeftButton extends MaterialMenuDrawable implements View.OnClickListener {
12
+
13
+    private static int getColor(TitleBarButtonParams params) {
14
+        return params != null && params.color.hasColor() ?
15
+                params.color.getColor() :
16
+                Color.BLACK;
17
+    }
18
+
19
+    private TitleBarButtonParams params;
20
+    private final TitleBarBackButtonListener titleBarBackButtonListener;
21
+    private final String navigatorEventId;
22
+
23
+    public LeftButton(Context context,
24
+                      TitleBarButtonParams params,
25
+                      TitleBarBackButtonListener titleBarBackButtonListener,
26
+                      String navigatorEventId) {
27
+        super(context, getColor(params), Stroke.THIN);
28
+        this.params = params;
29
+        this.titleBarBackButtonListener = titleBarBackButtonListener;
30
+        this.navigatorEventId = navigatorEventId;
31
+        setInitialState();
32
+    }
33
+
34
+    private void setInitialState() {
35
+        if (params != null) {
36
+            setIconState(getIconStateFromId(params.eventId));
37
+        } else {
38
+            setVisible(false);
39
+        }
40
+    }
41
+
42
+    @Override
43
+    public void onClick(View v) {
44
+        if (isBackButton()) {
45
+            titleBarBackButtonListener.onTitleBarBackPress();
46
+        }
47
+    }
48
+
49
+    // TODO: move to parser
50
+    public IconState getIconStateFromId(String id) {
51
+        switch (id) {
52
+            case "back":
53
+                return IconState.ARROW;
54
+            case "cancel":
55
+                return IconState.X;
56
+            case "accept":
57
+                return IconState.CHECK;
58
+            case "sideMenu":
59
+                return IconState.BURGER;
60
+            default:
61
+                throw new RuntimeException("Unsupported button type " + id);
62
+        }
63
+    }
64
+
65
+    private boolean isBackButton() {
66
+        return getIconState() == IconState.ARROW;
67
+    }
68
+}

+ 24
- 6
android/app/src/main/java/com/reactnativenavigation/views/TitleBar.java Прегледај датотеку

@@ -18,16 +18,34 @@ public class TitleBar extends Toolbar {
18 18
         super(context);
19 19
     }
20 20
 
21
-    public void setButtons(List<TitleBarButtonParams> buttons, String navigatorEventId) {
21
+    public void setRightButtons(List<TitleBarButtonParams> rightButtons, String navigatorEventId) {
22 22
         Menu menu = getMenu();
23 23
         menu.clear();
24 24
 
25
-        for (int i = 0; i < buttons.size(); i++) {
26
-            final TitleBarButton button = new TitleBarButton(menu, this, buttons.get(i), navigatorEventId);
27
-            // Add button in reverse order because in iOS index 0 starts at right
28
-            final int index = buttons.size() - i - 1;
29
-            button.addToMenu(index);
25
+        if (rightButtons == null) {
26
+            return;
30 27
         }
28
+
29
+        addButtonsToTitleBar(rightButtons, navigatorEventId, menu);
30
+    }
31
+
32
+    private void addButtonsToTitleBar(List<TitleBarButtonParams> rightButtons, String navigatorEventId, Menu menu) {
33
+        for (int i = 0; i < rightButtons.size(); i++) {
34
+            final TitleBarButton button = new TitleBarButton(menu, this, rightButtons.get(i), navigatorEventId);
35
+            addButtonInReverseOrder(rightButtons, i, button);
36
+        }
37
+    }
38
+
39
+    private void addButtonInReverseOrder(List<TitleBarButtonParams> rightButtons, int i, TitleBarButton button) {
40
+        final int index = rightButtons.size() - i - 1;
41
+        button.addToMenu(index);
42
+    }
43
+
44
+    public void setLeftButton(TitleBarButtonParams leftButtonParams,
45
+                               TitleBarBackButtonListener titleBarBackButtonListener, String navigatorEventId) {
46
+        LeftButton leftButton = new LeftButton(getContext(), leftButtonParams, titleBarBackButtonListener, navigatorEventId);
47
+        setNavigationOnClickListener(leftButton);
48
+        setNavigationIcon(leftButton);
31 49
     }
32 50
 
33 51
     public void setHideOnScroll(boolean hideOnScroll) {

+ 5
- 0
android/app/src/main/java/com/reactnativenavigation/views/TitleBarBackButtonListener.java Прегледај датотеку

@@ -0,0 +1,5 @@
1
+package com.reactnativenavigation.views;
2
+
3
+public interface TitleBarBackButtonListener {
4
+    void onTitleBarBackPress();
5
+}

+ 6
- 3
android/app/src/main/java/com/reactnativenavigation/views/TopBar.java Прегледај датотеку

@@ -21,10 +21,13 @@ public class TopBar extends AppBarLayout {
21 21
         setId(ViewUtils.generateViewId());
22 22
     }
23 23
 
24
-    public void addTitleBarAndSetButtons(List<TitleBarButtonParams> buttons, String navigatorEventId) {
24
+    public void addTitleBarAndSetButtons(List<TitleBarButtonParams> rightButtons, TitleBarButtonParams leftButton,
25
+                                         TitleBarBackButtonListener titleBarBackButtonListener,
26
+                                         String navigatorEventId) {
25 27
         titleBar = new TitleBar(getContext());
26 28
         addView(titleBar);
27
-        titleBar.setButtons(buttons, navigatorEventId);
29
+        titleBar.setRightButtons(rightButtons, navigatorEventId);
30
+        titleBar.setLeftButton(leftButton, titleBarBackButtonListener, navigatorEventId);
28 31
     }
29 32
 
30 33
     public void setTitle(String title) {
@@ -40,7 +43,7 @@ public class TopBar extends AppBarLayout {
40 43
     }
41 44
 
42 45
     public void setTitleBarButtons(String navigatorEventId, List<TitleBarButtonParams> titleBarButtons) {
43
-        titleBar.setButtons(titleBarButtons, navigatorEventId);
46
+        titleBar.setRightButtons(titleBarButtons, navigatorEventId);
44 47
     }
45 48
 
46 49
     public TabLayout initTabs() {

+ 34
- 3
src/deprecated/platformSpecificDeprecated.android.js Прегледај датотеку

@@ -136,6 +136,7 @@ function addTabIcon(tab) {
136 136
   }
137 137
 }
138 138
 
139
+// TODO: add left buttons here
139 140
 function navigatorSetButtons(navigator, navigatorEventID, params) {
140 141
   if (params.rightButtons) {
141 142
     params.rightButtons.forEach(function(button) {
@@ -229,8 +230,7 @@ function addNavigatorButtons(screen) {
229 230
   Object.assign(screen, Screen.navigatorButtons);
230 231
 
231 232
   // Get image uri from image id
232
-  const rightButtons = screen.navigatorButtons ? screen.navigatorButtons.rightButtons : null;
233
-
233
+  const rightButtons = getRightButtons(screen);
234 234
   if (rightButtons) {
235 235
     rightButtons.forEach(function(button) {
236 236
       if (button.icon) {
@@ -242,7 +242,38 @@ function addNavigatorButtons(screen) {
242 242
     });
243 243
   }
244 244
 
245
-  screen.titleBarButtons = rightButtons;
245
+  const leftButton = getLeftButton(screen);
246
+  if (leftButton) {
247
+    if (leftButton.icon) {
248
+      const icon = resolveAssetSource(leftButton.icon);
249
+      if (icon) {
250
+        leftButton.icon = icon.uri;
251
+      }
252
+    }
253
+  }
254
+
255
+  if (rightButtons) {
256
+    screen.rightButtons = rightButtons;
257
+  }
258
+  if (leftButton) {
259
+    screen.leftButton = leftButton;
260
+  }
261
+}
262
+
263
+function getLeftButton(screen) {
264
+  if (screen.navigatorButtons) {
265
+    return screen.navigatorButtons.leftButton;
266
+  }
267
+
268
+  return screen.leftButton
269
+}
270
+
271
+function getRightButtons(screen) {
272
+  if (screen.navigatorButtons) {
273
+    return screen.navigatorButtons.rightButtons;
274
+  }
275
+
276
+  return screen.rightButtons
246 277
 }
247 278
 
248 279
 function addNavigationStyleParams(screen) {