Désactiver le défilement dans la vue Web?


86

Jusqu'à présent, je n'ai été qu'un développeur iPhone et maintenant j'ai décidé de donner un tourbillon à Android. Quelque chose que je n'ai pas été en mesure de comprendre sur Android, c'est comment empêcher par programme le défilement dans un WebView?

Quelque chose de similaire à la prévention de l' onTouchMoveévénement par les iPhones serait génial!

Réponses:


179

Voici mon code pour désactiver tout le défilement dans la vue Web:

  // disable scroll on touch
  webview.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
  });

Pour masquer uniquement les barres de défilement, mais pas désactiver le défilement:

WebView.setVerticalScrollBarEnabled(false);
WebView.setHorizontalScrollBarEnabled(false);

ou vous pouvez essayer d'utiliser la disposition à une seule colonne, mais cela ne fonctionne qu'avec des pages simples et cela désactive le défilement horizontal:

   //Only disabled the horizontal scrolling:
   webview.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

Vous pouvez également essayer d' encapsuler votre vue Web avec une vue de défilement à défilement vertical et désactiver tout le défilement sur la vue Web:

<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="vertical"    >
  <WebView
    android:id="@+id/mywebview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="none" />
</ScrollView>

Et mettre

webview.setScrollContainer(false);

N'oubliez pas d'ajouter le webview.setOnTouchListener(...)code ci-dessus pour désactiver tout le défilement dans la vue Web. Le ScrollView vertical permettra de faire défiler le contenu de la WebView.


fonctionne bien, mais après quelques secondes, cela provoque un crash sur Samsung i5700 spica dans /system/lib/libwebcore.so.
Lukas

LayoutAlgorithm.SINGLE_COLUMN ou webview.setOnTouchListener?
peceps

3
Si vous placez un WebView dans un ScrollView, définissez l'attribut android: isScrollContainer de WebView sur "false" plutôt que de définir android: scrollbars sur "none". Cela a pour effet de désactiver complètement la gestion du défilement de la vue Web et lui permet de se développer en fonction de son contenu. Le défilement sera alors géré uniquement par le ScrollView parent.
BladeCoder

1
Si vous avez besoin de gérer des MotionEvent.ACTION_MOVEévénements dans votre WebViewvoir ma réponse ci-dessous.
GDanger

1
Ignorant la ACTION_MOVEsur l' setOnTouchListenerévénement a des effets secondaires , donc je ne recommanderais pas cette réponse; 1. Les balayages rapides sont comptés comme des onclickévénements sur la page. 2. Empêche le défilement excessif des éléments sur la page, cela peut être nécessaire pour une interaction appropriée selon le site. 3. L' touchmoveévénement JS . @GDanger a la bonne réponse qui remplace le overScrollByen étendant le WebViewcar il n'a aucun effet secondaire, empêche simplement le défilement de la page. stackoverflow.com/a/26129301/1244574
jkasten

22

Je ne sais pas si vous en avez encore besoin ou non, mais voici la solution:

appView = (WebView) findViewById(R.id.appView); 
appView.setVerticalScrollBarEnabled(false);
appView.setHorizontalScrollBarEnabled(false);

18
D'accord. cela désactive les barres de défilement, mais cela n'empêche pas le défilement par glissement. Il semble que le html doit s'adapter aussi ...
rdmueller

Si vous concevez vos pages Web uniquement pour la vue Web Android, je vous recommande de créer vos pages Web dans un tableau. La largeur doit être comme width = "100%" et identique pour la hauteur. il n'y aura donc plus de traînage.
umar

width = 100% ne fonctionne pas toujours, par exemple: stackoverflow.com/questions/6460871/…
NoBugs

génial ... c'est ce dont j'ai besoin. Merci
Peter

21

Faire WebViewignorer les événements de mouvement n'est pas la bonne façon de procéder. Et si le WebViewbesoin d'entendre parler de ces événements?

Au lieu de cela, sous WebView-classez et remplacez les méthodes de défilement non privées.

public class NoScrollWebView extends WebView {
    ...
    @Override
    public boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, 
                                int scrollRangeX, int scrollRangeY, int maxOverScrollX, 
                                int maxOverScrollY, boolean isTouchEvent) {
        return false;
    }

    @Override
    public void scrollTo(int x, int y) {
        // Do nothing
    }

    @Override
    public void computeScroll() {
        // Do nothing
    }
}

Si vous regardez la source de pour WebViewvous pouvez voir que les onTouchEventappels doDragqui appelle overScrollBy .


1
Si vous avez besoin de désactiver / activer le défilement par programme, regardez l' essentiel que j'ai créé.
GDanger

