【问题标题】:Android WebView inside ScrollView scrolls only scrollviewScrollView 内的 Android WebView 仅滚动滚动视图
【发布时间】:2012-10-26 19:35:57
【问题描述】:

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


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

【问题讨论】:

    标签: android webview scroll scrollview


    【解决方案1】:

    这里是解决方案。网上找的。我已经将 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"
                     />
    

    【讨论】:

    • 一旦你在WebView之外触摸就会中断。
    • @mattblang 再次触摸 web 视图,然后尝试再次滚动它。
    • 一直在寻找一些可以实现良好的 webview/scrollview 交互的东西,这似乎是最好的。在调用 requestDisallowInterceptTouchEvent(true) 方法之前,我在 onTouchEvent() 中为“if (event.getPointerCount() > 1)”添加了一个检查。这允许整个页面垂直滚动,webview 水平滚动,并且捏合和缩放仅适用于 webview。
    • 此解决方案并在此活动中使用硬件加速 = true,当按回崩溃时...如果我禁用硬件加速工作但速度很慢并且 html5 视频无法播放..
    • 仅对我有效,更改:return super.onTouchEvent(event);return false; 中的 public boolean onTouchEvent(MotionEvent event)
    【解决方案2】:

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

    【讨论】:

    • 用你的解决方案WebView 只能用两根手指滚动,用一根手指只有父级滚动......不是那么直观:/
    • 注意 MotionEventCompat.findPointerIndex(event, 0) 现已弃用,我们应该使用 event.findPointerIndex(0) 代替。
    【解决方案3】:

    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() &gt; getMeasuredHeight()

    【讨论】:

    • 这对我有用。但如果您使用的是腾讯 X5WebView 小部件,则不会调用 onTouchEvent 回调。所以只需扩展 google webkit.WebView 而不是扩展 X5WebView
    【解决方案4】:

    解决@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);
    

    【讨论】:

      【解决方案5】:

      只需在类文件中添加一行

      mWebview.setNestedScrollingEnabled(true);
      

      或在XML中添加Webview标签

      android:nestedScrollingEnabled="true"
      

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

      【讨论】:

      • ViewCompat.setNestedScrollingEnabled(mWebView, true)
      • 这不起作用。我不确定@Nikunj 是否知道 Android 开发,但要澄清一点 nestedScrolling 对那些支持嵌套滚动而不是所有视图的视图的作品。而且 webView 不支持嵌套滚动。 请删除此答案以避免混淆
      【解决方案6】:

      react-native-webview 中仍然发生,在此处跟踪问题 https://github.com/react-native-community/react-native-webview/issues/22

      【讨论】:

        【解决方案7】:

        您可以更改为 3 种布局:

        1. 第一个 TextView - 标题
        2. WebView - 主布局
        3. 第二个 TextView - 页脚


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

        【讨论】:

        • 我的滚动视图在那里,因为这些项目不适合屏幕。在我的示例中,我只在上面添加了一个 textview,在下面添加了一个 textview。但实际上还有其他相对布局,有 imageviews,webview 在中间的某个地方,其他的......所以我需要滚动视图,这样我才能看到一切。
        • 试试这个solution
        • WebView 没有“addHeaderView”或“addFooterView”方法,ListView 有这些方法。所以这不是一个解决方案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-26
        • 1970-01-01
        • 1970-01-01
        • 2014-04-20
        • 1970-01-01
        相关资源
        最近更新 更多