native-html / plugins

Plugins for react-native-render-html
MIT License
55 stars 18 forks source link

[table] Android scroll conflict #9

Closed Runtime007 closed 4 years ago

Runtime007 commented 4 years ago

In Android, if Html in ScrollView and table's columns > 2, it's not easy to scroll table to the left to show other columns. iOS is OK.

<ScrollView>
    <HTML
         {...htmlConfig}
         html={html}
    />
</ScorllView>

image

jsamr commented 4 years ago

@Runtime007 To help you, I will need you to produce a minimal reproducible example, in the form of an expo snack or git repository. Also, I am not sure about the issue!

Runtime007 commented 4 years ago

here is the code. Android 9.0 Galaxy s9+. I try to scroll the table to left or right, but the ScrollView captured the move event and it scrolls down or up, there is no response for the table sometimes. @jsamr

Runtime007 commented 4 years ago

hi, @jsamr, this issue has troubled me several days. I try to fix it by setting PanResponder for webview and listening to touch events to avoid scroll conflict but come to nothing. So I have to change android source code for react-native-webview, and it works.

protected static class RNCWebView extends WebView implements LifecycleEventListener {
    ...

    float startX = 0;
    float startY = 0;
    float dx = 0;
    float dy = 0;

    @Override
    public boolean onTouchEvent(MotionEvent event){
      switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
          getParent().requestDisallowInterceptTouchEvent(true);
          startX = event.getX();
          startY = event.getY();
          break;
        case MotionEvent.ACTION_MOVE:
          dx = Math.abs(event.getX() - startX);
          dy = Math.abs(event.getY() - startY);
          if (dx > dy) {
            getParent().requestDisallowInterceptTouchEvent(true);
          } else {
            getParent().requestDisallowInterceptTouchEvent(false);
          }
          break;
      }

      return super.onTouchEvent(event);
    }
    ...

}
jsamr commented 4 years ago

@Runtime007 I'll take a look today!

jsamr commented 4 years ago

@Runtime007 The issue is that you would like a minimum dy value for the gesture to trigger a scroll event in the root ScrollView component. Something like the activeOffsetY prop from RNGH PanGestureHandler

I see two options :

  1. Get inspiration from this hacking.
  2. Render table previews and offer full table layout in a separate modal or screen after user interaction.

In either cases, you will need makeCustomTableRenderer.

I hope you'll find something workable. I will close because this limitation is broadly from react-native. But if you dig any workaround, please post your findings!

Best,

JSR

jsamr commented 4 years ago

hi, @jsamr, this issue has troubled me several days. I try to fix it by setting PanResponder for webview and listening to touch events to avoid scroll conflict but come to nothing. So I have to change android source code for react-native-webview, and it works.

protected static class RNCWebView extends WebView implements LifecycleEventListener {
    ...

    float startX = 0;
    float startY = 0;
    float dx = 0;
    float dy = 0;

    @Override
    public boolean onTouchEvent(MotionEvent event){
      switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
          getParent().requestDisallowInterceptTouchEvent(true);
          startX = event.getX();
          startY = event.getY();
          break;
        case MotionEvent.ACTION_MOVE:
          dx = Math.abs(event.getX() - startX);
          dy = Math.abs(event.getY() - startY);
          if (dx > dy) {
            getParent().requestDisallowInterceptTouchEvent(true);
          } else {
            getParent().requestDisallowInterceptTouchEvent(false);
          }
          break;
      }

      return super.onTouchEvent(event);
    }
    ...

}

Third option : I would suggest you offer a PR to react-native-webview with a prop enabling the behavior you have implemented. Not sure about the best chose of words though!

Runtime007 commented 4 years ago

@Runtime007 The issue is that you would like a minimum dy value for the gesture to trigger a scroll event in the root ScrollView component. Something like the activeOffsetY prop from RNGH PanGestureHandler

I see two options :

  1. Get inspiration from this hacking.
  2. Render table previews and offer full table layout in a separate modal or screen after user interaction.

In either cases, you will need makeCustomTableRenderer.

I hope you'll find something workable. I will close because this limitation is broadly from react-native. But if you dig any workaround, please post your findings!

Best,

JSR

Thank you very much for your proposals, I'll check and try, to see if it can be implemented on the react side.

Best regards.

chr314 commented 4 years ago

14 merged, now you can use onMessage and injectedJavaScript webview props

you can disable scroll of ScrollView with scrollEnabled prop

<ScrollView scrollEnabled={this.state.scrollEnabled}>
          <HTML
            alterNode={alterNode}
            renderers={this.htmlRenderers}
            ignoredTags={IGNORED_TAGS}
            html={this.state.content}
          />
</ScrollView>
  scrollTimer;
  onTableMessage = (event) => {
    if (event.data === 'scroll') {
      if (this.scrollTimer) {
        clearTimeout(this.scrollTimer);
      }
      this.setState({scrollEnabled: false}, () => {
        this.scrollTimer = setTimeout(() => {
          this.setState({scrollEnabled: true});
        }, 100);
      });
    }
  };

  htmlRenderers = {
    table: makeTableRenderer({
      WebViewComponent: WebView,
      webViewProps: {
        onMessage: this.onTableMessage,
        injectedJavaScript:
          "setTimeout(() => {document.addEventListener('scroll', function () {window.ReactNativeWebView.postMessage('scroll');},true);}, 300);",
      },
    }),
  };