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 4e218487c9b505..870b31cd8f92cb 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 938524d3012156..2565e2294ef1c6 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 void setBlurRadius(ReactImageView view, float blurRadius) { 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 9ab9c8884e800c..cb294cbb93d7eb 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 CloseableReference process(Bitmap source, PlatformBitmapFactory b 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 void setSource(@Nullable ReadableArray sources) { 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 void maybeUpdateView() { GenericDraweeHierarchy hierarchy = getHierarchy(); hierarchy.setActualImageScaleType(mScaleType); + if (mDefaultImageDrawable != null) { + hierarchy.setPlaceholderImage(mDefaultImageDrawable, ScalingUtils.ScaleType.CENTER); + } + if (mLoadingImageDrawable != null) { hierarchy.setPlaceholderImage(mLoadingImageDrawable, ScalingUtils.ScaleType.CENTER); }