android - ScrollView 内的 Android WebView 中的 HTML 滚动事件

标签 android webview android-scrollview

我有一个用于测试目的的网页(https://storage.googleapis.com/htmltestingbucket/nested_scroll_helper.html),它只打印 html 在固定标题中捕获的滚动事件的计数器

当 Android WebView 是 fragment 中唯一可滚动的元素时,一切都很好,WebView 将滚动事件发送到页面

如果我想在 WebView 的上方和下方添加原生元素,那么事情会变得更加复杂。

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="20dp"
            android:text="SOMETHING ABOVE THE WEBVIEW" />

        <WebView
            android:id="@+id/webview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="20dp"
            android:text="SOMETHING BELOW THE WEBVIEW" />

    </LinearLayout>
</ScrollView>

我知道在 ScrollView 中包含 WebView 不好,但我必须在 html 文档中提供具有混合内容和适当滚动事件的单一滚动体验。 我发现了很多关于此事的问题,但我能够创建一个完整的端到端解决方案


此外,我知道 lint 对此进行了官方检查:

NestedScrolling --------------- Summary: Nested scrolling widgets

Priority: 7 / 10 Severity: Warning Category: Correctness

A scrolling widget such as a ScrollView should not contain any nested scrolling widgets since this has various usability issues

然而,我无法在 native 中实现 web View 内容,因此我需要一种替代方法来做到这一点

最佳答案

要在此处将 Webview 保留在 ScrollView 中,您需要测量 webview 的高度并将其设置在布局参数中。

在这里,我试图给出可滚动 webview 的答案。

<ScrollView
        android:layout_width="fill_parent" android:background="#FF744931"
        android:layout_height="fill_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            tools:ignore="WebViewLayout">

            <TextView
                android:id="@+id/txtVoiceSeachQuery"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="#FF0000"
                android:textSize="26sp" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:text="SOMETHING ABOVE THE WEBVIEW" />

            <com.example.ScrollableWebView
                android:id="@+id/webview"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:isWebViewInsideScroll="true" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="20dp"
                android:text="SOMETHING BELOW THE WEBVIEW" />

        </LinearLayout>
    </ScrollView>

res/values/attrs.xml

为自定义控件添加属性

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ScrollableWebView">
    <attr name="isWebViewInsideScroll" format="boolean"></attr>
</declare-styleable>
</resources>

可滚动的WebView

public class ScrollableWebView extends WebView {
    private boolean webViewInsideScroll = true;
    public static final String RESOURCE_NAMESPACE = "http://schemas.android.com/apk/res-auto";

    public ScrollableWebView(Context context) {
        super(context);
    }

    public ScrollableWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setWebViewInsideScroll(attrs.getAttributeBooleanValue
                (RESOURCE_NAMESPACE, "isWebViewInsideScroll", true));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (isWebViewInsideScroll()) {
            int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);
            ViewGroup.LayoutParams params = getLayoutParams();
            params.height = getMeasuredHeight();
            setLayoutParams(params);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    public boolean isWebViewInsideScroll() {
        return webViewInsideScroll;
    }

    public void setWebViewInsideScroll(boolean webViewInsideScroll) {
        this.webViewInsideScroll = webViewInsideScroll;
    }
}

要获取属性值,您还可以使用 Stylable,但这里我没有使用它。

ScrollableWebView webview = (ScrollableWebView) findViewById(R.id.webview);
        webview.loadUrl("https://storage.googleapis.com/htmltestingbucket/nested_scroll_helper.html");

下面是输出链接

如果您不想创建属性文件并在 res/values/attrs.xml 中添加自定义属性,则可以忽略该文件并检查 this pastebin在这里,我没有提供任何自定义属性,例如 isWebViewInsideScroll。您也可以将其从 xml 布局中删除。 如果有任何事情请告诉我。

关于android - ScrollView 内的 Android WebView 中的 HTML 滚动事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34793618/

相关文章:

java - Android webview进度条无论有没有网络都会持续加载

android - WebView.setInitialScale 不起作用

android - 出现键盘时向上滚动屏幕

android - 来自 Nexus Galaxy 的 fb0 上的 ffmpeg 错误 : "could not get frame filename number 2"

android - 为未决 Intent 设置可变性标志但仍收到 IllegalArgumentException 错误

android - 是否可以在android NDK中更改位图内部的像素矩阵

Android父级onTouchEvent劫持子级onTouchEvent

android - 在 OSMDROID 中的快速覆盖上设置图标

java - 在 Java 中自动填充字段 WebView

Android:ViewPager 内的 Vertical ScrollView - 无法滚动