I have WebView
(s) inside the RecyclerView
. In order to get smooth scrolling experience such that when user scrolls, the RecyclerView
will be responsible for scrolling (WebView
should not scroll) I called getParent().requestDisallowInterceptTouchEvent(false);
inside webview#onTouchEvent(event)
when there is only one touch point and is moving vertcially (scrolling up and down).
private void handleSingleFingerTouch(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = ev.getX();
y1 = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
x2 = ev.getX();
y2 = ev.getY();
// -ve param for canScrollHorizontally is to check scroll left. +ve otherwise
if (Math.abs(x1 - x2) >= Math.abs(y1 - y2)
&& canScrollHorizontally((int) (x1 - x2))) {
// scrolling horizontally. Retain the touch inside the webView.
getParent().requestDisallowInterceptTouchEvent(true);
} else {
// scrolling vertically. Share the touch event with the parent.
getParent().requestDisallowInterceptTouchEvent(false);
}
x1 = x2;
y1 = y2;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean multiTouch = ev.getPointerCount() > 1;
if (multiTouch) {
getParent().requestDisallowInterceptTouchEvent(true);
} else {
handleSingleFingerTouch(ev);
}
return super.onTouchEvent(ev);
}
It works as expected with just one bug, I found that while RecyclerView
(and webview) scrolling and I touch inside the WebView
, then RecyclerView
stops scrolling as expected, then if I don't lift up my finger but keep finger on the screen and try to zoom, the webview would not zoom and actually it wouldn't receive touch event at all. I have to lift my fingers and touch again to zoom. I know this is because getParent().requestDisallowInterceptTouchEvent(false);
won't cancel unless UI receive CANCEL
or UP
event. I tried to implement an interface that call getParent().requestDisallowInterceptTouchEvent(true);
when multi-touch happen. Though it did get called, but seems it doesn't work. Zoom still not happen and onTouchEvent
inside the WebView
still not get triggered. Any idea to solve this?
So basically the solution is to override the onInterceptTouchEvent
of the recyclerView
override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
// When recyclerview is scrolling this will stop scrolling and allow touch event passed to child views.
if (e.action == MotionEvent.ACTION_DOWN && this.scrollState == RecyclerView.SCROLL_STATE_SETTLING) {
this.stopScroll()
}
return super.onInterceptTouchEvent(e)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With