Scroll Webview inside a Scroll View

2019-02-23 02:53发布

问题:

What I have:
Right now I have a Scroll view as a parent. Inside this scroll view, I am using a WebView that loads a URL and then shows text in it. Here is my xml:

<ScrollView
    android:id="@+id/parentScroll"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/Heading" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="5dp" >

        <WebView
            android:id="@+id/webView"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="@drawable/webview" />
    </RelativeLayout>
</ScrollView>    

What I want:
I want to scroll webView inside it. When I touch the webView, unfortunately the parent scroll view gets called. I have to keep Parent scroll view also but besides this I want to scroll WebView content inside it when I touch on webView.

How can I do this?

回答1:

Create a Custom Touch Intercepting Webview

CustomWebview.java

 package com.mypackage.common.custom.android.widgets

public class CustomWebview extends WebView {

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

    public CustomWebview(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomWebview(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        requestDisallowInterceptTouchEvent(true);
        return super.onTouchEvent(event);
    }          
}

in layout.xml

<com.package.custom.widgets.CustomWebview
                android:id="@+id/view_extra"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                 />


回答2:

According to Android design documents you should never put a scrolling container inside a scrolling container if they scroll the same direction. It's not meant to handle such a thing.



回答3:

I had the same problem. You should set your webView Height equal as its content. for this do this:
add this lines to your onCreate method in Activity:

webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                webView.loadUrl("javascript:MyApp.resize(document.body.getBoundingClientRect().height)");

                super.onPageFinished(view, url);
            }
        });
webView.addJavascriptInterface(this, "MyApp");

and add this method to your activity:

@JavascriptInterface
    public void resize(final float height) {
        MainActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                webView.setLayoutParams(new LinearLayout.LayoutParams(getResources().getDisplayMetrics().widthPixels, (int) (height * getResources().getDisplayMetrics().density)));
            }
        });
    }


回答4:

Nested scrollable widgets are generally discouraged. It is a confusing user experience because it's easy to scroll the wrong thing. Say I intend to scroll the outer scroll region but I touched the inner region first and flinged really hard. Then the inner one will scroll and I'll be like huh? Why didn't it scroll?

Even if one scrolls horizontal and the other is vertical the gesture recognizers might confuse one for another so you get the same effect. It's a valid use case but it's still iffy and I'd avoid it. (IE: Humans don't perfectly swipe vertically and horizontally properly, it's usually with an angle.)

I would push to change the design to break out the scrollable areas. Ideally 1 scrollable item per page. Even propose one yourself and provide to the designer both experiences and see which one they choose.

To express how this will suck. Look at this example. This isn't a solution but just to show the experience.

<ScrollView
    android:id="@+id/parentScroll"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/Heading" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" android:orientation="vertical"
    android:padding="5dp" >
    <TextView
        android:id="@+id/topText"
        android:layout_width="match_parent"
        android:layout_height="1000dp"
        android:text="@string/lotsoftext" />
    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:background="@drawable/webview" />
    <TextView
        android:id="@+id/topText"
        android:layout_width="match_parent"
        android:layout_height="1000dp"
        android:text="@string/lotsoftext" />
</RelativeLayout>