1
Votre méthode fonctionne pour moi. Et je suis tout à fait d'accord avec vous. Dans mon cas, je ne peux pas faire glisser la barre de progression vidéo et audio intégrée dans WebView en utilisant la réponse d'acceptation.
codezjx

C'est la bonne réponse. Bien qu'il ait besoin de quelques ajustements sur les principaux constructeurs. Veuillez regarder ma réponse complète ci-dessous. stackoverflow.com/a/51936944/393502
Vansi

13

L'ajout des détails de la marge au corps empêchera le défilement si votre contenu s'emballe correctement, comme suit:

<body leftmargin="0" topmargin="0" rightmargin="0" bottommargin="0">

Assez facile, et beaucoup moins de code + de surcharge de bogue :)


1
Brillant! +1 pour une solution simple HTML uniquement. Parfois, je souhaite, la mise en page sous Android était aussi simple que css ...
Pritesh Desai

Cela a l'air bien dans le navigateur Android d'origine, mais ne semble pas fonctionner dans Firefox (Fennec) ... malgré qu'il n'y ait rien à faire défiler horizontalement, Firefox me laisse toujours faire défiler vers la droite au point où tout le contenu a défilé hors de l'écran.
Michael le

1
Ne fonctionne pas sur WebView moderne (Android 5 et supérieur)
Roel

8

Définissez un écouteur sur votre WebView:

webView.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return(event.getAction() == MotionEvent.ACTION_MOVE));
            }
        });

3
Il y a une parenthèse supplémentaire à la fin de la returnligne. Cela interrompt également les événements tactiles HTML5 et JavaScript.
Rohan Singh

Cela le désactive certainement, mais comment puis-je tuer l'auditeur plus tard pour une entrée renable? J'ai essayé event.getAction() != MotionEvent.ACTION_MOVEaussi bien quereturn true
CQM

Le cas standard du «ne rien faire» ne l'est return falsepas return true.
Matthew Lire

6

Je n'ai pas essayé cela car je n'ai pas encore rencontré ce problème, mais vous pourriez peut-être surcharger la fonction onScroll?

@Override
public void scrollTo(int x, int y){
super.scrollTo(0,y);
}

C'est ce que nous appelons en Inde un Jugaad ... bien que cela fonctionne très bien
R4chi7

4

Ma solution sale, mais facile à mettre en œuvre et qui fonctionne bien:

Mettez simplement la vue Web dans une vue de défilement. Faites en sorte que la vue Web soit beaucoup trop grande que le contenu possible (dans une ou les deux dimensions, selon les exigences). ..et configurez les barres de défilement de la vue de défilement comme vous le souhaitez.

Exemple de désactivation de la barre de défilement horizontale sur une vue Web:

<ScrollView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:scrollbars="vertical"
>
    <WebView
        android:id="@+id/mywebview"
        android:layout_width="1000dip"
        android:layout_height="fill_parent"
    />
</ScrollView>

J'espère que ça aide ;)


oui, mais alors la taille du rouleau ne serait pas trop grande avec beaucoup d'espace blanc en bas?
Rafael Sanches

1
Et si la largeur du contenu était de 1001dp?
Waltsu

3

J'ai résolu le scintillement et le défilement automatique en:

webView.setFocusable(false);
webView.setFocusableInTouchMode(false);

Cependant, si cela ne fonctionne toujours pas pour une raison quelconque, créez simplement une classe qui étend WebView et mettez cette méthode dessus:

// disable scroll on touch
  setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
      return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
  });

Je suggère d'étendre WebView, afin de fournir un contrôle plus efficace, comme désactiver / activer les balayages, activer / désactiver les touches, les écouteurs, contrôler les transitions, les animations, définir les paramètres en interne, etc.


3

Pour désactiver le défilement, utilisez ceci

webView.setOnTouchListener(new View.OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) 
    {
        return (event.getAction() == MotionEvent.ACTION_MOVE);
    }
});

2

Ce n'est peut-être pas la source de votre problème, mais j'ai passé des heures à essayer de comprendre pourquoi mon application qui fonctionnait bien sur l'iphone faisait que le navigateur Android lançait constamment les barres de défilement verticales / horizontales et déplaçait réellement la page. J'avais une balise de corps html avec une hauteur et une largeur réglées à 100%, et le corps était plein de diverses balises à différents endroits. Peu importe ce que j'ai essayé, les navigateurs Android afficheraient leurs barres de défilement et déplaceraient un peu la page, en particulier lors d'un balayage rapide. La solution qui a fonctionné pour moi sans avoir à faire quoi que ce soit dans un APK était d'ajouter ce qui suit à la balise body:

