In my app I have a ScrollView that contains some linearviews, some textviews and One Webview, then other linear layouts etc. The problem is that the WebView does not scroll. The Scroll listens only on ScrollView. Any suggestions??
<ScrollView >
<TextView />
<WebView /> <-- this does not scroll
<TextView />
</ScrollView >
Here is the solution. Found online. I have subclassed WebView and i'm using the requestDisallowInterceptTouchEvent(true);
method to allow my webview to handle the scroll event.
TouchyWebView.java
package com.mypackage.common.custom.android.widgets
public class TouchyWebView extends WebView {
public TouchyWebView(Context context) {
super(context);
}
public TouchyWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TouchyWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent event){
requestDisallowInterceptTouchEvent(true);
return super.onTouchEvent(event);
}
}
And in layout.xml
<com.mypackage.common.custom.android.widgets.TouchyWebView
android:id="@+id/description_web"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
The solution provided by @panos works but it still has issues when used with ScrollView. The following enhanced version overcomes that problem.
public class TouchyWebView extends WebView {
public TouchyWebView(Context context) {
super(context);
}
public TouchyWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TouchyWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//Check is required to prevent crash
if (MotionEventCompat.findPointerIndex(event, 0) == -1) {
return super.onTouchEvent(event);
}
if (event.getPointerCount() >= 2) {
requestDisallowInterceptTouchEvent(true);
} else {
requestDisallowInterceptTouchEvent(false);
}
return super.onTouchEvent(event);
}
@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
requestDisallowInterceptTouchEvent(true);
}
}
Additionally, you might want to have the following settings for your TouchyWebView.
mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
Panos solution is sufficient for me with one exception... My fixed-height (200dp) WebView
may be empty or may have loaded lot of content. So it may be or may be not scrollable "itself". Panos solution is consuming MotionEvent
s always, so when WebView
is empty and user touch WebView
and try to scroll then WebView
will not scroll (because there is no content) and scrollable parent also, cause WebView
"swallows" MotionEvent
- so nothing happens. I've added small if
statement for expected behaviour:
@Override
public boolean onTouchEvent(MotionEvent event) {
if(computeVerticalScrollRange() > getMeasuredHeight())
requestDisallowInterceptTouchEvent(true);
return super.onTouchEvent(event);
}
WebView
is empty and not-vertical-scrollable then computeVerticalScrollRange() == getMeasuredHeight()
WebView
have content longer than its height (is scrollable) then computeVerticalScrollRange() > getMeasuredHeight()
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