91

Until now I have been an iPhone developer only and now I have decided to give Android a whirl. Something I haven't been able to figure out on Android is how to programmatically prevent scrolling in a WebView?

Something similar to iPhones prevention of the onTouchMove event would be great!

13 Answers 13

190

Here is my code for disabling all scrolling in webview:

  // disable scroll on touch
  webview.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
  });

To only hide the scrollbars, but not disable scrolling:

WebView.setVerticalScrollBarEnabled(false);
WebView.setHorizontalScrollBarEnabled(false);

or you can try using single column layout but this only works with simple pages and it disables horizontal scrolling:

   //Only disabled the horizontal scrolling:
   webview.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

You can also try to wrap your webview with vertically scrolling scrollview and disable all scrolling on the webview:

<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical"    >
  <WebView
    android:id="@+id/mywebview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="none" />
</ScrollView>

And set

webview.setScrollContainer(false);

Don't forget to add the webview.setOnTouchListener(...) code above to disable all scrolling in the webview. The vertical ScrollView will allow for scrolling of the WebView's content.

13
  • works fine, but after few seconds causes crash on Samsung i5700 spica in /system/lib/libwebcore.so.
    – Lukas
    Commented May 20, 2011 at 10:29
  • LayoutAlgorithm.SINGLE_COLUMN or webview.setOnTouchListener?
    – peceps
    Commented May 21, 2011 at 20:48
  • 3
    If you put a WebView in a ScrollView, set the android:isScrollContainer attribute of the WebView to "false" rather than setting android:scrollbars to "none". This has the effect of completely disabling the scroll handling of the webview and allows it to expand according to its content. Scroll will then be handled solely by the parent ScrollView.
    – BladeCoder
    Commented Aug 14, 2014 at 10:07
  • 1
    If you need to handle MotionEvent.ACTION_MOVE events in your WebView see my answer below.
    – GDanger
    Commented Sep 30, 2014 at 20:23
  • 1
    Ignoring the ACTION_MOVE on the setOnTouchListener event has some side effects so I would NOT recommend this answer; 1. Quick swipes are counted as onclick events to the page. 2. Prevents overflow scrolling of elements on the page, this could be needed for proper interaction depending on the site. 3. The JS touchmove event. @GDanger has the correct answer which is overriding the overScrollBy by extending the WebView as it has no otherside effects, just prevents page scrolling. stackoverflow.com/a/26129301/1244574
    – jkasten
    Commented Mar 4, 2019 at 7:14
22

Making the WebView ignore motion events is the wrong way to go about it. What if the WebView needs to hear about these events?

Instead subclass WebView and override the non-private scroll methods.

public class NoScrollWebView extends WebView {
    ...
    @Override
    public boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, 
                                int scrollRangeX, int scrollRangeY, int maxOverScrollX, 
                                int maxOverScrollY, boolean isTouchEvent) {
        return false;
    }

    @Override
    public void scrollTo(int x, int y) {
        // Do nothing
    }

    @Override
    public void computeScroll() {
        // Do nothing
    }
}

If you look at the source for WebView you can see that onTouchEvent calls doDrag which calls overScrollBy.

3
  • 1
    If you need to programmatically disable/enable scroll look at this gist I created.
    – GDanger
    Commented Oct 24, 2014 at 20:47
  • 1
    Your method works for me. And I quite agree with you. In my case, I can't drag the video & audio progress bar embed in WebView by using the accept answer.
    – codezjx
    Commented May 6, 2015 at 7:11
  • This is the right answer. Though it needs some tweaks across overriding constructors. Please look at my complete answer below. stackoverflow.com/a/51936944/393502
    – Vansi
    Commented Aug 20, 2018 at 19:02
20

I don't know if you still need it or not, but here is the solution:

