Add onContentSizeChange prop to WebView

Summary: Added support for WebViews to take in an onContentSizeChange prop, which will return a native event that contains the width and height of the html content in the WebView. Also moved the ContentSizeChangeEvent from the recyclerview dir to the uimanager/events dir

Reviewed By: andreicoman11

Differential Revision: D3775399

fbshipit-source-id: 19a0579f8345e5853cc7311b80f1f1393c77ab58
This commit is contained in:
Andrew Y. Chen
2016-08-29 12:23:09 -07:00
committed by Facebook Github Bot 8
parent 101190f7f8
commit 22de6550d6
4 changed files with 51 additions and 24 deletions

View File

@@ -58,6 +58,7 @@ class WebView extends React.Component {
automaticallyAdjustContentInsets: PropTypes.bool,
contentInset: EdgeInsetsPropType,
onNavigationStateChange: PropTypes.func,
onContentSizeChange: PropTypes.func,
startInLoadingState: PropTypes.bool, // force WebView to show loadingView on first load
style: View.propTypes.style,
@@ -219,6 +220,7 @@ class WebView extends React.Component {
domStorageEnabled={this.props.domStorageEnabled}
contentInset={this.props.contentInset}
automaticallyAdjustContentInsets={this.props.automaticallyAdjustContentInsets}
onContentSizeChange={this.props.onContentSizeChange}
onLoadingStart={this.onLoadingStart}
onLoadingFinish={this.onLoadingFinish}
onLoadingError={this.onLoadingError}

View File

@@ -1,16 +1,13 @@
// Copyright 2004-present Facebook. All Rights Reserved.
package com.facebook.react.views.recyclerview;
package com.facebook.react.uimanager.events;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.RCTEventEmitter;
/**
* Event dispatched by {@link RecyclerViewBackedScrollView} when total height of it's children
* changes
* Event dispatched when total width or height of a view's children changes
*/
public class ContentSizeChangeEvent extends Event<ContentSizeChangeEvent> {

View File

@@ -16,6 +16,7 @@ import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.ContentSizeChangeEvent;
import com.facebook.react.uimanager.events.NativeGestureUtil;
import com.facebook.react.views.scroll.ScrollEvent;
import com.facebook.react.views.scroll.ScrollEventType;
@@ -174,7 +175,6 @@ public class RecyclerViewBackedScrollView extends RecyclerView {
}
return mOffsetForLastPosition;
}
}
/*package*/ static class ReactListAdapter extends Adapter<ConcreteViewHolder> {

View File

@@ -15,18 +15,18 @@ import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Picture;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.view.ViewGroup.LayoutParams;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.WebChromeClient;
import com.facebook.react.views.webview.events.TopLoadingErrorEvent;
import com.facebook.react.views.webview.events.TopLoadingFinishEvent;
import com.facebook.react.views.webview.events.TopLoadingStartEvent;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactContext;
@@ -40,10 +40,12 @@ import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.ContentSizeChangeEvent;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.EventDispatcher;
import android.content.Intent;
import android.net.Uri;
import com.facebook.react.views.webview.events.TopLoadingErrorEvent;
import com.facebook.react.views.webview.events.TopLoadingFinishEvent;
import com.facebook.react.views.webview.events.TopLoadingStartEvent;
/**
* Manages instances of {@link WebView}
@@ -85,6 +87,7 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
private static final String BLANK_URL = "about:blank";
private WebViewConfig mWebViewConfig;
private @Nullable WebView.PictureListener mPictureListener;
private static class ReactWebViewClient extends WebViewClient {
@@ -118,11 +121,11 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
if (url.startsWith("http://") || url.startsWith("https://")) {
return false;
} else {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
view.getContext().startActivity(intent);
return true;
}
view.getContext().startActivity(intent);
return true;
}
}
@Override
@@ -166,13 +169,6 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
createWebViewEvent(webView, url)));
}
private static void dispatchEvent(WebView webView, Event event) {
ReactContext reactContext = (ReactContext) webView.getContext();
EventDispatcher eventDispatcher =
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
eventDispatcher.dispatchEvent(event);
}
private WritableMap createWebViewEvent(WebView webView, String url) {
WritableMap event = Arguments.createMap();
event.putDouble("target", webView.getId());
@@ -295,7 +291,6 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
view.getSettings().setDomStorageEnabled(enabled);
}
@ReactProp(name = "userAgent")
public void setUserAgent(WebView view, @Nullable String userAgent) {
if (userAgent != null) {
@@ -368,6 +363,15 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
view.loadUrl(BLANK_URL);
}
@ReactProp(name = "onContentSizeChange")
public void setOnContentSizeChange(WebView view, boolean sendContentSizeChangeEvents) {
if (sendContentSizeChangeEvents) {
view.setPictureListener(getPictureListener());
} else {
view.setPictureListener(null);
}
}
@Override
protected void addEventEmitters(ThemedReactContext reactContext, WebView view) {
// Do not register default touch emitter and let WebView implementation handle touches
@@ -407,4 +411,28 @@ public class ReactWebViewManager extends SimpleViewManager<WebView> {
((ThemedReactContext) webView.getContext()).removeLifecycleEventListener((ReactWebView) webView);
((ReactWebView) webView).cleanupCallbacksAndDestroy();
}
private WebView.PictureListener getPictureListener() {
if (mPictureListener == null) {
mPictureListener = new WebView.PictureListener() {
@Override
public void onNewPicture(WebView webView, Picture picture) {
dispatchEvent(
webView,
new ContentSizeChangeEvent(
webView.getId(),
webView.getWidth(),
webView.getContentHeight()));
}
};
}
return mPictureListener;
}
private static void dispatchEvent(WebView webView, Event event) {
ReactContext reactContext = (ReactContext) webView.getContext();
EventDispatcher eventDispatcher =
reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
eventDispatcher.dispatchEvent(event);
}
}