禁止在Webview中滚动?


86

直到现在,我还只是一名iPhone开发人员,而现在,我决定让Android焕然一新。我无法在Android上弄清楚的是如何以编程方式防止滚动WebView

类似于iPhone的onTouchMove事件预防措施将是很棒的!

Answers:


179

这是我的代码,用于禁用webview中的所有滚动

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

要仅隐藏滚动条,而不禁用滚动,请执行以下操作:

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

或者您可以尝试使用单列布局,但这仅适用于简单页面,并且会禁用水平滚动:

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

您还可以尝试使用垂直滚动的scrollview来包装webview并禁用该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>

并设置

webview.setScrollContainer(false);

不要忘记添加webview.setOnTouchListener(...)上面的代码以禁用Web视图中的所有滚动。垂直的ScrollView将允许滚动WebView的内容。


工作正常,但几秒钟后会导致/system/lib/libwebcore.so中的Samsung i5700 spica崩溃。
卢卡斯

LayoutAlgorithm.SINGLE_COLUMN还是webview.setOnTouchListener?
2011年

3
如果将WebView放在ScrollView中,请将WebView的android:isScrollContainer属性设置为“ false”,而不是将android:scrollbars设置为“ none”。这具有完全禁用Web视图的滚动处理并允许其根据其内容扩展的效果。滚动将仅由父ScrollView处理。
BladeCoder

1
如果您需要处理MotionEvent.ACTION_MOVE事件,WebView请在下面查看我的答案。
GDanger 2014年

1
忽略ACTION_MOVEonsetOnTouchListener事件会产生一些副作用,因此我不建议您使用此答案。1.快速滑动将被视为onclick页面事件。2.防止页面上元素的溢出滚动,这可能需要适当的交互,具体取决于站点。3. JStouchmove事件。@GDanger具有正确的答案,可以overScrollBy通过扩展来覆盖,WebView因为它没有其他副作用,只是防止了页面滚动。stackoverflow.com/a/26129301/1244574
jkasten

22

我不知道您是否仍然需要它,但是这里是解决方案:

appView = (WebView) findViewById(R.id.appView); 
appView.setVerticalScrollBarEnabled(false);
appView.setHorizontalScrollBarEnabled(false);

18
好。这会禁用滚动条,但不会阻止通过拖动进行滚动。似乎html也必须适合...
rdmueller 2011年

如果您只为android网页视图设计网页,则建议您将网页放在表格中。宽度应类似于width =“ 100%”,高度相同。这样就不会再拖了。
umar

宽度= 100%并不总是工作,例如:stackoverflow.com/questions/6460871/...
NoBugs

很棒..这就是我需要的。谢谢您
彼得

21

进行WebView忽略运动事件是错误的处理方法。如果WebView需要了解这些事件怎么办?

而是继承WebView并重写非私有滚动方法。

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

如果你看一下WebView您可以看到onTouchEvent来电doDrag这就要求overScrollBy


1
如果您需要以编程方式禁用/启用滚动,请查看我创建的这个要点
GDanger 2014年

1
您的方法对我有用。我完全同意你的看法。就我而言,我无法使用接受答案来拖动WebView中嵌入的视频和音频进度栏。
codezjx

这是正确的答案。尽管它需要对覆盖的构造函数进行一些调整。请在下面查看我的完整答案。stackoverflow.com/a/51936944/393502
Vansi,

13

如果内容正确包装,则在正文中添加边距详细信息将防止滚动,如下所示:

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

足够容易,并且更少的代码和错误开销:)


1
辉煌!+1是一个简单的仅HTML解决方案。有时我希望,android中的布局就像CSS一样简单...
Pritesh Desai 2013年

在普通的android浏览器中看起来不错,但在Firefox(Fennec)中似乎不起作用...尽管没有任何东西可以水平滚动,但Firefox仍然允许我向右滚动到所有内容滚动的位置离开屏幕。
迈克尔

1
在现代WebView(Android 5及更高版本)上不起作用
Roel

8

在您的WebView上设置一个侦听器:

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

3
return行末尾有一个额外的括号。这也会中断HTML5 canvas和JavaScript触摸事件。
罗汉·辛格

这肯定会禁用它,但是稍后如何杀死监听器以实现可靠的输入呢?我试过event.getAction() != MotionEvent.ACTION_MOVE以及return true
CQM

标准的“什么都不做”的情况是return false,没有return true
马修(Matthew)阅读了

6

我还没有尝试过,因为我还没有遇到这个问题,但是也许您可以超越onScroll函数?

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

这就是我们在印度所说的Jugaad ...虽然效果很好
R4chi7

4

我肮脏但易于实现且运行良好的解决方案:

只需将webview放入滚动视图中即可。使Web视图远远大于可能的内容(一维或二维,取决于要求)。..并根据需要设置滚动视图的滚动条。

禁用Web视图上的水平滚动条的示例:

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

我希望这有帮助 ;)


是的,但是在底部有很多空白的情况下,滚动尺寸不会太大吗?
拉斐尔·桑切斯

1
如果内容宽度为1001dp怎么办?
Waltsu 2014年

3

我通过以下方法解决了闪烁和自动滚动的问题:

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

但是,如果由于某种原因它仍然无法工作,只需创建一个扩展WebView的类,然后在其上放置此方法:

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

我建议扩展WebView,以提供更有效的控制,例如禁用/启用滑动,启用/禁用触摸,侦听器,控件转换,动画,内部定义设置等。


3

要禁用滚动,请使用此

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

2

这可能不是您问题的根源,但我花了数小时试图找出为什么我的应用程序在iphone上运行正常,导致android浏览器不断抛出垂直/水平滚动条并实际移动页面的原因。我有一个HTML正文标签,其高度和宽度设置为100%,并且正文在不同位置充满了各种标签。无论我尝试了什么,Android浏览器都会显示其滚动条并稍微移动页面,尤其是在快速滑动时。对于我来说无需在APK中执行任何操作的解决方案是在body标签中添加以下内容:

leftmargin="0" topmargin="0"

似乎在droid上应用了body标签的默认边距,但在iphone上被忽略了


1

如果将Webview子类化,则可以简单地重写onTouchEvent来过滤掉触发滚动的移动事件。

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

研究以上答案几乎对我有用...但是我仍然有一个问题,我可以“赞同” 2.1的观点(似乎已被2.2和2.3修正)。

这是我的最终解决方案

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

重写onScrollChanged()方法对我有用。就我而言,我无法使用接受答案来拖动WebView中嵌入的视频和音频进度栏。非常感谢!
codezjx

-1

这应该是完整的答案。如@GDanger所建议。扩展WebView以覆盖滚动方法,并将自定义Webview嵌入布局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();
        }
    }
}

然后如下嵌入到布局文件中

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

然后在“活动”中,也使用其他一些方法来禁用滚动条。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.