feat(onScroll): Add `onScroll` callback for iOS & Android (#516)
* Add `onScroll` callback for iOS & Android This code was mostly extracted from https://github.com/react-native-community/react-native-webview/pull/202 I tried and tried to make it work with `Animated.event`'s `useNativeDriver`, but I was unsuccessful 😢 that'll have to be done later once I understand better how Animated's native stuff is hooked up. * fix crash for missing onScroll
This commit is contained in:
parent
409b9ae620
commit
e4c8dab2ae
|
@ -31,6 +31,9 @@ import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import com.facebook.react.views.scroll.ScrollEvent;
|
||||||
|
import com.facebook.react.views.scroll.ScrollEventType;
|
||||||
|
import com.facebook.react.views.scroll.OnScrollDispatchHelper;
|
||||||
import com.facebook.react.bridge.Arguments;
|
import com.facebook.react.bridge.Arguments;
|
||||||
import com.facebook.react.bridge.LifecycleEventListener;
|
import com.facebook.react.bridge.LifecycleEventListener;
|
||||||
import com.facebook.react.bridge.ReactContext;
|
import com.facebook.react.bridge.ReactContext;
|
||||||
|
@ -446,6 +449,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||||
}
|
}
|
||||||
export.put(TopLoadingProgressEvent.EVENT_NAME, MapBuilder.of("registrationName", "onLoadingProgress"));
|
export.put(TopLoadingProgressEvent.EVENT_NAME, MapBuilder.of("registrationName", "onLoadingProgress"));
|
||||||
export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
|
export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
|
||||||
|
export.put(ScrollEventType.SCROLL.getJSEventName(), MapBuilder.of("registrationName", "onScroll"));
|
||||||
return export;
|
return export;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -780,6 +784,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||||
protected @Nullable
|
protected @Nullable
|
||||||
RNCWebViewClient mRNCWebViewClient;
|
RNCWebViewClient mRNCWebViewClient;
|
||||||
protected boolean sendContentSizeChangeEvents = false;
|
protected boolean sendContentSizeChangeEvents = false;
|
||||||
|
private final OnScrollDispatchHelper mOnScrollDispatchHelper = new OnScrollDispatchHelper();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebView must be created with an context of the current activity
|
* WebView must be created with an context of the current activity
|
||||||
|
@ -886,6 +891,26 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||||
dispatchEvent(this, new TopMessageEvent(this.getId(), message));
|
dispatchEvent(this, new TopMessageEvent(this.getId(), message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
|
||||||
|
super.onScrollChanged(x, y, oldX, oldY);
|
||||||
|
|
||||||
|
if (mOnScrollDispatchHelper.onScrollChanged(x, y)) {
|
||||||
|
ScrollEvent event = ScrollEvent.obtain(
|
||||||
|
this.getId(),
|
||||||
|
ScrollEventType.SCROLL,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
mOnScrollDispatchHelper.getXFlingVelocity(),
|
||||||
|
mOnScrollDispatchHelper.getYFlingVelocity(),
|
||||||
|
this.computeHorizontalScrollRange(),
|
||||||
|
this.computeVerticalScrollRange(),
|
||||||
|
this.getWidth(),
|
||||||
|
this.getHeight());
|
||||||
|
|
||||||
|
dispatchEvent(this, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void cleanupCallbacksAndDestroy() {
|
protected void cleanupCallbacksAndDestroy() {
|
||||||
setWebViewClient(null);
|
setWebViewClient(null);
|
||||||
destroy();
|
destroy();
|
||||||
|
|
|
@ -34,6 +34,7 @@ static NSURLCredential* clientAuthenticationCredential;
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onLoadingProgress;
|
@property (nonatomic, copy) RCTDirectEventBlock onLoadingProgress;
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onShouldStartLoadWithRequest;
|
@property (nonatomic, copy) RCTDirectEventBlock onShouldStartLoadWithRequest;
|
||||||
@property (nonatomic, copy) RCTDirectEventBlock onMessage;
|
@property (nonatomic, copy) RCTDirectEventBlock onMessage;
|
||||||
|
@property (nonatomic, copy) RCTDirectEventBlock onScroll;
|
||||||
@property (nonatomic, copy) WKWebView *webView;
|
@property (nonatomic, copy) WKWebView *webView;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -509,6 +510,30 @@ static NSURLCredential* clientAuthenticationCredential;
|
||||||
if (!_scrollEnabled) {
|
if (!_scrollEnabled) {
|
||||||
scrollView.bounds = _webView.bounds;
|
scrollView.bounds = _webView.bounds;
|
||||||
}
|
}
|
||||||
|
else if (_onScroll != nil) {
|
||||||
|
NSDictionary *event = @{
|
||||||
|
@"contentOffset": @{
|
||||||
|
@"x": @(scrollView.contentOffset.x),
|
||||||
|
@"y": @(scrollView.contentOffset.y)
|
||||||
|
},
|
||||||
|
@"contentInset": @{
|
||||||
|
@"top": @(scrollView.contentInset.top),
|
||||||
|
@"left": @(scrollView.contentInset.left),
|
||||||
|
@"bottom": @(scrollView.contentInset.bottom),
|
||||||
|
@"right": @(scrollView.contentInset.right)
|
||||||
|
},
|
||||||
|
@"contentSize": @{
|
||||||
|
@"width": @(scrollView.contentSize.width),
|
||||||
|
@"height": @(scrollView.contentSize.height)
|
||||||
|
},
|
||||||
|
@"layoutMeasurement": @{
|
||||||
|
@"width": @(scrollView.frame.size.width),
|
||||||
|
@"height": @(scrollView.frame.size.height)
|
||||||
|
},
|
||||||
|
@"zoomScale": @(scrollView.zoomScale ?: 1),
|
||||||
|
};
|
||||||
|
_onScroll(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setDirectionalLockEnabled:(BOOL)directionalLockEnabled
|
- (void)setDirectionalLockEnabled:(BOOL)directionalLockEnabled
|
||||||
|
|
|
@ -56,6 +56,7 @@ RCT_EXPORT_VIEW_PROPERTY(allowsLinkPreview, BOOL)
|
||||||
*/
|
*/
|
||||||
RCT_EXPORT_VIEW_PROPERTY(messagingEnabled, BOOL)
|
RCT_EXPORT_VIEW_PROPERTY(messagingEnabled, BOOL)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onMessage, RCTDirectEventBlock)
|
RCT_EXPORT_VIEW_PROPERTY(onMessage, RCTDirectEventBlock)
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(onScroll, RCTDirectEventBlock)
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(postMessage:(nonnull NSNumber *)reactTag message:(NSString *)message)
|
RCT_EXPORT_METHOD(postMessage:(nonnull NSNumber *)reactTag message:(NSString *)message)
|
||||||
{
|
{
|
||||||
|
|
|
@ -382,6 +382,7 @@ class WebView extends React.Component<IOSWebViewProps, State> {
|
||||||
onLoadingProgress={this.onLoadingProgress}
|
onLoadingProgress={this.onLoadingProgress}
|
||||||
onLoadingStart={this.onLoadingStart}
|
onLoadingStart={this.onLoadingStart}
|
||||||
onMessage={this.onMessage}
|
onMessage={this.onMessage}
|
||||||
|
onScroll={this.props.onScroll}
|
||||||
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
||||||
ref={this.webViewRef}
|
ref={this.webViewRef}
|
||||||
scalesPageToFit={scalesPageToFit}
|
scalesPageToFit={scalesPageToFit}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {
|
||||||
NativeMethodsMixin,
|
NativeMethodsMixin,
|
||||||
Constructor,
|
Constructor,
|
||||||
UIManagerStatic,
|
UIManagerStatic,
|
||||||
|
NativeScrollEvent,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
export interface WebViewCommands {
|
export interface WebViewCommands {
|
||||||
|
@ -213,6 +214,7 @@ export interface CommonNativeWebViewProps extends ViewProps {
|
||||||
injectedJavaScript?: string;
|
injectedJavaScript?: string;
|
||||||
mediaPlaybackRequiresUserAction?: boolean;
|
mediaPlaybackRequiresUserAction?: boolean;
|
||||||
messagingEnabled: boolean;
|
messagingEnabled: boolean;
|
||||||
|
onScroll?: (event: NativeScrollEvent) => void;
|
||||||
onLoadingError: (event: WebViewErrorEvent) => void;
|
onLoadingError: (event: WebViewErrorEvent) => void;
|
||||||
onLoadingFinish: (event: WebViewNavigationEvent) => void;
|
onLoadingFinish: (event: WebViewNavigationEvent) => void;
|
||||||
onLoadingProgress: (event: WebViewProgressEvent) => void;
|
onLoadingProgress: (event: WebViewProgressEvent) => void;
|
||||||
|
@ -542,6 +544,11 @@ export interface WebViewSharedProps extends ViewProps {
|
||||||
*/
|
*/
|
||||||
renderLoading?: () => ReactElement;
|
renderLoading?: () => ReactElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that is invoked when the `WebView` scrolls.
|
||||||
|
*/
|
||||||
|
onScroll?: (event: NativeScrollEvent) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that is invoked when the `WebView` has finished loading.
|
* Function that is invoked when the `WebView` has finished loading.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue