From d854a17d2ada5b5bab1d5948654b7d051b9ed067 Mon Sep 17 00:00:00 2001 From: Ahmed El-Helw Date: Thu, 28 Jan 2016 17:06:17 -0800 Subject: [PATCH] Support fade for remote images in React with nodes. Summary: Support fade for DrawImageWithPipeline so that images are faded in when they are remotely fetched. Differential Revision: D2804997 --- .../react/flat/AbstractDrawCommand.java | 4 ++ .../com/facebook/react/flat/DrawImage.java | 26 +++++++------ .../react/flat/DrawImageWithDrawee.java | 8 ++++ .../react/flat/DrawImageWithPipeline.java | 39 ++++++++++++++++++- .../com/facebook/react/flat/RCTImageView.java | 5 +++ 5 files changed, 69 insertions(+), 13 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/AbstractDrawCommand.java b/ReactAndroid/src/main/java/com/facebook/react/flat/AbstractDrawCommand.java index bb8b5c659..24961d92b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/AbstractDrawCommand.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/AbstractDrawCommand.java @@ -32,6 +32,7 @@ import android.graphics.Canvas; @Override public final void draw(FlatViewGroup parent, Canvas canvas) { + onPreDraw(parent, canvas); if (shouldClip()) { canvas.save(); canvas.clipRect(mClipLeft, mClipTop, mClipRight, mClipBottom); @@ -42,6 +43,9 @@ import android.graphics.Canvas; } } + protected void onPreDraw(FlatViewGroup parent, Canvas canvas) { + } + /** * Updates boundaries of the AbstractDrawCommand and freezes it. * Will return a frozen copy if the current AbstractDrawCommand cannot be mutated. diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImage.java b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImage.java index 40710c9c5..4d3de822c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImage.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImage.java @@ -22,42 +22,44 @@ import com.facebook.imagepipeline.request.ImageRequest; * Returns true if an image source was assigned to the DrawImage. * A DrawImage with no source will not draw anything. */ - public boolean hasImageRequest(); + boolean hasImageRequest(); /** * Assigns a new image request to the DrawImage, or null to clear the image request. */ - public void setImageRequest(@Nullable ImageRequest imageRequest); + void setImageRequest(@Nullable ImageRequest imageRequest); /** * Assigns a tint color to apply to the image drawn. */ - public void setTintColor(int tintColor); + void setTintColor(int tintColor); /** * Assigns a scale type to draw to the image with. */ - public void setScaleType(ScaleType scaleType); + void setScaleType(ScaleType scaleType); /** * Returns a scale type to draw to the image with. */ - public ScaleType getScaleType(); + ScaleType getScaleType(); /** * React tag used for dispatching ImageLoadEvents, or 0 to ignore events. */ - public void setReactTag(int reactTag); + void setReactTag(int reactTag); - public void setBorderWidth(float borderWidth); + void setBorderWidth(float borderWidth); - public float getBorderWidth(); + float getBorderWidth(); - public void setBorderRadius(float borderRadius); + void setBorderRadius(float borderRadius); - public float getBorderRadius(); + float getBorderRadius(); - public void setBorderColor(int borderColor); + void setBorderColor(int borderColor); - public int getBorderColor(); + int getBorderColor(); + + void setFadeDuration(int fadeDuration); } diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithDrawee.java b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithDrawee.java index c52cb1cdb..a317c779f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithDrawee.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithDrawee.java @@ -24,6 +24,7 @@ import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.infer.annotation.Assertions; import com.facebook.react.views.image.ImageLoadEvent; import com.facebook.react.views.image.ImageResizeMode; +import com.facebook.react.views.image.ReactImageView; /** * DrawImageWithDrawee is DrawCommand that can draw a local or remote image. @@ -39,6 +40,7 @@ import com.facebook.react.views.image.ImageResizeMode; private float mBorderRadius; private int mBorderColor; private int mReactTag; + private int mFadeDuration = ReactImageView.REMOTE_IMAGE_FADE_DURATION_MS; private @Nullable FlatViewGroup.InvalidateCallback mCallback; @Override @@ -104,6 +106,11 @@ import com.facebook.react.views.image.ImageResizeMode; return mBorderColor; } + @Override + public void setFadeDuration(int fadeDuration) { + mFadeDuration = fadeDuration; + } + @Override public void setReactTag(int reactTag) { mReactTag = reactTag; @@ -138,6 +145,7 @@ import com.facebook.react.views.image.ImageResizeMode; hierarchy.setActualImageScaleType(mScaleType); hierarchy.setActualImageColorFilter(mColorFilter); + hierarchy.setFadeDuration(mFadeDuration); hierarchy.getTopLevelDrawable().setBounds( Math.round(getLeft()), diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java index 7a987fa88..c186f8f04 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/DrawImageWithPipeline.java @@ -25,6 +25,7 @@ import com.facebook.drawee.drawable.ScalingUtils.ScaleType; import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.infer.annotation.Assertions; import com.facebook.react.views.image.ImageResizeMode; +import com.facebook.react.views.image.ReactImageView; /** * DrawImageWithPipeline is DrawCommand that can draw a local or remote image. @@ -46,6 +47,10 @@ import com.facebook.react.views.image.ImageResizeMode; private boolean mForceClip; private int mReactTag; + // variables used for fading the image in + private long mFirstDrawTime = -1; + private int mFadeDuration = ReactImageView.REMOTE_IMAGE_FADE_DURATION_MS; + @Override public boolean hasImageRequest() { return mRequestHelper != null; @@ -86,6 +91,39 @@ import com.facebook.react.views.image.ImageResizeMode; mReactTag = reactTag; } + @Override + public void setFadeDuration(int fadeDuration) { + mFadeDuration = fadeDuration; + } + + @Override + protected void onPreDraw(FlatViewGroup parent, Canvas canvas) { + super.onPreDraw(parent, canvas); + + Bitmap bitmap = Assertions.assumeNotNull(mRequestHelper).getBitmap(); + if (bitmap == null) { + mFirstDrawTime = 0; + } else { + if (mFirstDrawTime == -1) { + PAINT.setAlpha(255); + } else { + long currentDrawingTime = parent.getDrawingTime(); + if (mFirstDrawTime == 0) { + mFirstDrawTime = currentDrawingTime - 16; // -16 to skip one draw cycle, so that we start + // with a non-zero alpha (otherwise, we waste 16ms doing nothing during this cycle). + } + int alpha = (int) (255.0f * (1.0f * (currentDrawingTime - mFirstDrawTime) / mFadeDuration)); + if (alpha >= 255) { + mFirstDrawTime = -1; + alpha = 255; + } else { + Assertions.assumeNotNull(mCallback).invalidate(); + } + PAINT.setAlpha(alpha); + } + } + } + @Override protected void onDraw(Canvas canvas) { Bitmap bitmap = Assertions.assumeNotNull(mRequestHelper).getBitmap(); @@ -184,7 +222,6 @@ import com.facebook.react.views.image.ImageResizeMode; final float scale; if (mScaleType == ScaleType.CENTER_INSIDE) { - final float ratio; if (containerWidth >= imageWidth && containerHeight >= imageHeight) { scale = 1.0f; } else { diff --git a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTImageView.java b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTImageView.java index 75d3abdb8..729a4b5f2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/flat/RCTImageView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/flat/RCTImageView.java @@ -127,6 +127,11 @@ import com.facebook.react.views.image.ImageResizeMode; } } + @ReactProp(name = "fadeDuration") + public void setFadeDuration(int durationMs) { + getMutableDrawImage().setFadeDuration(durationMs); + } + private T getMutableDrawImage() { if (mDrawImage.isFrozen()) { mDrawImage = (T) mDrawImage.mutableCopy();