appView = (WebView) findViewById(R.id.appView); 
appView.setVerticalScrollBarEnabled(false);
appView.setHorizontalScrollBarEnabled(false);
3
  • 20
    ok. this disables the scrollbars, but it does not prevent scrolling by dragging. It seems that the html must fit too...
    – rdmueller
    Commented Feb 13, 2011 at 21:01
  • If u are designing your web pages only for android web view then I recommend make your web pages in table. The width should be like width="100%" and same for the height. so there will be no dragging any more.
    – umar
    Commented Feb 13, 2011 at 21:19
  • width=100% doesn't always work, for example: stackoverflow.com/questions/6460871/…
    – NoBugs
    Commented Jun 25, 2011 at 0:28
16

Adding the margin details to the body will prevent scrolling if your content properly wraps, as so:

<body leftmargin="0" topmargin="0" rightmargin="0" bottommargin="0">

Easy enough, and a lot less code + bug overhead :)

2
  • Looks good in the stock android browser, but doesn't seem to work in Firefox (Fennec)... despite there being nothing to scroll to horizontally, Firefox still lets me scroll off to the right to the point where all the content has scrolled off the screen.
    – Michael
    Commented Sep 3, 2013 at 17:37
  • 1
    Does not work on modern WebView (Android 5 and higher)
    – Roel
    Commented Jun 14, 2017 at 15:14
9

Set a listener on your WebView:

webView.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return(event.getAction() == MotionEvent.ACTION_MOVE));
            }
        });
3
  • 4
    There's an extra parenthesis at the end of the return line there. Also this breaks HTML5 canvas and JavaScript touch events. Commented Oct 9, 2010 at 21:21
  • This certainly disables it, but how do I kill the listener later on to renable input? I tried event.getAction() != MotionEvent.ACTION_MOVE as well as return true
    – CQM
    Commented Jul 19, 2011 at 22:33
  • The standard "do nothing" case is return false, not return true. Commented Mar 31, 2018 at 1:07
6

I haven't tried this as I have yet to encounter this problem, but perhaps you could overrive the onScroll function?

@Override
public void scrollTo(int x, int y){
super.scrollTo(0,y);
}
0
4

My dirty, but easy-to-implement and well working solution:

Simply put the webview inside a scrollview. Make the webview to be far too bigger than the possible content (in one or both dimensions, depending on the requirements). ..and set up the scrollview's scrollbar(s) as you wish.

Example to disable the horizontal scrollbar on a webview:

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="vertical"
>
    <WebView
        android:id="@+id/mywebview"
        android:layout_width="1000dip"
        android:layout_height="fill_parent"
    />
</ScrollView>

I hope this helps ;)

2
  • yep, but then the scroll size wouldn't be too big with lots of white space in the bottom? Commented Sep 23, 2011 at 18:55
  • 1
    What if content width will be 1001dp?
    – Waltsu
    Commented Aug 22, 2014 at 12:11
4

To Disable scroll use this

webView.setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) 
    {
        return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
});
0
3

I resolved the flicker and auto-scroll by:

webView.setFocusable(false);
webView.setFocusableInTouchMode(false);

However if it still does not work for some reason, simply make a class that extends WebView, and put this method on it:

// disable scroll on touch
  setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
  });

I am suggesting to extend WebView, in order to provide more effective control, like disable/enable swipes, enable/disable touches, listeners, control transitions, animations, define settings internally so on..

0
2

This may not be the source of your problem but I have spent hours trying to track down why my application that worked fine on the iphone cause the android browser to constantly throw up the vertical/horizontal scrollbars and actually move the page. I had an html body tag with height and width set to 100%, and the body was full of various tags in different locations. No matter what I tried, the android browsers would show their scroll bars and move the page just a little bit, particularly when doing a fast swipe. The solution that worked for me without having to do anything in an APK was to add the following to the body tag:

leftmargin="0" topmargin="0"

It seems the default margins for body tag were being applied on the droid but ignored on the iphone

1

If you subclass Webview, you can simply override onTouchEvent to filter out the move-events that trigger scrolling.

public class SubWebView extends WebView {

