mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-02-09 22:50:21 +08:00
Add onLoadX support on Android
Summary: ~~This is a WIP, just finished the first bit and wanted to get some feedback to see if this approach seems appropriate, as I haven't done a lot of Android development.~~ Looks ready for review now. Closes https://github.com/facebook/react-native/pull/3791 Reviewed By: svcscm Differential Revision: D2672262 Pulled By: mkonicek fb-gh-sync-id: 1e8f1cc6658fb719a68f7da455f30a7c9b1db730
This commit is contained in:
committed by
facebook-github-bot-5
parent
b65f1f2234
commit
ae09a10c95
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.views.image;
|
||||
|
||||
import android.support.annotation.IntDef;
|
||||
|
||||
import com.facebook.react.uimanager.events.Event;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
public class ImageLoadEvent extends Event<ImageLoadEvent> {
|
||||
@IntDef({ON_ERROR, ON_LOAD, ON_LOAD_END, ON_LOAD_START, ON_PROGRESS})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@interface ImageEventType {}
|
||||
|
||||
// Currently ON_ERROR and ON_PROGRESS are not implemented, these can be added
|
||||
// easily once support exists in fresco.
|
||||
public static final int ON_ERROR = 1;
|
||||
public static final int ON_LOAD = 2;
|
||||
public static final int ON_LOAD_END = 3;
|
||||
public static final int ON_LOAD_START = 4;
|
||||
public static final int ON_PROGRESS = 5;
|
||||
|
||||
private final int mEventType;
|
||||
|
||||
public ImageLoadEvent(int viewId, long timestampMs, @ImageEventType int eventType) {
|
||||
super(viewId, timestampMs);
|
||||
mEventType = eventType;
|
||||
}
|
||||
|
||||
public static String eventNameForType(@ImageEventType int eventType) {
|
||||
switch(eventType) {
|
||||
case ON_ERROR:
|
||||
return "topError";
|
||||
case ON_LOAD:
|
||||
return "topLoad";
|
||||
case ON_LOAD_END:
|
||||
return "topLoadEnd";
|
||||
case ON_LOAD_START:
|
||||
return "topLoadStart";
|
||||
case ON_PROGRESS:
|
||||
return "topProgress";
|
||||
default:
|
||||
throw new IllegalStateException("Invalid image event: " + Integer.toString(eventType));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventName() {
|
||||
return ImageLoadEvent.eventNameForType(mEventType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getCoalescingKey() {
|
||||
// Intentionally casting mEventType because it is guaranteed to be small
|
||||
// enough to fit into short.
|
||||
return (short) mEventType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch(RCTEventEmitter rctEventEmitter) {
|
||||
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), null);
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,13 @@ package com.facebook.react.views.image;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.drawee.controller.AbstractDraweeControllerBuilder;
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.uimanager.ReactProp;
|
||||
import com.facebook.react.uimanager.SimpleViewManager;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
@@ -102,6 +105,23 @@ public class ReactImageManager extends SimpleViewManager<ReactImageView> {
|
||||
view.setFadeDuration(durationMs);
|
||||
}
|
||||
|
||||
@ReactProp(name = "shouldNotifyLoadEvents")
|
||||
public void setLoadHandlersRegistered(ReactImageView view, boolean shouldNotifyLoadEvents) {
|
||||
view.setShouldNotifyLoadEvents(shouldNotifyLoadEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map getExportedCustomDirectEventTypeConstants() {
|
||||
return MapBuilder.of(
|
||||
ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD_START),
|
||||
MapBuilder.of("registrationName", "onLoadStart"),
|
||||
ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD),
|
||||
MapBuilder.of("registrationName", "onLoad"),
|
||||
ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD_END),
|
||||
MapBuilder.of("registrationName", "onLoadEnd")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAfterUpdateTransaction(ReactImageView view) {
|
||||
super.onAfterUpdateTransaction(view);
|
||||
|
||||
@@ -20,11 +20,15 @@ import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.net.Uri;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import com.facebook.common.util.UriUtil;
|
||||
import com.facebook.drawee.controller.AbstractDraweeControllerBuilder;
|
||||
import com.facebook.drawee.controller.BaseControllerListener;
|
||||
import com.facebook.drawee.controller.ControllerListener;
|
||||
import com.facebook.drawee.controller.ForwardingControllerListener;
|
||||
import com.facebook.drawee.drawable.ScalingUtils;
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchy;
|
||||
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
|
||||
@@ -32,11 +36,15 @@ import com.facebook.drawee.generic.RoundingParams;
|
||||
import com.facebook.drawee.interfaces.DraweeController;
|
||||
import com.facebook.drawee.view.GenericDraweeView;
|
||||
import com.facebook.imagepipeline.common.ResizeOptions;
|
||||
import com.facebook.imagepipeline.image.ImageInfo;
|
||||
import com.facebook.imagepipeline.request.BasePostprocessor;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
import com.facebook.imagepipeline.request.Postprocessor;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
|
||||
/**
|
||||
* Wrapper class around Fresco's GenericDraweeView, enabling persisting props across multiple view
|
||||
@@ -104,8 +112,9 @@ public class ReactImageView extends GenericDraweeView {
|
||||
private boolean mIsLocalImage;
|
||||
private final AbstractDraweeControllerBuilder mDraweeControllerBuilder;
|
||||
private final RoundedCornerPostprocessor mRoundedCornerPostprocessor;
|
||||
private final @Nullable Object mCallerContext;
|
||||
private @Nullable ControllerListener mControllerListener;
|
||||
private @Nullable ControllerListener mControllerForTesting;
|
||||
private final @Nullable Object mCallerContext;
|
||||
private int mFadeDurationMs = -1;
|
||||
private boolean mProgressiveRenderingEnabled;
|
||||
|
||||
@@ -127,6 +136,48 @@ public class ReactImageView extends GenericDraweeView {
|
||||
mCallerContext = callerContext;
|
||||
}
|
||||
|
||||
public void setShouldNotifyLoadEvents(boolean shouldNotify) {
|
||||
if (!shouldNotify) {
|
||||
mControllerListener = null;
|
||||
} else {
|
||||
final EventDispatcher mEventDispatcher = ((ReactContext) getContext()).
|
||||
getNativeModule(UIManagerModule.class).getEventDispatcher();
|
||||
|
||||
mControllerListener = new BaseControllerListener<ImageInfo>() {
|
||||
@Override
|
||||
public void onSubmit(String id, Object callerContext) {
|
||||
mEventDispatcher.dispatchEvent(
|
||||
new ImageLoadEvent(getId(), SystemClock.uptimeMillis(), ImageLoadEvent.ON_LOAD_START)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinalImageSet(
|
||||
String id,
|
||||
@Nullable final ImageInfo imageInfo,
|
||||
@Nullable Animatable animatable) {
|
||||
if (imageInfo != null) {
|
||||
mEventDispatcher.dispatchEvent(
|
||||
new ImageLoadEvent(getId(), SystemClock.uptimeMillis(), ImageLoadEvent.ON_LOAD_END)
|
||||
);
|
||||
mEventDispatcher.dispatchEvent(
|
||||
new ImageLoadEvent(getId(), SystemClock.uptimeMillis(), ImageLoadEvent.ON_LOAD)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String id, Throwable throwable) {
|
||||
mEventDispatcher.dispatchEvent(
|
||||
new ImageLoadEvent(getId(), SystemClock.uptimeMillis(), ImageLoadEvent.ON_LOAD_END)
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
mIsDirty = true;
|
||||
}
|
||||
|
||||
public void setBorderColor(int borderColor) {
|
||||
mBorderColor = borderColor;
|
||||
mIsDirty = true;
|
||||
@@ -217,21 +268,33 @@ public class ReactImageView extends GenericDraweeView {
|
||||
.setProgressiveRenderingEnabled(mProgressiveRenderingEnabled)
|
||||
.build();
|
||||
|
||||
DraweeController draweeController = mDraweeControllerBuilder
|
||||
.reset()
|
||||
// This builder is reused
|
||||
mDraweeControllerBuilder.reset();
|
||||
|
||||
mDraweeControllerBuilder
|
||||
.setAutoPlayAnimations(true)
|
||||
.setCallerContext(mCallerContext)
|
||||
.setOldController(getController())
|
||||
.setImageRequest(imageRequest)
|
||||
.setControllerListener(mControllerListener)
|
||||
.build();
|
||||
setController(draweeController);
|
||||
.setImageRequest(imageRequest);
|
||||
|
||||
if (mControllerListener != null && mControllerForTesting != null) {
|
||||
ForwardingControllerListener combinedListener = new ForwardingControllerListener();
|
||||
combinedListener.addListener(mControllerListener);
|
||||
combinedListener.addListener(mControllerForTesting);
|
||||
mDraweeControllerBuilder.setControllerListener(combinedListener);
|
||||
} else if (mControllerForTesting != null) {
|
||||
mDraweeControllerBuilder.setControllerListener(mControllerForTesting);
|
||||
} else if (mControllerListener != null) {
|
||||
mDraweeControllerBuilder.setControllerListener(mControllerListener);
|
||||
}
|
||||
|
||||
setController(mDraweeControllerBuilder.build());
|
||||
mIsDirty = false;
|
||||
}
|
||||
|
||||
// VisibleForTesting
|
||||
public void setControllerListener(ControllerListener controllerListener) {
|
||||
mControllerListener = controllerListener;
|
||||
mControllerForTesting = controllerListener;
|
||||
mIsDirty = true;
|
||||
maybeUpdateView();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user