Jusqu'à présent, je n'étais qu'un développeur iPhone et maintenant j'ai décidé de donner un tourbillon Android. Quelque chose que je n'ai pas réussi à comprendre Android est comment empêcher par programme le défilement dans un WebView
?
Quelque chose de similaire à la prévention par l’iPhone de l’événement onTouchMove
serait génial!
Voici mon code pour désactivant 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 sans désactiver le défilement:
WebView.setVerticalScrollBarEnabled(false);
WebView.setHorizontalScrollBarEnabled(false);
ou vous pouvez essayer d'utiliser disposition sur une seule colonne mais cela ne fonctionne qu'avec des pages simples et désactive le défilement horizontal:
//Only disabled the horizontal scrolling:
webview.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
Vous pouvez également essayer de emballer votre webview avec un scrollview à défilement vertical et désactiver tout défilement sur la web view:
<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 code webview.setOnTouchListener(...)
ci-dessus pour désactiver tout défilement dans la vue Web. ScrollView vertical permettra de faire défiler le contenu de la WebView.
Je ne sais pas si vous en avez toujours besoin ou pas, mais voici la solution:
appView = (WebView) findViewById(R.id.appView);
appView.setVerticalScrollBarEnabled(false);
appView.setHorizontalScrollBarEnabled(false);
Faire en sorte que les WebView
ignorer les événements de mouvement ne soit pas la bonne solution. Que se passe-t-il si le WebView
a besoin d'entendre parler de ces événements?
À la place, sous-classe WebView
et substituez 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 le source pour WebView
, vous pouvez voir que onTouchEvent
appelle doDrag
qui appelle overScrollBy .
L'ajout des détails de la marge au corps empêchera le défilement si votre contenu est correctement enveloppé, comme suit:
<body leftmargin="0" topmargin="0" rightmargin="0" bottommargin="0">
Assez facile, et beaucoup moins de code + surcharge de bug :)
Définir un écouteur sur votre WebView:
webView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return(event.getAction() == MotionEvent.ACTION_MOVE));
}
});
Je n'ai pas essayé cela car je n'ai pas encore rencontré ce problème, mais peut-être pourriez-vous outrepasser la fonction onScroll?
@Override
public void scrollTo(int x, int y){
super.scrollTo(0,y);
}
Ma solution sale, mais facile à mettre en œuvre et qui fonctionne bien:
Il suffit de placer la vue Web dans une vue à défilement. Faites en sorte que la vue Web soit beaucoup trop volumineuse par rapport au contenu possible (dans une ou les deux dimensions, en fonction des besoins). ..et configurez la ou les barres de défilement de la vue de défilement à votre guise.
Exemple pour désactiver 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 ;)
Pour désactiver le défilement, utilisez cette
webView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event)
{
return (event.getAction() == MotionEvent.ACTION_MOVE);
}
});
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-y cette méthode:
// 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 l'activation/désactivation des balayages, l'activation/désactivation des touches, des écouteurs, des transitions de contrôle, des animations, la définition de paramètres en interne, etc.
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 un iphone faisait en sorte que le Android navigateur lançait constamment les barres de défilement vertical/horizontal). J'avais une balise html body dont la hauteur et la largeur étaient définies à 100% et dont le corps était rempli de différentes balises à différents endroits. Quoi que j'aie essayé, les Android montrerait ses barres de défilement et déplacerait la page un peu, en particulier lors d’un balayage rapide. La solution qui me convenait sans rien faire 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 les balises body étaient appliquées sur le droïde mais ignorées sur l'iphone
Si vous sous-classe 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);
}
...
étudier les réponses ci-dessus a presque fonctionné pour moi ... mais j'avais quand même un problème: je pouvais "jeter" le point de vue sur la version 2.1 (qui semblait être résolu avec les versions 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);
}
}