Browse Source

Implement custom TitleBar buttons on Android

Guy Carmeli 7 years ago
parent
commit
803dccffd4

+ 7
- 0
android/app/src/main/java/com/reactnativenavigation/params/BaseTitleBarButtonParams.java View File

@@ -1,6 +1,7 @@
1 1
 package com.reactnativenavigation.params;
2 2
 
3 3
 import android.graphics.drawable.Drawable;
4
+import android.os.Bundle;
4 5
 import android.view.MenuItem;
5 6
 
6 7
 public class BaseTitleBarButtonParams {
@@ -20,6 +21,8 @@ public class BaseTitleBarButtonParams {
20 21
     public String eventId;
21 22
     public String label;
22 23
     public Drawable icon;
24
+    public String componentName;
25
+    public Bundle componentProps;
23 26
     public StyleParams.Color color;
24 27
     public StyleParams.Color disabledColor;
25 28
     public ShowAsAction showAsAction;
@@ -42,4 +45,8 @@ public class BaseTitleBarButtonParams {
42 45
         }
43 46
         return disabledColor.hasColor() ? disabledColor : AppStyle.appStyle.titleBarDisabledButtonColor;
44 47
     }
48
+
49
+    public boolean hasComponent() {
50
+        return componentName != null;
51
+    }
45 52
 }

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

@@ -32,6 +32,8 @@ public class TitleBarButtonParamsParser extends Parser {
32 32
         result.hint = bundle.getString("hint", "");
33 33
         result.eventId = bundle.getString("id");
34 34
         result.disableIconTint = bundle.getBoolean("disableIconTint", false);
35
+        result.componentName = bundle.getString("component");
36
+        result.componentProps = bundle.getBundle("passProps");
35 37
         return result;
36 38
     }
37 39
 

+ 0
- 18
android/app/src/main/java/com/reactnativenavigation/views/ButtonFactory.java View File

@@ -1,18 +0,0 @@
1
-package com.reactnativenavigation.views;
2
-
3
-import android.view.Menu;
4
-import android.view.View;
5
-
6
-import com.reactnativenavigation.params.TitleBarButtonParams;
7
-
8
-class ButtonFactory {
9
-
10
-    public static TitleBarButton create(Menu menu, View parent, TitleBarButtonParams params, String navigatorEventId) {
11
-        switch (params.eventId) {
12
-            case TitleBarSearchButton.BUTTON_ID:
13
-                return new TitleBarSearchButton(menu, parent, params, navigatorEventId);
14
-            default:
15
-                return new TitleBarButton(menu, parent, params, navigatorEventId);
16
-        }
17
-    }
18
-}

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

