From 66717d802b9d42c5bff8ce1d7b6e5998a1591514 Mon Sep 17 00:00:00 2001 From: Charles Marsh Date: Thu, 22 Oct 2015 04:40:21 -0700 Subject: [PATCH] Allow for styling of ToolbarAndroid's overflow icon Summary: Fixes #2858. Here's a screenshot of the custom overflow icon in action: overflow Closes https://github.com/facebook/react-native/pull/3497 Reviewed By: svcscm Differential Revision: D2559787 Pulled By: foghina fb-gh-sync-id: f188711ec094af3fa307722527f22aefff722e64 --- .../ToolbarAndroidExample.android.js | 6 +++ .../ToolbarAndroid/ToolbarAndroid.android.js | 8 ++++ .../react/views/toolbar/ReactToolbar.java | 43 ++++++++++++++++++- .../views/toolbar/ReactToolbarManager.java | 5 +++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/Examples/UIExplorer/ToolbarAndroidExample.android.js b/Examples/UIExplorer/ToolbarAndroidExample.android.js index c621296d91..769737a33e 100644 --- a/Examples/UIExplorer/ToolbarAndroidExample.android.js +++ b/Examples/UIExplorer/ToolbarAndroidExample.android.js @@ -101,6 +101,12 @@ var ToolbarAndroidExample = React.createClass({ title="Bunny and Hawk" style={styles.toolbar} /> + + + ); }, diff --git a/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js b/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js index 5692c97714..dcaed6b0ce 100644 --- a/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js +++ b/Libraries/Components/ToolbarAndroid/ToolbarAndroid.android.js @@ -103,6 +103,10 @@ var ToolbarAndroid = React.createClass({ * Callback called when the icon is selected. */ onIconClicked: ReactPropTypes.func, + /** + * Sets the overflow icon. + */ + overflowIcon: optionalImageSource, /** * Sets the toolbar subtitle. */ @@ -135,6 +139,9 @@ var ToolbarAndroid = React.createClass({ if (this.props.navIcon) { nativeProps.navIcon = resolveAssetSource(this.props.navIcon); } + if (this.props.overflowIcon) { + nativeProps.overflowIcon = resolveAssetSource(this.props.overflowIcon); + } if (this.props.actions) { nativeProps.actions = []; for (var i = 0; i < this.props.actions.length; i++) { @@ -169,6 +176,7 @@ var toolbarAttributes = { actions: true, logo: true, navIcon: true, + overflowIcon: true, subtitle: true, subtitleColor: true, title: true, diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbar.java b/ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbar.java index 91741c1c6f..5fe30921a6 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbar.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbar.java @@ -6,6 +6,7 @@ import javax.annotation.Nullable; import android.content.Context; import android.graphics.drawable.Animatable; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.support.v7.widget.Toolbar; import android.view.Menu; @@ -36,6 +37,7 @@ public class ReactToolbar extends Toolbar { private final DraweeHolder mLogoHolder; private final DraweeHolder mNavIconHolder; + private final DraweeHolder mOverflowIconHolder; private final MultiDraweeHolder mActionsHolder = new MultiDraweeHolder<>(); @@ -69,6 +71,21 @@ public class ReactToolbar extends Toolbar { } }; + private final ControllerListener mOverflowIconControllerListener = + new BaseControllerListener() { + @Override + public void onFinalImageSet( + String id, + @Nullable final ImageInfo imageInfo, + @Nullable Animatable animatable) { + if (imageInfo != null) { + final DrawableWithIntrinsicSize overflowIconDrawable = + new DrawableWithIntrinsicSize(mOverflowIconHolder.getTopLevelDrawable(), imageInfo); + setOverflowIcon(overflowIconDrawable); + } + } + }; + private static class ActionIconControllerListener extends BaseControllerListener { private final MenuItem mItem; private final DraweeHolder mHolder; @@ -94,6 +111,7 @@ public class ReactToolbar extends Toolbar { mLogoHolder = DraweeHolder.create(createDraweeHierarchy(), context); mNavIconHolder = DraweeHolder.create(createDraweeHierarchy(), context); + mOverflowIconHolder = DraweeHolder.create(createDraweeHierarchy(), context); } private final Runnable mLayoutRunnable = new Runnable() { @@ -136,19 +154,20 @@ public class ReactToolbar extends Toolbar { @Override public void onFinishTemporaryDetach() { super.onFinishTemporaryDetach(); - mLogoHolder.onAttach(); - mNavIconHolder.onAttach(); + attachDraweeHolders(); } private void detachDraweeHolders() { mLogoHolder.onDetach(); mNavIconHolder.onDetach(); + mOverflowIconHolder.onDetach(); mActionsHolder.onDetach(); } private void attachDraweeHolders() { mLogoHolder.onAttach(); mNavIconHolder.onAttach(); + mOverflowIconHolder.onAttach(); mActionsHolder.onAttach(); } @@ -184,6 +203,22 @@ public class ReactToolbar extends Toolbar { } } + /* package */ void setOverflowIconSource(@Nullable ReadableMap source) { + String uri = source != null ? source.getString("uri") : null; + if (uri == null) { + setOverflowIcon(null); + } else if (uri.startsWith("http://") || uri.startsWith("https://")) { + DraweeController controller = Fresco.newDraweeControllerBuilder() + .setUri(Uri.parse(uri)) + .setControllerListener(mOverflowIconControllerListener) + .setOldController(mOverflowIconHolder.getController()) + .build(); + mOverflowIconHolder.setController(controller); + } else { + setOverflowIcon(getDrawableByName(uri)); + } + } + /* package */ void setActions(@Nullable ReadableArray actions) { Menu menu = getMenu(); menu.clear(); @@ -247,4 +282,8 @@ public class ReactToolbar extends Toolbar { getContext().getPackageName()); } + private Drawable getDrawableByName(String name) { + return getResources().getDrawable(getDrawableResourceByName(name)); + } + } diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbarManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbarManager.java index 93fe8a61d6..de1038a980 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbarManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/toolbar/ReactToolbarManager.java @@ -59,6 +59,11 @@ public class ReactToolbarManager extends ViewGroupManager { view.setNavIconSource(navIcon); } + @ReactProp(name = "overflowIcon") + public void setOverflowIcon(ReactToolbar view, @Nullable ReadableMap overflowIcon) { + view.setOverflowIconSource(overflowIcon); + } + @ReactProp(name = "subtitle") public void setSubtitle(ReactToolbar view, @Nullable String subtitle) { view.setSubtitle(subtitle);