leftmargin="0" topmargin="0"

Il semble que les marges par défaut pour la balise corporelle étaient appliquées sur le droïde mais ignorées sur l'iphone


1

Si vous sous- classez Webview, vous pouvez simplement remplacer onTouchEvent pour filtrer les événements de déplacement qui déclenchent le défilement.

public class SubWebView extends WebView {

    @Override
    public boolean onTouchEvent (MotionEvent ev)    {
        if(ev.getAction() == MotionEvent.ACTION_MOVE) {
            postInvalidate();
            return true;
        }
        return super.onTouchEvent(ev);
    }
    ...

0

étudier les réponses ci-dessus a presque fonctionné pour moi ... mais j'avais toujours un problème en ce que je pouvais «lancer» la vue sur 2.1 (semblait être corrigé avec 2.2 et 2.3).

voici ma solution finale

public class MyWebView extends WebView
{
private boolean bAllowScroll = true;
@SuppressWarnings("unused") // it is used, just java is dumb
private long downtime;

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

public void setAllowScroll(int allowScroll)
{
    bAllowScroll = allowScroll!=0;
    if (!bAllowScroll)
        super.scrollTo(0,0);
    setHorizontalScrollBarEnabled(bAllowScroll);
    setVerticalScrollBarEnabled(bAllowScroll);
}

@Override
public boolean onTouchEvent(MotionEvent ev) 
{
    switch (ev.getAction())
    {
    case MotionEvent.ACTION_DOWN:
        if (!bAllowScroll)
            downtime = ev.getEventTime();
        break;
    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_UP:
        if (!bAllowScroll)
        {
            try {
                Field fmNumSamples = ev.getClass().getDeclaredField("mNumSamples");
                fmNumSamples.setAccessible(true);
                Field fmTimeSamples = ev.getClass().getDeclaredField("mTimeSamples");
                fmTimeSamples.setAccessible(true);
                long newTimeSamples[] = new long[fmNumSamples.getInt(ev)];
                newTimeSamples[0] = ev.getEventTime()+250;
                fmTimeSamples.set(ev,newTimeSamples);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        break;
    }
    return super.onTouchEvent(ev);
}

@Override
public void flingScroll(int vx, int vy)
{
    if (bAllowScroll)
        super.flingScroll(vx,vy);
}

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt)
{
    if (bAllowScroll)
        super.onScrollChanged(l, t, oldl, oldt);
    else if (l!=0 || t!=0)
        super.scrollTo(0,0);
}

@Override
public void scrollTo(int x, int y)
{
    if (bAllowScroll)
        super.scrollTo(x,y);
}

@Override
public void scrollBy(int x, int y)
{
    if (bAllowScroll)
        super.scrollBy(x,y);
}
}

Remplacer la méthode onScrollChanged () fonctionne pour moi. Dans mon cas, je ne peux pas faire glisser la barre de progression vidéo et audio intégrée dans WebView en utilisant la réponse d'acceptation. Merci beaucoup!
codezjx

-1

Cela devrait être la réponse complète. Comme suggéré par @GDanger. Étendez WebView pour remplacer les méthodes de défilement et incorporer la vue Web personnalisée dans le format xml.

public class ScrollDisabledWebView extends WebView {

    private boolean scrollEnabled = false;

    public ScrollDisabledWebView(Context context) {
        super(context);
        initView(context);
    }

    public ScrollDisabledWebView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        initView(context);
    }
    // this is important. Otherwise it throws Binary Inflate Exception.
    private void initView(Context context) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,
                                   int scrollRangeX, int scrollRangeY, int maxOverScrollX,
                                   int maxOverScrollY, boolean isTouchEvent) {
        if (scrollEnabled) {
            return super.overScrollBy(deltaX, deltaY, scrollX, scrollY,
                    scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
        }
        return false;
    }

    @Override
    public void scrollTo(int x, int y) {
        if (scrollEnabled) {
            super.scrollTo(x, y);
        }
    }

    @Override
    public void computeScroll() {
        if (scrollEnabled) {
            super.computeScroll();
        }
    }
}

Et puis incorporer dans le fichier de mise en page comme suit

<com.sample.apps.ScrollDisabledWebView
    android:id="@+id/webView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_centerInParent="true"
    tools:context="com.sample.apps.HomeActivity"/>

Ensuite, dans l'activité, utilisez également des méthodes supplémentaires pour désactiver les barres de défilement.

ScrollDisabledWebView webView = (ScrollDisabledWebView) findViewById(R.id.webView);
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);

-3

Utilisez simplement android:focusableInTouchMode="false"sur votre webView .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.