@@ -175,7 +175,7 @@ public class TitleBar extends Toolbar {
175 175
 
176 176
     private void addButtonsToTitleBar(String navigatorEventId, Menu menu) {
177 177
         for (int i = 0; i < rightButtons.size(); i++) {
178
-            final TitleBarButton button = ButtonFactory.create(menu, this, rightButtons.get(i), navigatorEventId);
178
+            final TitleBarButton button = new TitleBarButton(menu, this, rightButtons.get(i), navigatorEventId);
179 179
             addButtonInReverseOrder(rightButtons, i, button);
180 180
         }
181 181
     }

+ 3
- 0
android/app/src/main/java/com/reactnativenavigation/views/TitleBarButton.java View File

@@ -34,6 +34,9 @@ class TitleBarButton implements MenuItem.OnMenuItemClickListener {
34 34
         MenuItem item = createMenuItem(index);
35 35
         item.setShowAsAction(buttonParams.showAsAction.action);
36 36
         item.setEnabled(buttonParams.enabled);
37
+        if (buttonParams.hasComponent()) {
38
+            item.setActionView(new TitleBarButtonComponent(parent.getContext(), buttonParams.componentName, buttonParams.componentProps));
39
+        }
37 40
         setIcon(item);
38 41
         setColor();
39 42
         setFont();

+ 25
- 0
android/app/src/main/java/com/reactnativenavigation/views/TitleBarButtonComponent.java View File

@@ -0,0 +1,25 @@
1
+package com.reactnativenavigation.views;
2
+
3
+import android.content.Context;
4
+import android.os.Bundle;
5
+import android.widget.FrameLayout;
6
+
7
+import com.reactnativenavigation.params.NavigationParams;
8
+import com.reactnativenavigation.views.utils.Constants;
9
+import com.reactnativenavigation.views.utils.ViewMeasurer;
10
+
11
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
12
+
13
+public class TitleBarButtonComponent extends ContentView {
14
+
15
+    public TitleBarButtonComponent(Context context, String componentName, Bundle passProps) {
16
+        super(context, componentName, NavigationParams.EMPTY, passProps);
17
+        setLayoutParams(new FrameLayout.LayoutParams(WRAP_CONTENT, Constants.TOOLBAR_BUTTON_SIZE));
18
+        setViewMeasurer(new ViewMeasurer() {
19
+            @Override
20
+            public int getMeasuredWidth(int widthMeasureSpec) {
21
+                return getChildCount() > 0 ? getChildAt(0).getWidth() : 0;
22
+            }
23
+        });
24
+    }
25
+}

+ 25
- 0
android/app/src/main/java/com/reactnativenavigation/views/TitleBarCustomComponentButton.java View File

@@ -0,0 +1,25 @@
1
+package com.reactnativenavigation.views;
2
+
3
+import android.content.Context;
4
+import android.support.annotation.Nullable;
5
+import android.view.Menu;
6
+import android.view.MenuItem;
7
+import android.view.View;
8
+
9
+import com.reactnativenavigation.params.NavigationParams;
10
+import com.reactnativenavigation.params.TitleBarButtonParams;
11
+
12
+class TitleBarCustomComponentButton extends TitleBarButton {
13
+    TitleBarCustomComponentButton(Menu menu, View parent, TitleBarButtonParams buttonParams, @Nullable String navigatorEventId) {
14
+        super(menu, parent, buttonParams, navigatorEventId);
15
+    }
16
+
17
+    @Override
18
+    MenuItem addToMenu(int index) {
19
+        throw new RuntimeException("Can't add custom component to menu");
20
+    }
21
+
22
+    View createView(Context context) {
23
+        return new ContentView(context, buttonParams.componentName, NavigationParams.EMPTY, buttonParams.componentProps);
24
+    }
25
+}

+ 0
- 156
android/app/src/main/java/com/reactnativenavigation/views/TitleBarSearchButton.java View File

@@ -1,156 +0,0 @@
1
-package com.reactnativenavigation.views;
2
-
3
-import android.app.Activity;
4
-import android.graphics.drawable.Drawable;
5
-import android.support.annotation.Nullable;
6
-import android.support.v4.view.MenuItemCompat;
7
-import android.support.v7.widget.SearchView;
8
-import android.support.v7.widget.Toolbar;
9
-import android.view.Menu;
10
-import android.view.MenuItem;
11
-import android.view.View;
12
-import android.view.ViewGroup;
13
-import android.widget.EditText;
14
-import android.widget.ImageButton;
15
-import android.widget.ImageView;
16
-
17
-import com.facebook.react.bridge.Arguments;
18
-import com.facebook.react.bridge.WritableMap;
19
-import com.reactnativenavigation.NavigationApplication;
20
-import com.reactnativenavigation.R;
21
-import com.reactnativenavigation.params.TitleBarButtonParams;
22
-import com.reactnativenavigation.utils.ReflectionUtils;
23
-import com.reactnativenavigation.utils.ViewUtils;
24
-
25
-class TitleBarSearchButton extends TitleBarButton implements SearchView.OnQueryTextListener, View.OnFocusChangeListener, View.OnClickListener {
26
-    static final String BUTTON_ID = "searchView";
27
-    private SearchView searchView;
28
-
29
-    TitleBarSearchButton(Menu menu, View parent, TitleBarButtonParams buttonParams, @Nullable String navigatorEventId) {
30
-        super(menu, parent, buttonParams, navigatorEventId);
31
-    }
32
-
33
-    MenuItem addToMenu(int index) {
34
-        ((Activity) parent.getContext()).getMenuInflater().inflate(R.menu.search_item, menu);
35
-        MenuItem item = menu.findItem(R.id.toolbar_action_search);
36
-        item.setOnMenuItemClickListener(this);
37
-        if (buttonParams.icon != null) {
38
-            item.setIcon(buttonParams.icon);
39
-        }
40
-        searchView = (SearchView) MenuItemCompat.getActionView(item);
41
-        searchView.setQueryHint(buttonParams.hint);
42
-        searchView.setOnQueryTextFocusChangeListener(this);
43
-        searchView.setOnQueryTextListener(this);
44
-        searchView.setOnSearchClickListener(this);
45
-        setColor();
46
-        return item;
47
-    }
48
-
49
-    private void setColor() {
50
-        EditText searchEditText = ViewUtils.findChildByClass(searchView, EditText.class);
51
-        if (searchEditText != null) {
52
-            if (buttonParams.color.hasColor()) {
53
-                searchEditText.setTextColor(buttonParams.color.getColor());
54
-                searchEditText.setHintTextColor(buttonParams.color.getColor());
55
-            }
56
-            colorCloseButton(searchEditText);
57
-            setImagePlateColor();
58
-        }
59
-    }
60
-
61
-    private void colorCloseButton(EditText searchEditText) {
62
-        ViewUtils.performOnChildren((ViewGroup) searchEditText.getParent(), new ViewUtils.PerformOnViewTask() {
63
-            @Override
64
-            public void runOnView(View view) {
65
-                if (view instanceof ImageView) {
66
-                    if (buttonParams.color.hasColor()) {
67
-                        ((ImageView) view).setColorFilter(buttonParams.color.getColor());
68
-                    }
69
-                }
70
-            }
71
-        });
72
-    }
73
-
74
-    private void setImagePlateColor() {
75
-        if (buttonParams.color.hasColor()) {
76
-            Object mSearchPlate = ReflectionUtils.getDeclaredField(searchView, "mSearchPlate");
77
-            if (mSearchPlate != null) {
78
-                Drawable background = ((View) mSearchPlate).getBackground();
79
-                if (background != null) {
80
-                    ViewUtils.tintDrawable(background, buttonParams.color.getColor(), true);
81
-                }
82
-            }
83
-        }
84
-    }
85
-
86
-    @Override
87
-    public boolean onMenuItemClick(MenuItem item) {
88
-        setupBackButtonAfterSearchViewIsExpended();
89
-        return false;
90
-    }
91
-
92
-    private void setupBackButtonAfterSearchViewIsExpended() {
93
-        ViewUtils.runOnPreDraw(searchView, new Runnable() {
94
-            @Override
95
-            public void run() {
96
-                Object backButton = ViewUtils.findChildByClass((ViewGroup) searchView.getParent(), ImageButton.class);
97
-                if (backButton != null) {
98
-                    setBackButtonClickListener((View) backButton);
99
-                    colorBackButton((ImageView) backButton);
100
-                }
101
-            }
102
-
103
-            private void colorBackButton(ImageView backButton) {
104
-                if (buttonParams.color.hasColor()) {
105
-                    ViewUtils.tintDrawable(backButton.getDrawable(), buttonParams.color.getColor(), true);
106
-                }
107
-            }
108
-
109
-            private void setBackButtonClickListener(View backButton) {
110
-                backButton.setOnClickListener(new View.OnClickListener() {
111
-                    @Override
112
-                    public void onClick(View v) {
113
-                        ((Toolbar) searchView.getParent()).collapseActionView();
114
-                        sendEvent("searchViewHidden");
115
-                    }
116
-                });
117
-            }
118
-        });
119
-    }
120
-
121
-    @Override
122
-    public boolean onQueryTextSubmit(String query) {
123
-        WritableMap arguments = Arguments.createMap();
124
-        arguments.putString("query", query);
125
-        sendEvent("searchQuerySubmit", arguments);
126
-        return false;
127
-    }
128
-
129
-    @Override
130
-    public boolean onQueryTextChange(String newText) {
131
-        WritableMap arguments = Arguments.createMap();
132
-        arguments.putString("query", newText);
133
-        sendEvent("searchQueryChange", arguments);
134
-        return false;
135
-    }
136
-
137
-    @Override
138
-    public void onFocusChange(View v, boolean hasFocus) {
139
-        WritableMap arguments = Arguments.createMap();
140
-        arguments.putBoolean("hasFocus", hasFocus);
141
-        sendEvent("searchFocusChange", arguments);
142
-    }
143
-
144
-    @Override
145
-    public void onClick(View v) {
146
-        sendEvent("searchViewShown");
147
-    }
148
-
149
-    private void sendEvent(String eventId, WritableMap arguments) {
150
-        NavigationApplication.instance.getEventEmitter().sendNavigatorEvent(eventId, navigatorEventId, arguments);
151
-    }
152
-
153
-    private void sendEvent(String eventId) {
154
-        NavigationApplication.instance.getEventEmitter().sendNavigatorEvent(eventId, navigatorEventId);
155
-    }
156
-}

+ 1
- 0
android/app/src/main/java/com/reactnativenavigation/views/utils/Constants.java View File

@@ -4,4 +4,5 @@ import com.reactnativenavigation.utils.ViewUtils;
4 4
 
5 5
 public class Constants {
6 6
     public static final int BOTTOM_TABS_HEIGHT = (int) ViewUtils.convertDpToPixel(56);
7
+    public static final int TOOLBAR_BUTTON_SIZE = (int) ViewUtils.convertDpToPixel(48);
7 8
 }