Disattivare lo scorrimento in WebView?


86

Fino ad ora sono stato solo uno sviluppatore di iPhone e ora ho deciso di provare Android. Qualcosa che non sono riuscito a capire su Android è come impedire programmaticamente lo scorrimento in un WebView?

Qualcosa di simile alla prevenzione onTouchMovedell'evento da parte degli iPhone sarebbe fantastico!

Risposte:


179

Ecco il mio codice per disabilitare tutto lo scorrimento in webview:

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

Per nascondere solo le barre di scorrimento, ma non disabilitare lo scorrimento:

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

oppure puoi provare a utilizzare il layout a colonna singola ma funziona solo con pagine semplici e disabilita lo scorrimento orizzontale:

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

Puoi anche provare a racchiudere la tua visualizzazione web con scrollview a scorrimento verticale e disabilitare tutto lo scorrimento sulla visualizzazione 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>

E set

webview.setScrollContainer(false);

Non dimenticare di aggiungere il webview.setOnTouchListener(...)codice sopra per disabilitare tutto lo scorrimento nella visualizzazione web. Lo ScrollView verticale consentirà lo scorrimento del contenuto del WebView.


funziona bene, ma dopo pochi secondi provoca l'arresto anomalo su Samsung i5700 spica in /system/lib/libwebcore.so.
Lukas

LayoutAlgorithm.SINGLE_COLUMN o webview.setOnTouchListener?
peceps

3
Se metti una WebView in una ScrollView, imposta l'attributo android: isScrollContainer della WebView su "false" invece di impostare android: scrollbars su "none". Ciò ha l'effetto di disabilitare completamente la gestione dello scorrimento della visualizzazione Web e consentirne l'espansione in base al suo contenuto. Lo scorrimento verrà quindi gestito esclusivamente dal padre ScrollView.
BladeCoder

1
Se hai bisogno di gestire MotionEvent.ACTION_MOVEeventi nel tuo WebViewvedi la mia risposta di seguito.
GDanger

1
Ignorando l' ACTION_MOVEsulla setOnTouchListenermanifestazione ha alcuni effetti collaterali in modo da non voglio raccomandare questa risposta; 1. I passaggi rapidi vengono conteggiati come onclickeventi nella pagina. 2. Impedisce lo scorrimento eccessivo degli elementi sulla pagina, potrebbe essere necessario per una corretta interazione a seconda del sito. 3. L' touchmoveevento JS . @GDanger ha la risposta corretta che sovrascrive overScrollByestendendo il in WebViewquanto non ha effetti sugli altri, impedisce solo lo scorrimento della pagina. stackoverflow.com/a/26129301/1244574
jkasten

22

Non so se ne hai ancora bisogno o meno, ma ecco la soluzione:

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

18
ok. questo disabilita le barre di scorrimento, ma non impedisce lo scorrimento mediante trascinamento. Sembra che anche l'html debba adattarsi ...
rdmueller

Se stai progettando le tue pagine web solo per la visualizzazione web Android, ti consiglio di creare le tue pagine web in tabella. La larghezza dovrebbe essere come width = "100%" e lo stesso per l'altezza. quindi non ci sarà più alcun trascinamento.
umar

larghezza = 100% non funziona sempre, per esempio: stackoverflow.com/questions/6460871/...
NoBugs

fantastico .. è quello che mi serve. Grazie
Peter,

21

Fare in modo che WebViewignori gli eventi di movimento è il modo sbagliato di procedere. E se fosse WebViewnecessario conoscere questi eventi?

Invece sottoclasse WebViewe sovrascriva i metodi di scorrimento non privati.

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

Se si guarda alla fonte per WebViewvoi può vedere che onTouchEventle chiamate doDragche invita overScrollBy .


1
Se hai bisogno di disabilitare / abilitare lo scorrimento a livello di codice guarda questo gist che ho creato.
GDanger

1
Il tuo metodo funziona per me. E sono abbastanza d'accordo con te. Nel mio caso, non posso trascinare la barra di avanzamento video e audio incorporata in WebView utilizzando la risposta di accettazione.
codezjx

Questa è la risposta esatta. Anche se ha bisogno di alcune modifiche ai costruttori di override. Si prega di guardare la mia risposta completa di seguito. stackoverflow.com/a/51936944/393502
Vansi

13

L'aggiunta dei dettagli del margine al corpo impedirà lo scorrimento se il contenuto si avvolge correttamente, in questo modo:

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

Abbastanza facile e molto meno codice + sovraccarico di bug :)


