Desativar rolagem no webview?


86

Até agora, eu era apenas um desenvolvedor de iPhone e agora decidi dar uma olhada no Android. Algo que não consegui descobrir no Android é como evitar programaticamente a rolagem em um WebView?

Algo parecido com a prevenção de iPhones do onTouchMoveevento seria ótimo!

Respostas:


179

Aqui está o meu código para desativar toda a rolagem no webview:

  // 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 apenas as barras de rolagem, mas não desativar a rolagem:

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

ou você pode tentar usar o layout de coluna única, mas isso só funciona com páginas simples e desativa a rolagem horizontal:

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

Você também pode tentar envolver sua visualização da web com rolagem vertical de rolagem e desativar toda a rolagem na visualização da 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 definir

webview.setScrollContainer(false);

Não se esqueça de adicionar o webview.setOnTouchListener(...)código acima para desativar toda a rolagem na visualização da web. O ScrollView vertical permitirá a rolagem do conteúdo do WebView.


funciona bem, mas após alguns segundos causa travamento no Samsung i5700 spica em /system/lib/libwebcore.so.
— Lukas de

LayoutAlgorithm.SINGLE_COLUMN ou webview.setOnTouchListener?
— peceps

3
Se você colocar um WebView em um ScrollView, defina o atributo android: isScrollContainer do WebView como "false" em vez de definir android: scrollbars como "none". Isso tem o efeito de desabilitar completamente o manuseio de rolagem da visualização da web e permite que ela se expanda de acordo com seu conteúdo. A rolagem será então tratada exclusivamente pela ScrollView pai.
— BladeCoder

1
Se você precisar lidar com MotionEvent.ACTION_MOVEeventos em seu, WebViewveja minha resposta abaixo.
— GDanger

1
Ignorar o ACTION_MOVEno setOnTouchListenerevento tem alguns efeitos colaterais, então eu NÃO recomendaria esta resposta; 1. Deslizamentos rápidos são contados como onclickeventos na página. 2. Evita o estouro de rolagem de elementos na página, isso pode ser necessário para uma interação adequada, dependendo do site. 3. O touchmoveevento JS . @GDanger tem a resposta correta que está substituindo o overScrollByestendendo o, WebViewpois não tem efeitos colaterais, apenas evita a rolagem da página. stackoverflow.com/a/26129301/1244574
— jkasten

22

Não sei se ainda precisa ou não, mas aqui está a solução:

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

18
Está bem. isso desativa as barras de rolagem, mas não impede a rolagem arrastando. Parece que o html deve caber também ...
— rdmueller

Se você está projetando suas páginas da web apenas para visualização na web do Android, então eu recomendo fazer suas páginas na tabela. A largura deve ser como largura = "100%" e igual para a altura. então não haverá mais nenhum arrastamento.
— umar de

largura = 100% nem sempre funciona, por exemplo: stackoverflow.com/questions/6460871/…
— NoBugs

incrível .. é o que eu preciso. Obrigado
— Peter

21

Fazer WebViewignorar eventos de movimento é a maneira errada de fazer isso. E se WebViewprecisar ouvir sobre esses eventos?

Em vez disso, crie uma subclasse WebViewe substitua os métodos de rolagem não 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
    }
}

Se você olhar para a fonte para WebViewque você pode ver que as onTouchEventchamadas doDragque chama overScrollBy .


1
Se você precisar desabilitar / habilitar a rolagem programaticamente, dê uma olhada nesta essência que criei.
— GDanger

1
Seu método funciona para mim. E eu concordo totalmente com você. No meu caso, não consigo arrastar a barra de progresso de vídeo e áudio incorporada ao WebView usando a resposta de aceitação.
— codezjx

Esta é a resposta certa. Embora precise de alguns ajustes nos construtores de substituição. Por favor, olhe minha resposta completa abaixo. stackoverflow.com/a/51936944/393502
— Vansi

13

Adicionar os detalhes da margem ao corpo impedirá a rolagem se o conteúdo for agrupado corretamente, da seguinte forma:

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

Fácil, e muito menos código + sobrecarga de bug :)


