mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-05-27 12:41:49 +00:00
Merge pull request #94 from silverspace/android_blank_initial_render
Android: SVG Images not rendering the first time a view is displayed
This commit is contained in:
@@ -16,12 +16,10 @@ import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import com.facebook.common.executors.UiThreadImmediateExecutorService;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
||||
import com.facebook.imagepipeline.image.CloseableBitmap;
|
||||
@@ -31,6 +29,9 @@ import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -44,7 +45,7 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
private String mW;
|
||||
private String mH;
|
||||
private Uri mUri;
|
||||
private boolean mLoading;
|
||||
private AtomicBoolean mLoading = new AtomicBoolean(false);
|
||||
|
||||
@ReactProp(name = "x")
|
||||
public void setX(String x) {
|
||||
@@ -86,13 +87,14 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
|
||||
@Override
|
||||
public void draw(final Canvas canvas, final Paint paint, final float opacity) {
|
||||
final ImageRequest request = ImageRequestBuilder.newBuilderWithSource(mUri).build();
|
||||
final boolean inMemoryCache = Fresco.getImagePipeline().isInBitmapMemoryCache(request);
|
||||
if (!mLoading.get()) {
|
||||
final ImageRequest request = ImageRequestBuilder.newBuilderWithSource(mUri).build();
|
||||
|
||||
if (inMemoryCache) {
|
||||
tryRender(request, canvas, paint, opacity * mOpacity);
|
||||
} else if (!mLoading) {
|
||||
loadBitmap(request, canvas, paint);
|
||||
if (Fresco.getImagePipeline().isInBitmapMemoryCache(request)) {
|
||||
tryRender(request, canvas, paint, opacity * mOpacity);
|
||||
} else {
|
||||
loadBitmap(request, canvas, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,8 +108,10 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
if (bitmap != null) {
|
||||
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
||||
paint.reset();
|
||||
mLoading = false;
|
||||
mLoading.set(false);
|
||||
|
||||
getSvgShadowNode().drawChildren(canvas, paint);
|
||||
getSvgShadowNode().invalidateView(getRect());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +119,7 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
public void onFailureImpl(DataSource dataSource) {
|
||||
// No cleanup required here.
|
||||
// TODO: more details about this failure
|
||||
mLoading = false;
|
||||
mLoading.set(false);
|
||||
FLog.w(ReactConstants.TAG, dataSource.getFailureCause(), "RNSVG: fetchDecodedImage failed!");
|
||||
}
|
||||
},
|
||||
@@ -123,18 +127,25 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
);
|
||||
}
|
||||
|
||||
private void doRender(@Nonnull final Canvas canvas, @Nonnull final Paint paint, @Nonnull final Bitmap bitmap, final float opacity) {
|
||||
final int count = saveAndSetupCanvas(canvas);
|
||||
|
||||
clip(canvas, paint);
|
||||
@Nonnull
|
||||
private Rect getRect() {
|
||||
float x = PropHelper.fromPercentageToFloat(mX, mCanvasWidth, 0, mScale);
|
||||
float y = PropHelper.fromPercentageToFloat(mY, mCanvasHeight, 0, mScale);
|
||||
float w = PropHelper.fromPercentageToFloat(mW, mCanvasWidth, 0, mScale);
|
||||
float h = PropHelper.fromPercentageToFloat(mH, mCanvasHeight, 0, mScale);
|
||||
|
||||
return new Rect((int) x, (int) y, (int) (x + w), (int) (y + h));
|
||||
}
|
||||
|
||||
private void doRender(@Nonnull final Canvas canvas, @Nonnull final Paint paint, @Nonnull final Bitmap bitmap, final float opacity) {
|
||||
final int count = saveAndSetupCanvas(canvas);
|
||||
|
||||
clip(canvas, paint);
|
||||
|
||||
Paint alphaPaint = new Paint();
|
||||
alphaPaint.setAlpha((int) (opacity * 255));
|
||||
|
||||
canvas.drawBitmap(bitmap, null, new Rect((int) x, (int) y, (int) (x + w), (int) (y + h)), alphaPaint);
|
||||
canvas.drawBitmap(bitmap, null, getRect(), alphaPaint);
|
||||
|
||||
restoreCanvas(canvas, count);
|
||||
markUpdateSeen();
|
||||
|
||||
@@ -310,7 +310,9 @@ public class RNSVGPathShadowNode extends RNSVGVirtualNode {
|
||||
mPath.computeBounds(box, true);
|
||||
}
|
||||
PropHelper.RNSVGBrush brush = getSvgShadowNode().getDefinedBrush(colors.getString(1));
|
||||
brush.setupPaint(paint, box, mScale, opacity);
|
||||
if (brush != null) {
|
||||
brush.setupPaint(paint, box, mScale, opacity);
|
||||
}
|
||||
} else {
|
||||
// TODO: Support pattern.
|
||||
FLog.w(ReactConstants.TAG, "RNSVG: Color type " + colorType + " not supported!");
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewGroupManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* ViewManager for RNSVGSvgView React views. Renders as a {@link RNSVGSvgView} and handles
|
||||
* invalidating the native view on shadow view updates happening in the underlying tree.
|
||||
@@ -24,6 +25,7 @@ import java.util.ArrayList;
|
||||
public class RNSVGSvgViewManager extends ViewGroupManager<RNSVGSvgView> {
|
||||
|
||||
private static final String REACT_CLASS = "RNSVGSvgView";
|
||||
private RNSVGSvgView svgView = null;
|
||||
|
||||
// TODO: use an ArrayList to connect RNSVGSvgViewShadowNode with RNSVGSvgView, not sure if there will be a race condition.
|
||||
// TODO: find a better way to replace this
|
||||
@@ -34,9 +36,14 @@ public class RNSVGSvgViewManager extends ViewGroupManager<RNSVGSvgView> {
|
||||
return REACT_CLASS;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RNSVGSvgView getSvgView() {
|
||||
return this.svgView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RNSVGSvgViewShadowNode createShadowNodeInstance() {
|
||||
RNSVGSvgViewShadowNode node = new RNSVGSvgViewShadowNode();
|
||||
RNSVGSvgViewShadowNode node = new RNSVGSvgViewShadowNode(this);
|
||||
SvgShadowNodes.add(node);
|
||||
return node;
|
||||
}
|
||||
@@ -50,7 +57,8 @@ public class RNSVGSvgViewManager extends ViewGroupManager<RNSVGSvgView> {
|
||||
protected RNSVGSvgView createViewInstance(ThemedReactContext reactContext) {
|
||||
RNSVGSvgViewShadowNode shadowNode = SvgShadowNodes.get(0);
|
||||
SvgShadowNodes.remove(0);
|
||||
return new RNSVGSvgView(reactContext, shadowNode);
|
||||
this.svgView = new RNSVGSvgView(reactContext, shadowNode);
|
||||
return this.svgView;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,15 +13,19 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.util.Log;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
import com.facebook.react.uimanager.UIViewOperationQueue;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Shadow node for RNSVG virtual tree root - RNSVGSvgView
|
||||
*/
|
||||
@@ -32,6 +36,13 @@ public class RNSVGSvgViewShadowNode extends LayoutShadowNode {
|
||||
private static final Map<String, RNSVGVirtualNode> mDefinedTemplates = new HashMap<>();
|
||||
private static final Map<String, PropHelper.RNSVGBrush> mDefinedBrushes = new HashMap<>();
|
||||
|
||||
@Nonnull private final RNSVGSvgViewManager viewManager;
|
||||
|
||||
public RNSVGSvgViewShadowNode(@Nonnull final RNSVGSvgViewManager viewManager) {
|
||||
super();
|
||||
this.viewManager = viewManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) {
|
||||
super.onCollectExtraUpdates(uiUpdater);
|
||||
@@ -54,7 +65,7 @@ public class RNSVGSvgViewShadowNode extends LayoutShadowNode {
|
||||
* Draw all of the child nodes of this root node
|
||||
*
|
||||
* This method is synchronized since
|
||||
* {@link com.horcrux.svg.RNSVGImageShadowNode#loadImage(ImageRequest, Canvas, Paint)} calls it
|
||||
* {@link com.horcrux.svg.RNSVGImageShadowNode#loadBitmap(ImageRequest, Canvas, Paint)} calls it
|
||||
* asynchronously after images have loaded and are ready to be drawn.
|
||||
*
|
||||
* @param canvas
|
||||
@@ -77,6 +88,16 @@ public class RNSVGSvgViewShadowNode extends LayoutShadowNode {
|
||||
}
|
||||
}
|
||||
|
||||
protected void invalidateView(@Nonnull final Rect dirtyRect) {
|
||||
final RNSVGSvgView svgView = this.viewManager.getSvgView();
|
||||
if (svgView != null) {
|
||||
final View rootView = svgView.getRootView();
|
||||
if (rootView != null) {
|
||||
rootView.invalidate(dirtyRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void enableTouchEvents() {
|
||||
if (!mResponsible) {
|
||||
mResponsible = true;
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
package com.horcrux.svg;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
@@ -18,16 +16,16 @@ import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Base class for RNSVGView virtual nodes: {@link RNSVGGroupShadowNode}, {@link RNSVGPathShadowNode} and
|
||||
@@ -81,8 +79,7 @@ public abstract class RNSVGVirtualNode extends LayoutShadowNode {
|
||||
* @param canvas the canvas to set up
|
||||
*/
|
||||
protected final int saveAndSetupCanvas(Canvas canvas) {
|
||||
int count = canvas.getSaveCount();
|
||||
canvas.save();
|
||||
final int count = canvas.save();
|
||||
if (mMatrix != null) {
|
||||
canvas.concat(mMatrix);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user