    @Override
    public boolean onTouchEvent (MotionEvent ev)    {
        if(ev.getAction() == MotionEvent.ACTION_MOVE) {
            postInvalidate();
            return true;
        }
        return super.onTouchEvent(ev);
    }
    ...
0

studying the above answers almost worked for me ... but I still had a problem that I could 'fling' the view on 2.1 (seemed to be fixed with 2.2 & 2.3).

here is my final solution

public class MyWebView extends WebView
{
private boolean bAllowScroll = true;
@SuppressWarnings("unused") // it is used, just java is dumb
private long downtime;

public MyWebView(Context context, AttributeSet attrs)
{
    super(context, attrs);
}

public void setAllowScroll(int allowScroll)
{
    bAllowScroll = allowScroll!=0;
    if (!bAllowScroll)
        super.scrollTo(0,0);
    setHorizontalScrollBarEnabled(bAllowScroll);
    setVerticalScrollBarEnabled(bAllowScroll);
}

@Override
public boolean onTouchEvent(MotionEvent ev) 
{
    switch (ev.getAction())
    {
    case MotionEvent.ACTION_DOWN:
        if (!bAllowScroll)
            downtime = ev.getEventTime();
        break;
    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_UP:
        if (!bAllowScroll)
        {
            try {
                Field fmNumSamples = ev.getClass().getDeclaredField("mNumSamples");
                fmNumSamples.setAccessible(true);
                Field fmTimeSamples = ev.getClass().getDeclaredField("mTimeSamples");
                fmTimeSamples.setAccessible(true);
                long newTimeSamples[] = new long[fmNumSamples.getInt(ev)];
                newTimeSamples[0] = ev.getEventTime()+250;
                fmTimeSamples.set(ev,newTimeSamples);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        break;
    }
    return super.onTouchEvent(ev);
}

@Override
public void flingScroll(int vx, int vy)
{
    if (bAllowScroll)
        super.flingScroll(vx,vy);
}

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt)
{
    if (bAllowScroll)
        super.onScrollChanged(l, t, oldl, oldt);
    else if (l!=0 || t!=0)
        super.scrollTo(0,0);
}

@Override
public void scrollTo(int x, int y)
{
    if (bAllowScroll)
        super.scrollTo(x,y);
}

@Override
public void scrollBy(int x, int y)
{
    if (bAllowScroll)
        super.scrollBy(x,y);
}
}
2
  • To override the onScrollChanged() method works for me. In my case, I can't drag the video & audio progress bar embed in WebView by using the accept answer. Thanks a lot!
    – codezjx
    Commented May 6, 2015 at 7:13
  • Webview cant load more automatically using this custom webview.
    – Viks
    Commented May 8, 2021 at 5:10
0

This should be the complete answer. As suggested by @GDanger . Extend WebView to override the scroll methods and embed the custom webview within layout xml.

public class ScrollDisabledWebView extends WebView {

    private boolean scrollEnabled = false;

    public ScrollDisabledWebView(Context context) {
        super(context);
        initView(context);
    }

    public ScrollDisabledWebView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        initView(context);
    }
    // this is important. Otherwise it throws Binary Inflate Exception.
    private void initView(Context context) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,
                                   int scrollRangeX, int scrollRangeY, int maxOverScrollX,
                                   int maxOverScrollY, boolean isTouchEvent) {
        if (scrollEnabled) {
            return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,
                    scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
        }
        return false;
    }

    @Override
    public void scrollTo(int x, int y) {
        if (scrollEnabled) {
            super.scrollTo(x, y);
        }
    }

    @Override
    public void computeScroll() {
        if (scrollEnabled) {
            super.computeScroll();
        }
    }
}

And then embed in layout file as follows

<com.sample.apps.ScrollDisabledWebView
    android:id="@+id/webView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    tools:context="com.sample.apps.HomeActivity"/>

Then in the Activity, use some additional methods for disabling scrollbars too.

ScrollDisabledWebView webView = (ScrollDisabledWebView) findViewById(R.id.webView);
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.