瀏覽代碼

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
Jared Forsyth 5 年之前
父節點
當前提交
e4c8dab2ae

+ 25
- 0
android/src/main/java/com/reactnativecommunity/webview/RNCWebViewManager.java 查看文件

@@ -31,6 +31,9 @@ import android.webkit.WebView;
31 31
 import android.webkit.WebViewClient;
32 32
 import android.widget.FrameLayout;
33 33
 
34
+import com.facebook.react.views.scroll.ScrollEvent;
35
+import com.facebook.react.views.scroll.ScrollEventType;
36
+import com.facebook.react.views.scroll.OnScrollDispatchHelper;
34 37
 import com.facebook.react.bridge.Arguments;
35 38
 import com.facebook.react.bridge.LifecycleEventListener;
36 39
 import com.facebook.react.bridge.ReactContext;
@@ -446,6 +449,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
446 449
     }
447 450
     export.put(TopLoadingProgressEvent.EVENT_NAME, MapBuilder.of("registrationName", "onLoadingProgress"));
448 451
     export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
452
+    export.put(ScrollEventType.SCROLL.getJSEventName(), MapBuilder.of("registrationName", "onScroll"));
449 453
     return export;
450 454
   }
451 455
 
@@ -780,6 +784,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
780 784
     protected @Nullable
781 785
     RNCWebViewClient mRNCWebViewClient;
782 786
     protected boolean sendContentSizeChangeEvents = false;
787
+    private final OnScrollDispatchHelper mOnScrollDispatchHelper = new OnScrollDispatchHelper();
783 788
 
784 789
     /**
785 790
      * WebView must be created with an context of the current activity
@@ -886,6 +891,26 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
886 891
       dispatchEvent(this, new TopMessageEvent(this.getId(), message));
887 892
     }
888 893
 
894
+    protected void onScrollChanged(int x, int y, int oldX, int oldY) {
895
+      super.onScrollChanged(x, y, oldX, oldY);
896
+
897
+      if (mOnScrollDispatchHelper.onScrollChanged(x, y)) {
898
+        ScrollEvent event = ScrollEvent.obtain(
899
+                this.getId(),
900
+                ScrollEventType.SCROLL,
901
+                x,
902
+                y,
903
+                mOnScrollDispatchHelper.getXFlingVelocity(),
904
+                mOnScrollDispatchHelper.getYFlingVelocity(),
905
+                this.computeHorizontalScrollRange(),
906
+                this.computeVerticalScrollRange(),
907
+                this.getWidth(),
908
+                this.getHeight());
909
+
910
+        dispatchEvent(this, event);
911
+      }
912
+    }
913
+
889 914
     protected void cleanupCallbacksAndDestroy() {
890 915
       setWebViewClient(null);
891 916
       destroy();

+ 25
- 0
ios/RNCWKWebView.m 查看文件

@@ -34,6 +34,7 @@ static NSURLCredential* clientAuthenticationCredential;
34 34
 @property (nonatomic, copy) RCTDirectEventBlock onLoadingProgress;
35 35
 @property (nonatomic, copy) RCTDirectEventBlock onShouldStartLoadWithRequest;
36 36
 @property (nonatomic, copy) RCTDirectEventBlock onMessage;
37
+@property (nonatomic, copy) RCTDirectEventBlock onScroll;
37 38
 @property (nonatomic, copy) WKWebView *webView;
38 39
 @end
39 40
 
@@ -509,6 +510,30 @@ static NSURLCredential* clientAuthenticationCredential;
509 510
   if (!_scrollEnabled) {
510 511
     scrollView.bounds = _webView.bounds;
511 512
   }
513
+  else if (_onScroll != nil) {
514
+    NSDictionary *event = @{
515
+      @"contentOffset": @{
516
+          @"x": @(scrollView.contentOffset.x),
517
+          @"y": @(scrollView.contentOffset.y)
518
+          },
519
+      @"contentInset": @{
520
+          @"top": @(scrollView.contentInset.top),
521
+          @"left": @(scrollView.contentInset.left),
522
+          @"bottom": @(scrollView.contentInset.bottom),
523
+          @"right": @(scrollView.contentInset.right)
524
+          },
525
+      @"contentSize": @{
526
+          @"width": @(scrollView.contentSize.width),
527
+          @"height": @(scrollView.contentSize.height)
528
+          },
529
+      @"layoutMeasurement": @{
530
+          @"width": @(scrollView.frame.size.width),
531
+          @"height": @(scrollView.frame.size.height)
532
+          },
533
+      @"zoomScale": @(scrollView.zoomScale ?: 1),
534
+      };
535
+    _onScroll(event);
536
+  }
512 537
 }
513 538
 
514 539
 - (void)setDirectionalLockEnabled:(BOOL)directionalLockEnabled

+ 1
- 0
ios/RNCWKWebViewManager.m 查看文件

@@ -56,6 +56,7 @@ RCT_EXPORT_VIEW_PROPERTY(allowsLinkPreview, BOOL)
56 56
  */
57 57
 RCT_EXPORT_VIEW_PROPERTY(messagingEnabled, BOOL)
58 58
 RCT_EXPORT_VIEW_PROPERTY(onMessage, RCTDirectEventBlock)
59
+RCT_EXPORT_VIEW_PROPERTY(onScroll, RCTDirectEventBlock)
59 60
 
60 61
 RCT_EXPORT_METHOD(postMessage:(nonnull NSNumber *)reactTag message:(NSString *)message)
61 62
 {

+ 1
- 0
src/WebView.ios.tsx 查看文件

@@ -382,6 +382,7 @@ class WebView extends React.Component<IOSWebViewProps, State> {
382 382
         onLoadingProgress={this.onLoadingProgress}
383 383
         onLoadingStart={this.onLoadingStart}
384 384
         onMessage={this.onMessage}
385
+        onScroll={this.props.onScroll}
385 386
         onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
386 387
         ref={this.webViewRef}
387 388
         scalesPageToFit={scalesPageToFit}

+ 7
- 0
src/WebViewTypes.ts 查看文件

@@ -7,6 +7,7 @@ import {
7 7
   NativeMethodsMixin,
8 8
   Constructor,
9 9
   UIManagerStatic,
10
+  NativeScrollEvent,
10 11
 } from 'react-native';
11 12
 
12 13
 export interface WebViewCommands {
@@ -213,6 +214,7 @@ export interface CommonNativeWebViewProps extends ViewProps {
213 214
   injectedJavaScript?: string;
214 215
   mediaPlaybackRequiresUserAction?: boolean;
215 216
   messagingEnabled: boolean;
217
+  onScroll?: (event: NativeScrollEvent) => void;
216 218
   onLoadingError: (event: WebViewErrorEvent) => void;
217 219
   onLoadingFinish: (event: WebViewNavigationEvent) => void;
218 220
   onLoadingProgress: (event: WebViewProgressEvent) => void;
@@ -542,6 +544,11 @@ export interface WebViewSharedProps extends ViewProps {
542 544
    */
543 545
   renderLoading?: () => ReactElement;
544 546
 
547
+  /**
548
+   * Function that is invoked when the `WebView` scrolls.
549
+   */
550
+  onScroll?: (event: NativeScrollEvent) => void;
551
+
545 552
   /**
546 553
    * Function that is invoked when the `WebView` has finished loading.
547 554
    */