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 >
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"
/>
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);
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 MotionEvent
s 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, puiscomputeVerticalScrollRange() == getMeasuredHeight()
- quand
WebView
avoir un contenu plus long que sa hauteur (est scrollable) puiscomputeVerticalScrollRange() > getMeasuredHeight()
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);
Vous pouvez changer en 3 configurations:
- premier en - tête TextView
- WebView - page principale
- 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);