1
Brillante! +1 per una semplice soluzione solo HTML. A volte vorrei che il layout in Android fosse facile come CSS ...
Pritesh Desai

Sembra buono nel browser Android di serie, ma non sembra funzionare in Firefox (Fennec) ... nonostante non ci sia nulla da scorrere orizzontalmente, Firefox mi consente comunque di scorrere verso destra fino al punto in cui è stato fatto scorrere tutto il contenuto fuori dallo schermo.
Michael

1
Non funziona sulla moderna WebView (Android 5 e versioni successive)
Roel

8

Imposta un listener sul tuo WebView:

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

3
C'è una parentesi in più alla fine della returnriga lì. Anche questo interrompe la tela HTML5 e gli eventi di tocco JavaScript.
Rohan Singh

Questo certamente lo disabilita, ma come posso uccidere l'ascoltatore in seguito per riattivare l'input? Ho provato event.getAction() != MotionEvent.ACTION_MOVEanchereturn true
CQM

Il caso standard "non fare nulla" è return false, non è return true.
Matthew ha letto il

6

Non l'ho provato perché devo ancora riscontrare questo problema, ma forse potresti sovrascrivere la funzione onScroll?

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

Questo è ciò che in India chiamiamo Jugaad ... anche se ha funzionato bene
R4chi7

4

La mia soluzione sporca, ma facile da implementare e ben funzionante:

Metti semplicemente la webview in una scrollview. Rendi la visualizzazione web troppo grande del contenuto possibile (in una o entrambe le dimensioni, a seconda dei requisiti). ..e imposta le barre di scorrimento della visualizzazione di scorrimento come desideri.

Esempio per disabilitare la barra di scorrimento orizzontale su una visualizzazione 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>

Spero che questo possa essere d'aiuto ;)


sì, ma allora la dimensione dello scorrimento non sarebbe troppo grande con molto spazio bianco in basso?
Rafael Sanches

1
E se la larghezza del contenuto fosse 1001dp?
Waltsu

3

Ho risolto lo sfarfallio e lo scorrimento automatico di:

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

Tuttavia, se per qualche motivo continua a non funzionare, crea semplicemente una classe che estenda WebView e mettici sopra questo metodo:

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

Sto suggerendo di estendere WebView, al fine di fornire un controllo più efficace, come disabilitare / abilitare swipes, abilitare / disabilitare tocchi, ascoltatori, transizioni di controllo, animazioni, definire impostazioni internamente e così via ..


3

Per disabilitare lo scorrimento usa questo

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

2

Questa potrebbe non essere la fonte del tuo problema, ma ho passato ore a cercare di rintracciare perché la mia applicazione che ha funzionato bene su iPhone fa sì che il browser Android sollevi costantemente le barre di scorrimento verticale / orizzontale e sposti effettivamente la pagina. Avevo un tag body html con altezza e larghezza impostate al 100% e il corpo era pieno di vari tag in posizioni diverse. Indipendentemente da ciò che ho provato, i browser Android mostravano le loro barre di scorrimento e spostavano la pagina solo un po ', in particolare quando si esegue uno scorrimento veloce. La soluzione che ha funzionato per me senza dover fare nulla in un APK è stata aggiungere quanto segue al tag body:

leftmargin="0" topmargin="0"

Sembra che i margini predefiniti per il tag body siano stati applicati al droide ma ignorati sull'iPhone


1

Se si sottoclasse Webview, è possibile sovrascrivere semplicemente onTouchEvent per filtrare gli eventi di spostamento che attivano lo scorrimento.

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

studiare le risposte di cui sopra ha quasi funzionato per me ... ma avevo ancora il problema di poter "lanciare" la vista su 2.1 (sembrava essere stato risolto con 2.2 e 2.3).

ecco la mia soluzione 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);
}
}

Per sovrascrivere il metodo onScrollChanged () funziona per me. Nel mio caso, non posso trascinare la barra di avanzamento video e audio incorporata in WebView utilizzando la risposta di accettazione. Molte grazie!
codezjx

-1

Questa dovrebbe essere la risposta completa. Come suggerito da @GDanger. Estendi WebView per sovrascrivere i metodi di scorrimento e incorporare la visualizzazione Web personalizzata all'interno di layout 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();
        }
    }
}

E poi incorporalo nel file di layout come segue

<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"/>

Quindi nell'attività, utilizza alcuni metodi aggiuntivi per disabilitare anche le barre di scorrimento.

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

-3

Basta usare android:focusableInTouchMode="false"sul tuo webView .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.