Android WebView inside ScrollView scrolls only scrollview

48,646

Solution 1

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"
                 />

Solution 2

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);

Solution 3

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 MotionEvents 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);
}
  • when WebView is empty and not-vertical-scrollable then computeVerticalScrollRange() == getMeasuredHeight()
  • when WebView have content longer than its height (is scrollable) then computeVerticalScrollRange() > getMeasuredHeight()

Solution 4

Working off the solutions of @Panos and @Dipendra I still had some issues with a mapview inside a scrollview. It would not consistently scroll vertically and the methods were deprecated so I worked out this trick I use with mapview inside of scrollviews and works great. I hope this can help a few of you.

public class TouchyWebView extends WebView {
ViewParent mViewParent;

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);
}

public void setViewParent(@Nullable final ViewParent viewParent) { //any ViewGroup
    mViewParent = viewParent;
}


@Override
public boolean onTouchEvent(MotionEvent event) {

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (null == mViewParent) {
                getParent().requestDisallowInterceptTouchEvent(true);
            } else {
                mViewParent.requestDisallowInterceptTouchEvent(true);
            }
            break;
        case MotionEvent.ACTION_UP:
            if (null == mViewParent) {
                getParent().requestDisallowInterceptTouchEvent(false);
            } else {
                mViewParent.requestDisallowInterceptTouchEvent(false);
            }
            break;
        default:
            break;
    }
    return super.onTouchEvent(event);
}

@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
    super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
    requestDisallowInterceptTouchEvent(true);


}

}

I also followed @Dipendra advice about settings the controls.

mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
Share:
48,646

Related videos on Youtube

Panos
Author by

Panos

Updated on July 09, 2022

Comments

  • Panos
    Panos almost 2 years

    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 >
    
  • Panos
    Panos over 11 years
    My scroll view is there because those items don't fit in the screen. In my example I added only one textview above and one textview below. But in reality there are other relative layouts, there imageviews, webview is somewhere in the middle and the others... So I need the scroll view so I can see everything.
  • Artyom Kiriliyk
    Artyom Kiriliyk over 11 years
    Try this solution
  • theblang
    theblang over 10 years
    This breaks once you touch outside of the WebView.
  • Panos
    Panos over 10 years
    @mattblang touch once the webview again and then try to scroll it again.
  • ismailarilik
    ismailarilik about 10 years
    WebView does not have "addHeaderView" or "addFooterView" methods, ListView has these methods. So this is not a solution.
  • reactive-core
    reactive-core about 10 years
    Been looking around a bit for something to allow good webview/scrollview interaction, and this seems the best. I added a check in onTouchEvent() for "if (event.getPointerCount() > 1)" before calling the requestDisallowInterceptTouchEvent(true) method. This allows the entire page to be scrolled vertically, the webview to be scrolled horizontally, and pinch & zoom to apply only to the webview.
  • aimiliano
    aimiliano almost 9 years
    this solution and using hardware accelerated = true in this activity, when pressing back crashes... if i disable hardware accelleration works but is going slow and html5 videos not playing..
  • Darpan Kulkarni
    Darpan Kulkarni almost 9 years
    Any Updates on this? I used it and its working but sometimes the webview does not catch the touch..
  • ricky.tribbia
    ricky.tribbia over 8 years
    works for me only changing: return super.onTouchEvent(event); with return false; in public boolean onTouchEvent(MotionEvent event)
  • snachmsm
    snachmsm over 7 years
    with your solution WebView is scrollable only by two fingers, with one finger only parent is scrolling... not so intuitive :/
  • Mila
    Mila about 7 years
    It works fine when the WebView contains scrollable content. However, if it is not scrollable, it gets stuck disabling the parent ScrollView's scrolling... Has anybody dealt with that?
  • Micer
    Micer almost 6 years
    Note MotionEventCompat.findPointerIndex(event, 0) is now deprecated, we should use event.findPointerIndex(0) instead.
  • Lennoard Silva
    Lennoard Silva about 3 years
    Or ViewCompat.setNestedScrollingEnabled(mWebView, true)
  • AndroidEngineX
    AndroidEngineX about 3 years
    This doesn't work. I am not sure whether @Nikunj is aware of Android developemennt or not but to clarify a little bit nestedScrolling on works for those view which support nested scrolling and not for all the views. And webView doesn't support nested scrolling. Please delete this answer to avoid any confusion
  • Rayman
    Rayman almost 3 years
    It's work for me. But if you are using Tencent X5WebView widget, onTouchEvent callback doesn't invoke. So just extends google webkit.WebView instead of extends X5WebView