45

在我的应用程序中,我有一个 ScrollView,其中包含一些线性视图、一些文本视图和一个 Webview,然后是其他线性布局等。问题是 WebView 不滚动。Scroll 仅在 ScrollView 上侦听。有什么建议么??


<ScrollView >
    <TextView />
    <WebView />              <-- this does not scroll
    <TextView />
</ScrollView >
4

7 回答 7

98

这是解决方案。网上找的。我已经将 WebView 子类化,并且我正在使用该requestDisallowInterceptTouchEvent(true);方法来允许我的 webview 处理滚动事件。

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

在 layout.xml 中

<com.mypackage.common.custom.android.widgets.TouchyWebView 
                android:id="@+id/description_web"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                 />
于 2012-11-13T00:25:11.927 回答
15

@panos 提供的解决方案有效,但与 ScrollView 一起使用时仍然存在问题。下面的增强版本克服了这个问题。

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

}

此外,您可能希望对 TouchyWebView 进行以下设置。

mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
于 2016-04-07T22:08:52.373 回答
6

Panos 解决方案对我来说就足够了,但有一个例外......我的固定高度 (200dp)WebView可能是空的,或者可能已经加载了很多内容。所以它可能是也可能不是可滚动的“本身”。Panos 解决方案总是消耗MotionEvents,所以当WebView它是空的并且用户触摸WebView并尝试滚动WebView时将不会滚动(因为没有内容)和可滚动的父级也会导致WebView“吞咽” MotionEvent- 所以什么也没有发生。我if为预期的行为添加了小声明:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(computeVerticalScrollRange() > getMeasuredHeight())
        requestDisallowInterceptTouchEvent(true);
    return super.onTouchEvent(event);
}
  • 何时WebView为空且不可垂直滚动computeVerticalScrollRange() == getMeasuredHeight()
  • WebView内容长于其高度(可滚动)时computeVerticalScrollRange() > getMeasuredHeight()
于 2016-10-24T11:23:20.733 回答
0

解决了@Panos 和@Dipendra 的解决方案,我在滚动视图中的地图视图仍然存在一些问题。它不会始终垂直滚动,并且这些方法已被弃用,所以我想出了这个技巧,我在滚动视图中使用 mapview 并且效果很好。我希望这可以帮助你们中的一些人。

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


}

}

我还遵循了@Dipendra 关于设置控件的建议。

mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
于 2017-11-30T07:11:10.537 回答
0

只需在类文件中添加一行

mWebview.setNestedScrollingEnabled(true);

Webview在 XML 中添加标签

android:nestedScrollingEnabled="true"

警告:仅适用于 API 21 和 21+

于 2019-05-05T08:10:39.687 回答
0

仍然发生在react-native-webview,这里跟踪的问题 https://github.com/react-native-community/react-native-webview/issues/22

于 2019-06-24T07:28:36.377 回答
-15

You can change into 3 layouts:

  1. First TextView - header
  2. WebView - main layout
  3. Second TextView - footer


WebView web = (WebView) findViewById(R.id.webView);
View header = getLayoutInflater().inflate(R.layout.header_layout, null);
View footer = getLayoutInflater().inflate(R.layout.foorer_layout, null);
web.addHeaderView(headerComment);
web.addFooterView(footerComment);
于 2012-11-06T19:34:38.290 回答