¿Deshabilitar el desplazamiento en la vista web?

86

Hasta ahora, solo he sido desarrollador de iPhone y ahora he decidido darle un giro a Android. Algo que no he podido averiguar en Android es cómo prevenir programáticamente el desplazamiento en un WebView?

¡Algo similar a la prevención del onTouchMoveevento con iPhones sería genial!

Jake Sankey
fuente

Respuestas:

179

Aquí está mi código para deshabilitar todo el desplazamiento en la vista web:

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

Para ocultar solo las barras de desplazamiento, pero no deshabilitar el desplazamiento:

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

o puede intentar usar el diseño de una sola columna, pero esto solo funciona con páginas simples y deshabilita el desplazamiento horizontal:

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

También puede intentar ajustar su vista web con la vista de desplazamiento de desplazamiento vertical y deshabilitar todo el desplazamiento en la vista 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>

Y establecer

webview.setScrollContainer(false);

No olvide agregar el webview.setOnTouchListener(...)código anterior para deshabilitar todo el desplazamiento en la vista web. El ScrollView vertical permitirá el desplazamiento del contenido de WebView.

peceps
fuente
funciona bien, pero después de unos segundos provoca un bloqueo en Samsung i5700 spica en /system/lib/libwebcore.so.
Lukas
LayoutAlgorithm.SINGLE_COLUMN o webview.setOnTouchListener?
peceps
3
Si pones un WebView en un ScrollView, configura el atributo android: isScrollContainer del WebView en "falso" en lugar de configurar android: scrollbars en "ninguno". Esto tiene el efecto de deshabilitar por completo el manejo de desplazamiento de la vista web y le permite expandirse de acuerdo con su contenido. Scroll será manejado únicamente por el ScrollView padre.
BladeCoder
1
Si necesita manejar MotionEvent.ACTION_MOVEeventos en su, WebViewvea mi respuesta a continuación.
GDanger
1
Haciendo caso omiso de la ACTION_MOVEen el setOnTouchListenerevento tiene algunos efectos secundarios, así que no recomendaría esta respuesta; 1. Los deslizamientos rápidos se cuentan como onclickeventos en la página. 2. Evita el desplazamiento desbordado de elementos en la página, esto podría ser necesario para una interacción adecuada según el sitio. 3. El touchmoveevento JS . @GDanger tiene la respuesta correcta, que anula overScrollByal extender el, WebViewya que no tiene efectos en el otro lado, solo evita el desplazamiento de la página. stackoverflow.com/a/26129301/1244574
jkasten
22

No sé si todavía lo necesita o no, pero aquí está la solución:

appView = (WebView) findViewById(R.id.appView); 
appView.setVerticalScrollBarEnabled(false);
appView.setHorizontalScrollBarEnabled(false);
umar
fuente
18
Okay. esto desactiva las barras de desplazamiento, pero no evita el desplazamiento arrastrando. Parece que el html también debe encajar ...
rdmueller
Si está diseñando sus páginas web solo para la vista web de Android, le recomiendo hacer sus páginas web en la tabla. El ancho debe ser como ancho = "100%" y lo mismo para la altura. por lo que no habrá más arrastre.
umar
width = 100% no siempre funciona, por ejemplo: stackoverflow.com/questions/6460871/…
NoBugs
impresionante .. es lo que necesito. Gracias
Peter
21

Hacer los WebVieweventos de movimiento de ignorar es la forma incorrecta de hacerlo. ¿Qué pasa si WebViewnecesita escuchar sobre estos eventos?

En su lugar, subclase WebViewy anule los métodos de desplazamiento no privados.

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 nos fijamos en la fuente para WebViewque pueda ver que las onTouchEventllamadas doDragque se pide overScrollBy .

GDanger
fuente
1
Si necesita deshabilitar / habilitar el desplazamiento mediante programación, mire esta esencia que creé.
GDanger
1
Tu método me funciona. Y estoy bastante de acuerdo contigo. En mi caso, no puedo arrastrar la barra de progreso de video y audio incrustada en WebView usando la respuesta de aceptación.
codezjx
Esta es la respuesta correcta. Aunque necesita algunos ajustes en los constructores primordiales. Por favor, mire mi respuesta completa a continuación. stackoverflow.com/a/51936944/393502
Vansi
13

Agregar los detalles de los márgenes al cuerpo evitará el desplazamiento si su contenido se ajusta correctamente, así:

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

Bastante fácil, y mucho menos código + error de sobrecarga :)