1
Brilhante! 1 para uma solução simples apenas de HTML. Às vezes eu gostaria, o layout no Android era tão fácil quanto css ...
— Pritesh Desai

Parece bom no navegador padrão do Android, mas não parece funcionar no Firefox (Fennec) ... apesar de não haver nada para rolar horizontalmente, o Firefox ainda me permite rolar para a direita até o ponto onde todo o conteúdo rolou fora da tela.
— Michael,

1
Não funciona no WebView moderno (Android 5 e superior)
— Roel

8

Defina um ouvinte em seu WebView:

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

3
Há um parêntese extra no final da returnlinha. Além disso, isso quebra a tela HTML5 e os eventos de toque do JavaScript.
— Rohan Singh,

Isso certamente o desativa, mas como faço para matar o ouvinte mais tarde para reativar a entrada? Eu tentei event.getAction() != MotionEvent.ACTION_MOVEtão bem quantoreturn true
— CQM

O caso padrão de "não fazer nada" é return falsenão return true.
— Matthew leu

6

Não tentei fazer isso porque ainda não encontrei esse problema, mas talvez você possa sobrescrever a função onScroll?

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

Isso é o que chamamos de Jugaad na Índia ... embora tenha funcionado muito bem
— R4chi7

4

Minha solução suja, mas fácil de implementar e que funciona bem:

Basta colocar o webview dentro de um scrollview. Faça com que a webview seja muito maior do que o conteúdo possível (em uma ou ambas as dimensões, dependendo dos requisitos). ..e configure a (s) barra (s) de rolagem da visualização de rolagem como desejar.

Exemplo para desativar a barra de rolagem horizontal em uma visualização da 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>

Eu espero que isso ajude ;)


Sim, mas o tamanho do pergaminho não seria muito grande com muito espaço em branco na parte inferior?
— Rafael Sanches

1
E se a largura do conteúdo for 1001 dp?
— Waltsu de

3

Resolvi a tremulação e a rolagem automática:

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

No entanto, se por algum motivo ainda não funcionar, basta fazer uma classe que estenda WebView e colocar este método nela:

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

Estou sugerindo estender o WebView, a fim de fornecer um controle mais eficaz, como desabilitar / habilitar deslizamentos, habilitar / desabilitar toques, ouvintes, controlar transições, animações, definir configurações internamente e assim por diante.


3

Para desativar a rolagem, use este

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

2

Esta pode não ser a origem do seu problema, mas passei horas tentando rastrear por que meu aplicativo funcionou bem no iphone faz com que o navegador Android erga constantemente as barras de rolagem vertical / horizontal e realmente mova a página. Eu tinha uma tag de corpo html com altura e largura definidas em 100%, e o corpo estava cheio de várias tags em locais diferentes. Não importava o que eu tentasse, os navegadores Android mostravam suas barras de rolagem e moviam a página um pouco, principalmente ao deslizar rapidamente. A solução que funcionou para mim sem ter que fazer nada em um APK foi adicionar o seguinte à tag do corpo:

leftmargin="0" topmargin="0"

Parece que as margens padrão para a etiqueta do corpo foram aplicadas no droid, mas ignoradas no iphone


1

Se você criar uma subclasse de Webview, poderá simplesmente substituir onTouchEvent para filtrar os eventos de movimentação que acionam a rolagem.

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

estudar as respostas acima quase funcionou para mim ... mas eu ainda tinha o problema de poder 'lançar' a visão no 2.1 (parecia estar corrigido no 2.2 e 2.3).

aqui está minha solução 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);
}
}

Substituir o método onScrollChanged () funciona para mim. No meu caso, não consigo arrastar a barra de progresso de vídeo e áudio incorporada ao WebView usando a resposta de aceitação. Muito obrigado!
— codezjx

-1

Esta deve ser a resposta completa. Conforme sugerido por @GDanger. Estenda o WebView para substituir os métodos de rolagem e incorporar o WebView personalizado no XML de layout.

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, em seguida, incorpore no arquivo de layout da seguinte forma

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

Em seguida, na Atividade, use alguns métodos adicionais para desativar as barras de rolagem também.

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

-3

Basta usar android:focusableInTouchMode="false"no seu webView .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.