Android WebView inside ScrollView ScrollView Scrolls only scrollview

dans mon application j'ai un ScrollView qui contient quelques aperçus linéaires, quelques textviews et un Webview, puis d'autres layouts linéaires etc. Le problème est que le WebView ne fait pas défiler. Le Scroll n'écoute que sur ScrollView. Toutes les suggestions??


<ScrollView >
    <TextView />
    <WebView />              <-- this does not scroll
    <TextView />
</ScrollView >
25
demandé sur Panos 2012-11-06 23:28:56

5 réponses

Voici la solution. Trouvés en ligne. J'AI sous-classé WebView et j'utilise le requestDisallowInterceptTouchEvent(true); méthode permettant à mon webview de gérer l'événement scroll.

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

Et dans la mise en page.xml

<com.mypackage.common.custom.android.widgets.TouchyWebView 
                android:id="@+id/description_web"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                 />
71
répondu Panos 2013-01-09 10:32:20

la solution fournie par @panos fonctionne mais elle a toujours des problèmes lorsqu'elle est utilisée avec ScrollView. La version améliorée suivante résout ce problème.

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


 }

  }

en outre, vous pourriez vouloir avoir les paramètres suivants pour votre TouchyWebView.

mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
9
répondu Dipendra 2016-04-07 22:16:50

Panos solution est suffisante pour moi à une exception près... Mon de hauteur fixe (200dp) WebView peut être vide ou peut avoir chargé beaucoup de contenu. Donc il peut être ou ne pas être "lui-même"scrollable. Panos solution consomme MotionEvents toujours, de sorte que lorsque WebView est vide et que l'utilisateur touche WebView et essayez de faire défiler puis WebView ne sera pas de défilement (car il n'y a pas de contenu) et défilement de parent, la cause WebView "les hirondelles" MotionEvent - rien ne se passe. J'ai ajouté des petits if déclaration pour comportement attendu:

@Override
public boolean onTouchEvent(MotionEvent event) {
    if(computeVerticalScrollRange() > getMeasuredHeight())
        requestDisallowInterceptTouchEvent(true);
    return super.onTouchEvent(event);
}
  • quand WebView est vide et non-vertical liste déroulante, puis computeVerticalScrollRange() == getMeasuredHeight()
  • quand WebView avoir un contenu plus long que sa hauteur (est scrollable) puis computeVerticalScrollRange() > getMeasuredHeight()
3
répondu snachmsm 2016-10-24 11:23:20

en travaillant sur les solutions de @Panos et @Dipendra j'avais encore quelques problèmes avec un mapview à l'intérieur d'un scrollview. Il ne défilerait pas toujours verticalement et les méthodes ont été dépréciées donc j'ai travaillé sur cette astuce que j'utilise avec mapview à l'intérieur de scrollviews et fonctionne très bien. J'espère que cela peut aider quelques un d'entre vous.

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


}

}

j'ai aussi suivi les conseils de @Dipendra sur les réglages des commandes.

mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
0
répondu Randy 2017-11-30 07:11:10

Vous pouvez changer en 3 configurations:

  1. premier en - tête TextView
  2. WebView - page principale
  3. Second TextView-footter



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);
-11
répondu Artyom Kiriliyk 2012-11-06 19:34:38