web-dev-qa-db-ja.com

Android ScrollView内のWebViewはscrollviewのみをスクロールします

私のアプリには、LinearView、TextView、One Webview、その他の線形レイアウトなどを含むScrollViewがあります。問題は、WebViewがスクロールしないことです。 ScrollはScrollViewでのみリッスンします。助言がありますか??


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

これが解決策です。オンラインで発見。 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"
                 />
80
Panos

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

Panosソリューションは、1つの例外を除いて十分です...固定高(200dp)WebViewが空であるか、大量のコンテンツが読み込まれている可能性があります。そのため、「それ自体」でスクロールできる場合とできない場合があります。 PanosソリューションはMotionEventsを常に消費するため、WebViewが空で、ユーザーがWebViewをタッチしてスクロールしようとすると、WebViewはスクロールしません(ないため)コンテンツ)およびスクロール可能な親も、WebView "swallows" MotionEventを引き起こす-何も起こりません。予想される動作に小さなifステートメントを追加しました。

_@Override
public boolean onTouchEvent(MotionEvent event) {
    if(computeVerticalScrollRange() > getMeasuredHeight())
        requestDisallowInterceptTouchEvent(true);
    return super.onTouchEvent(event);
}
_
  • WebViewが空で、垂直スクロールできない場合、computeVerticalScrollRange() == getMeasuredHeight()
  • WebViewがコンテンツの高さより長い(スクロール可能)場合、computeVerticalScrollRange() > getMeasuredHeight()
4
snachmsm

クラスファイルに1行追加するだけです

mWebview.setNestedScrollingEnabled(true);

またはXMLのWebviewタグに追加

Android:nestedScrollingEnabled="true"

警告:API 21および21+のみ

2
Nikunj Paradva

それでもreact-native-webview、ここで追跡されている問題 https://github.com/react-native-community/react-native-webview/issues/22

0
gasolin

@Panosと@Dipendraのソリューションを解決するために、スクロールビュー内のマップビューにまだいくつかの問題がありました。一貫して垂直にスクロールしないため、メソッドが非推奨になったため、スクロールビュー内のマップビューで使用するこのトリックを解決しました。これがあなたの一部に役立つことを願っています。

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