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
This commit is contained in:
Ahmed El-Helw 2016-01-28 17:06:17 -08:00
parent 74c72111f1
commit d854a17d2a
5 changed files with 69 additions and 13 deletions

View File

@ -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.

View File

@ -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);
}

View File

@ -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()),

View File

@ -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 {

View File

@ -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();