【问题标题】:Disable scrolling in webview?禁用网页视图中的滚动?
【发布时间】:2010-03-27 02:27:21
【问题描述】:

到目前为止,我只是一名 iPhone 开发人员,现在我决定试一试 Android。我在 Android 上无法弄清楚的事情是如何以编程方式防止在 WebView 中滚动?

类似于 iPhone 防止 onTouchMove 事件的东西会很棒!

【问题讨论】:

    标签: android android-webview android-scroll android-scrollbar


    【解决方案1】:

    这是我在 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);
    

    您也可以尝试使用垂直滚动的滚动视图包装您的 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 中的三星 i5700 spica 崩溃。
    • LayoutAlgorithm.SINGLE_COLUMN 还是 webview.setOnTouchListener?
    • 如果你把一个 WebView 放在一个 ScrollView 中,请将 WebView 的 android:isScrollContainer 属性设置为“false”,而不是将 android:scrollbars 设置为“none”。这具有完全禁用 webview 的滚动处理的效果,并允许它根据其内容进行扩展。然后滚动将由父 ScrollView 单独处理。
    • 如果您需要在WebView 中处理MotionEvent.ACTION_MOVE 事件,请参阅下面的答案。
    • 忽略setOnTouchListener 事件上的ACTION_MOVE 有一些副作用,所以我不推荐这个答案; 1. 快速滑动被视为页面的onclick 事件。 2. 防止页面上的元素溢出滚动,这可能需要根据站点进行适当的交互。 3. JStouchmove事件。 @GDanger 的正确答案是通过扩展 WebView 来覆盖 overScrollBy,因为它没有其他副作用,只是防止页面滚动。 stackoverflow.com/a/26129301/1244574
    【解决方案2】:

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

    如果您查看sourceWebView,您会看到onTouchEvent 调用doDrag,后者调用overScrollBy

    【讨论】:

    • 如果您需要以编程方式禁用/启用滚动,请查看我创建的 gist
    • 你的方法对我有用。我非常同意你的看法。就我而言,我无法使用接受答案拖动嵌入在 WebView 中的视频和音频进度条。
    • 这是正确的答案。尽管它需要对覆盖的构造函数进行一些调整。请在下面查看我的完整答案。 stackoverflow.com/a/51936944/393502
    【解决方案3】:

    我不知道你是否还需要它,但这里是解决方案:

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

    【讨论】:

    • 好的。这会禁用滚动条,但不会阻止通过拖动进行滚动。看来html也必须适合...
    • 如果您只为 android 网页视图设计网页,那么我建议您将网页放在表格中。宽度应该像 width="100%" 和高度一样。这样就不会再拖了。
    • width=100% 并不总是有效,例如:stackoverflow.com/questions/6460871/…
    【解决方案4】:

    如果您的内容正确换行,将边距详细信息添加到正文将阻止滚动,如下所示:

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

    足够简单,而且代码和错误开销要少得多:)

    【讨论】:

    • 在普通的 android 浏览器中看起来不错,但在 Firefox (Fennec) 中似乎不起作用......尽管没有任何东西可以水平滚动,但 Firefox 仍然让我向右滚动到所有内容都滚出屏幕的点。
    • 不适用于现代 WebView(Android 5 及更高版本)
    【解决方案5】:

    在你的 WebView 上设置一个监听器:

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

    【讨论】:

    • return 行的末尾有一个额外的括号。这也破坏了 HTML5 画布和 JavaScript 触摸事件。
    • 这当然会禁用它,但是我以后如何杀死侦听器以重新启用输入?我试过event.getAction() != MotionEvent.ACTION_MOVEreturn true
    • 标准的“什么都不做”案例是return false,而不是return true
    【解决方案6】:

    我没有尝试过,因为我还没有遇到这个问题,但也许你可以覆盖 onScroll 函数?

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

    【讨论】:

      【解决方案7】:

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

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

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

      我希望这会有所帮助;)

      【讨论】:

      • 是的,但是滚动大小不会太大,底部有很多空白?
      • 如果内容宽度为 1001dp 怎么办?
      【解决方案8】:

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

      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,以提供更有效的控制,例如禁用/启用滑动、启用/禁用触摸、侦听器、控制转换、动画、内部定义设置等等..

      【讨论】:

        【解决方案9】:

        要禁用滚动使用这个

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

        【讨论】:

          【解决方案10】:

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

          leftmargin="0" topmargin="0"
          

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

          【讨论】:

            【解决方案11】:

            如果您子类化 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);
                }
                ...
            

            【讨论】:

              【解决方案12】:

              研究上述答案几乎对我有用......但我仍然有一个问题,我可以在 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 中的视频和音频进度条。非常感谢!
              • Webview 无法使用此自定义 webview 自动加载。
              【解决方案13】:

              这应该是完整的答案。正如@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"/>
              

              然后在 Activity 中,使用一些额外的方法来禁用滚动条。

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-09-04
                • 2011-08-15
                • 2011-11-28
                • 1970-01-01
                • 2014-12-24
                相关资源
                最近更新 更多