From a797be6ffdd8fd9107cd8654b0c0d7c46ee2c6bb Mon Sep 17 00:00:00 2001 From: Alexander Blom Date: Fri, 6 Nov 2015 02:33:32 -0800 Subject: [PATCH] Support 'color' attribute in ProgressBarAndroid Differential Revision: D2625690 fb-gh-sync-id: 34ef656be7ce3304add3fae3e697c6b39b866af1 --- .../ProgressBarAndroidExample.android.js | 4 ++ .../ProgressBarAndroid.android.js | 14 ++-- .../progressbar/ProgressBarContainerView.java | 68 +++++++++++++++++++ .../ReactProgressBarViewManager.java | 41 +++++------ 4 files changed, 99 insertions(+), 28 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ProgressBarContainerView.java diff --git a/Examples/UIExplorer/ProgressBarAndroidExample.android.js b/Examples/UIExplorer/ProgressBarAndroidExample.android.js index 040ed00fd..2c172198d 100644 --- a/Examples/UIExplorer/ProgressBarAndroidExample.android.js +++ b/Examples/UIExplorer/ProgressBarAndroidExample.android.js @@ -54,6 +54,10 @@ var ProgressBarAndroidExample = React.createClass({ + + + + ); }, diff --git a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js index 307a2bad4..9a07db002 100644 --- a/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js +++ b/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.android.js @@ -15,7 +15,7 @@ var React = require('React'); var ReactPropTypes = require('ReactPropTypes'); var ReactNativeViewAttributes = require('ReactNativeViewAttributes'); -var createReactNativeComponentClass = require('createReactNativeComponentClass'); +var requireNativeComponent = require('requireNativeComponent'); var STYLE_ATTRIBUTES = [ 'Horizontal', @@ -62,6 +62,10 @@ var ProgressBarAndroid = React.createClass({ * - LargeInverse */ styleAttr: ReactPropTypes.oneOf(STYLE_ATTRIBUTES), + /** + * Color of the progress bar. + */ + color: ReactPropTypes.string, /** * Used to locate this view in end-to-end tests. */ @@ -81,12 +85,6 @@ var ProgressBarAndroid = React.createClass({ }, }); -var AndroidProgressBar = createReactNativeComponentClass({ - validAttributes: { - ...ReactNativeViewAttributes.UIView, - styleAttr: true, - }, - uiViewClassName: 'AndroidProgressBar', -}); +var AndroidProgressBar = requireNativeComponent('AndroidProgressBar', ProgressBarAndroid); module.exports = ProgressBarAndroid; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ProgressBarContainerView.java b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ProgressBarContainerView.java new file mode 100644 index 000000000..08c11902f --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ProgressBarContainerView.java @@ -0,0 +1,68 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +package com.facebook.react.views.progressbar; + +import javax.annotation.Nullable; + +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ProgressBar; + +import com.facebook.react.bridge.JSApplicationIllegalArgumentException; + +/** + * Controls an enclosing ProgressBar. Exists so that the ProgressBar can be recreated if + * the style would change. + */ +class ProgressBarContainerView extends FrameLayout { + private @Nullable Integer mColor; + private @Nullable ProgressBar mProgressBar; + + public ProgressBarContainerView(Context context) { + super(context); + } + + public void setStyle(@Nullable String styleName) { + int style = ReactProgressBarViewManager.getStyleFromString(styleName); + mProgressBar = new ProgressBar(getContext(), null, style); + removeAllViews(); + addView( + mProgressBar, + new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT)); + } + + public void setColor(@Nullable Integer color) { + this.mColor = color; + } + + public void apply() { + if (mProgressBar == null) { + throw new JSApplicationIllegalArgumentException("setStyle() not called"); + } + setColor(mProgressBar); + } + + private void setColor(ProgressBar progressBar) { + Drawable drawable; + if (progressBar.isIndeterminate()) { + drawable = progressBar.getIndeterminateDrawable(); + } else { + drawable = progressBar.getProgressDrawable(); + } + + if (drawable == null) { + return; + } + + if (mColor != null) { + drawable.setColorFilter(mColor, PorterDuff.Mode.SRC_IN); + } else { + drawable.clearColorFilter(); + } + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ReactProgressBarViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ReactProgressBarViewManager.java index 191ce191d..0a26fa49c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ReactProgressBarViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/progressbar/ReactProgressBarViewManager.java @@ -11,23 +11,20 @@ package com.facebook.react.views.progressbar; import javax.annotation.Nullable; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.ProgressBar; - import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.uimanager.BaseViewManager; import com.facebook.react.uimanager.ReactProp; import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.ViewProps; /** - * Manages instances of ProgressBar. ProgressBar is wrapped in a FrameLayout because the style of - * the ProgressBar can only be set in the constructor; whenever the style of a ProgressBar changes, - * we have to drop the existing ProgressBar (if there is one) and create a new one with the style - * given. + * Manages instances of ProgressBar. ProgressBar is wrapped in a ProgressBarContainerView because + * the style of the ProgressBar can only be set in the constructor; whenever the style of a + * ProgressBar changes, we have to drop the existing ProgressBar (if there is one) and create a new + * one with the style given. */ public class ReactProgressBarViewManager extends - BaseViewManager { + BaseViewManager { /* package */ static final String PROP_STYLE = "styleAttr"; @@ -40,19 +37,18 @@ public class ReactProgressBarViewManager extends } @Override - protected FrameLayout createViewInstance(ThemedReactContext context) { - return new FrameLayout(context); + protected ProgressBarContainerView createViewInstance(ThemedReactContext context) { + return new ProgressBarContainerView(context); } @ReactProp(name = PROP_STYLE) - public void setStyle(FrameLayout view, @Nullable String styleName) { - final int style = getStyleFromString(styleName); - view.removeAllViews(); - view.addView( - new ProgressBar(view.getContext(), null, style), - new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT)); + public void setStyle(ProgressBarContainerView view, @Nullable String styleName) { + view.setStyle(styleName); + } + + @ReactProp(name = ViewProps.COLOR, customType = "Color") + public void setColor(ProgressBarContainerView view, @Nullable Integer color) { + view.setColor(color); } @Override @@ -66,10 +62,15 @@ public class ReactProgressBarViewManager extends } @Override - public void updateExtraData(FrameLayout root, Object extraData) { + public void updateExtraData(ProgressBarContainerView root, Object extraData) { // do nothing } + @Override + protected void onAfterUpdateTransaction(ProgressBarContainerView view) { + view.apply(); + } + /* package */ static int getStyleFromString(@Nullable String styleStr) { if (styleStr == null) { throw new JSApplicationIllegalArgumentException(