Auri Rahimzadeh
fuente
1
¡Brillante! +1 para una solución simple de solo HTML. A veces deseo, el diseño en Android fue tan fácil como css ...
Pritesh Desai
Se ve bien en el navegador de Android estándar, pero no parece funcionar en Firefox (Fennec) ... a pesar de que no hay nada a lo que desplazarse horizontalmente, Firefox todavía me permite desplazarme hacia la derecha hasta el punto en que todo el contenido se ha desplazado fuera de la pantalla.
Michael
1
No funciona en WebView moderno (Android 5 y superior)
Roel
8

Configure un oyente en su WebView:

webView.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return(event.getAction() == MotionEvent.ACTION_MOVE));
            }
        });
user322987
fuente
3
Hay un paréntesis adicional al final de la returnlínea. Además, esto rompe el lienzo HTML5 y los eventos táctiles de JavaScript.
Rohan Singh
Esto ciertamente lo deshabilita, pero ¿cómo elimino al oyente más adelante para cambiar la entrada? Lo intenté event.getAction() != MotionEvent.ACTION_MOVEtan bien comoreturn true
CQM
El caso estándar de "no hacer nada" es return false, no return true.
Matthew Read
6

No he probado esto porque todavía no he encontrado este problema, pero ¿quizás podrías anular la función onScroll?

@Override
public void scrollTo(int x, int y){
super.scrollTo(0,y);
}
Cero Verdades
fuente
Esto es lo que llamamos en la India un Jugaad ... aunque funcionó bien
R4chi7
4

Mi solución sucia, pero fácil de implementar y que funciona bien:

Simplemente coloque la vista web dentro de una vista de desplazamiento. Haga que la vista web sea mucho más grande que el contenido posible (en una o ambas dimensiones, según los requisitos). ..y configure las barras de desplazamiento de scrollview como desee.

Ejemplo para deshabilitar la barra de desplazamiento horizontal en una vista 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>

Espero que esto ayude ;)

usuario289463
fuente
sí, ¿pero entonces el tamaño del desplazamiento no sería demasiado grande con mucho espacio en blanco en la parte inferior?
Rafael Sanches
1
¿Qué pasa si el ancho del contenido será 1001dp?
Waltsu
3

Resolví el parpadeo y el desplazamiento automático por:

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

Sin embargo, si todavía no funciona por alguna razón, simplemente cree una clase que amplíe WebView y coloque este método en ella:

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

Estoy sugiriendo extender WebView, para proporcionar un control más efectivo, como deshabilitar / habilitar deslizamientos, habilitar / deshabilitar toques, oyentes, controlar transiciones, animaciones, definir configuraciones internamente, etc.

Abhinav Saxena
fuente
3

Para deshabilitar el desplazamiento usa esto

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

Puede que esta no sea la fuente de su problema, pero he pasado horas tratando de rastrear por qué mi aplicación que funcionó bien en el iPhone hace que el navegador de Android muestre constantemente las barras de desplazamiento verticales / horizontales y mueva la página. Tenía una etiqueta de cuerpo html con alto y ancho establecidos al 100%, y el cuerpo estaba lleno de varias etiquetas en diferentes ubicaciones. No importa lo que intente, los navegadores de Android mostrarían sus barras de desplazamiento y moverían la página solo un poco, especialmente al hacer un deslizamiento rápido. La solución que funcionó para mí sin tener que hacer nada en un APK fue agregar lo siguiente a la etiqueta del cuerpo:

leftmargin="0" topmargin="0"

Parece que los márgenes predeterminados para la etiqueta del cuerpo se aplicaron en el droide pero se ignoraron en el iphone

Robert Etheredge
fuente
1

Si crea una subclase de Webview, simplemente puede anular onTouchEvent para filtrar los eventos de movimiento que desencadenan el desplazamiento.

public class SubWebView extends WebView {

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

estudiar las respuestas anteriores casi funcionó para mí ... pero todavía tenía el problema de que podía 'lanzar' la vista en 2.1 (parecía estar solucionado con 2.2 y 2.3).

aquí está mi solución final

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);
}
}
SteelBytes
fuente
Anular el método onScrollChanged () funciona para mí. En mi caso, no puedo arrastrar la barra de progreso de video y audio incrustada en WebView usando la respuesta de aceptación. ¡Muchas gracias!
codezjx
-1

Esta debería ser la respuesta completa. Como lo sugiere @GDanger. Extienda WebView para anular los métodos de desplazamiento e incrustar la vista web personalizada en el formato 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();
        }
    }
}

Y luego incrustar en el archivo de diseño de la siguiente manera

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

Luego, en la Actividad, use algunos métodos adicionales para deshabilitar también las barras de desplazamiento.

ScrollDisabledWebView webView = (ScrollDisabledWebView) findViewById(R.id.webView);
webView.setVerticalScrollBarEnabled(false);
webView.setHorizontalScrollBarEnabled(false);
Vansi
fuente
-3

Solo utilícelo android:focusableInTouchMode="false"en su webView .

Socratex
fuente