Disable scrolling in webview?
Asked Answered
W

13

90

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!

Wristlet answered 27/3, 2010 at 2:27 Comment(0)
B
188

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.

Breadboard answered 11/3, 2011 at 14:50 Comment(12)
works fine, but after few seconds causes crash on Samsung i5700 spica in /system/lib/libwebcore.so.Unicellular
LayoutAlgorithm.SINGLE_COLUMN or webview.setOnTouchListener?Breadboard
I am starting another activity in onTouchListener so can you please tell me how to dissable vertical scroll..?Wilkins
@Wilkins public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_MOVE) return true; // start activity here return false; }Breadboard
Hi want Display the Content is page wise in webview i do all of this but its cant work for me.please give me any solution.Fenestrated
webView.setHorizontalScrollBarEnabled(false); webView.setHorizontalScrollbarOverlay(false); webView.setVerticalScrollBarEnabled(false); webView.setVerticalScrollbarOverlay(false);Outdoors
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.Fulk
If you need to handle MotionEvent.ACTION_MOVE events in your WebView see my answer below.Feeding
May you forgot @Override on onTouch, No problem. I edited.Twirp
In my case, I can't drag the video & audio progress bar embed in WebView by using this answer. But I found another way in the bottom: override the overScrollBy() or onScrollChanged() in WebView.Bucket
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. @Feeding has the correct answer which is overriding the overScrollBy by extending the WebView as it has no otherside effects, just prevents page scrolling. https://mcmap.net/q/57356/-disable-scrolling-in-webviewLorri
Webview scroll disabled but my view pager swipe also not workingRemillard
F
21

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.

Feeding answered 30/9, 2014 at 20:15 Comment(3)
If you need to programmatically disable/enable scroll look at this gist I created.Feeding
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.Bucket
This is the right answer. Though it needs some tweaks across overriding constructors. Please look at my complete answer below. https://mcmap.net/q/57356/-disable-scrolling-in-webviewConsecution
A
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);
Alterative answered 9/2, 2011 at 1:25 Comment(3)
ok. this disables the scrollbars, but it does not prevent scrolling by dragging. It seems that the html must fit too...Sabbath
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.Alterative
width=100% doesn't always work, for example: #6461371Haleyhalf
S
15

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

Stroller answered 31/1, 2012 at 15:50 Comment(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.Allamerican
Does not work on modern WebView (Android 5 and higher)Dullard
C
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));
            }
        });
Clack answered 22/4, 2010 at 7:9 Comment(3)
There's an extra parenthesis at the end of the return line there. Also this breaks HTML5 canvas and JavaScript touch events.Rodger
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 trueEntomologize
The standard "do nothing" case is return false, not return true.Braca
M
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);
}
Mccrary answered 8/7, 2010 at 0:25 Comment(0)
N
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 ;)

Nette answered 16/4, 2010 at 11:42 Comment(2)
yep, but then the scroll size wouldn't be too big with lots of white space in the bottom?Fausta
What if content width will be 1001dp?Florentinoflorenza
A
4

To Disable scroll use this

webView.setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) 
    {
        return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
});
Alfi answered 2/10, 2014 at 4:37 Comment(0)
D
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..

Definiens answered 18/2, 2014 at 11:22 Comment(0)
E
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

Esch answered 25/10, 2011 at 22:47 Comment(0)
B
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);
    }
    ...
Bibliotheca answered 15/3, 2012 at 12:59 Comment(0)
S
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);
}
}
Slavocracy answered 8/3, 2011 at 2:31 Comment(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!Bucket
Webview cant load more automatically using this custom webview.Gretagretal
C
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);
Consecution answered 20/8, 2018 at 18:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.