From b0fa3228a77d89d6736da6fcae5dd32f74f3052c Mon Sep 17 00:00:00 2001 From: Dulmandakh Date: Fri, 6 Apr 2018 15:57:09 -0700 Subject: [PATCH] Implement Image.defaultSource property on Android Summary: This pull request implements Image.defaultSource property on Android, using Fresco (http://frescolib.org/docs/placeholder-failure-retry.html), which will show placeholder image (local asset) while loading remote image. Implementation code is almost same with loadingIndicatorSource, but without rotation. This requires release or production to bundle local images in an APK file. This provides feature parity with iOS. Set Image.defaultSource on Android, and will show it while loading Image.source. ```JSX ')} source={{uri: ''}} style={{ height: 300, width: 300 }} /> ``` [ANDROID] [FEATURE] [IMAGE] - Image.defaultSource will show local image as placeholder while loading remote Image.source. Closes https://github.com/facebook/react-native/pull/18588 Differential Revision: D7540489 Pulled By: himabindugadupudi fbshipit-source-id: 908ceb659b3416e517bba64c76a31879d965ec09 --- Libraries/Image/Image.android.js | 15 +++++++++++++++ .../react/views/image/ReactImageManager.java | 6 ++++++ .../react/views/image/ReactImageView.java | 10 ++++++++++ 3 files changed, 31 insertions(+) diff --git a/Libraries/Image/Image.android.js b/Libraries/Image/Image.android.js index 4e218487c..870b31cd8 100644 --- a/Libraries/Image/Image.android.js +++ b/Libraries/Image/Image.android.js @@ -74,6 +74,10 @@ var Image = createReactClass({ * See https://facebook.github.io/react-native/docs/image.html#blurradius */ blurRadius: PropTypes.number, + /** + * See https://facebook.github.io/react-native/docs/image.html#defaultsource + */ + defaultSource: PropTypes.number, /** * See https://facebook.github.io/react-native/docs/image.html#loadingindicatorsource */ @@ -197,6 +201,7 @@ var Image = createReactClass({ render: function() { const source = resolveAssetSource(this.props.source); + const defaultSource = resolveAssetSource(this.props.defaultSource); const loadingIndicatorSource = resolveAssetSource( this.props.loadingIndicatorSource, ); @@ -220,6 +225,12 @@ var Image = createReactClass({ ); } + if (this.props.defaultSource && this.props.loadingIndicatorSource) { + throw new Error( + 'The component cannot have defaultSource and loadingIndicatorSource at the same time. Please use either defaultSource or loadingIndicatorSource.', + ); + } + if (source && (source.uri || Array.isArray(source))) { let style; let sources; @@ -243,6 +254,9 @@ var Image = createReactClass({ ), src: sources, headers: source.headers, + defaultSrc: defaultSource + ? defaultSource.uri + : null, loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null, @@ -268,6 +282,7 @@ var cfg = { nativeOnly: { src: true, headers: true, + defaultSrc: true, loadingIndicatorSrc: true, shouldNotifyLoadEvents: true, }, diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java index 938524d30..2565e2294 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.java @@ -88,6 +88,12 @@ public class ReactImageManager extends SimpleViewManager { view.setBlurRadius(blurRadius); } + // In JS this is Image.props.defaultSource + @ReactProp(name = "defaultSrc") + public void setDefaultSource(ReactImageView view, @Nullable String source) { + view.setDefaultSource(source); + } + // In JS this is Image.props.loadingIndicatorSource.uri @ReactProp(name = "loadingIndicatorSrc") public void setLoadingIndicatorSource(ReactImageView view, @Nullable String source) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java index 9ab9c8884..cb294cbb9 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageView.java @@ -184,6 +184,7 @@ public class ReactImageView extends GenericDraweeView { private @Nullable ImageSource mImageSource; private @Nullable ImageSource mCachedImageSource; + private @Nullable Drawable mDefaultImageDrawable; private @Nullable Drawable mLoadingImageDrawable; private @Nullable RoundedColorDrawable mBackgroundImageDrawable; private int mBackgroundColor = 0x00000000; @@ -369,6 +370,11 @@ public class ReactImageView extends GenericDraweeView { mIsDirty = true; } + public void setDefaultSource(@Nullable String name) { + mDefaultImageDrawable = ResourceDrawableIdHelper.getInstance().getResourceDrawable(getContext(), name); + mIsDirty = true; + } + public void setLoadingIndicatorSource(@Nullable String name) { Drawable drawable = ResourceDrawableIdHelper.getInstance().getResourceDrawable(getContext(), name); mLoadingImageDrawable = @@ -428,6 +434,10 @@ public class ReactImageView extends GenericDraweeView { GenericDraweeHierarchy hierarchy = getHierarchy(); hierarchy.setActualImageScaleType(mScaleType); + if (mDefaultImageDrawable != null) { + hierarchy.setPlaceholderImage(mDefaultImageDrawable, ScalingUtils.ScaleType.CENTER); + } + if (mLoadingImageDrawable != null) { hierarchy.setPlaceholderImage(mLoadingImageDrawable, ScalingUtils.ScaleType.CENTER); }