Pergunta

Até agora, sou apenas um desenvolvedor de iPhone e agora decidi dar um giro do Android. Algo que não consegui descobrir no Android é como impedir programaticamente a rolagem em um WebView?

Algo semelhante à prevenção dos iPhones do onTouchMove Evento seria ótimo!

Foi útil?

Solução

Aqui está o meu código para desativando 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 desative a rolagem:

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

ou você pode tentar usar Layout de coluna única Mas isso funciona apenas 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 Enrole sua visão da web Com rolagem verticalmente ScrollView e desativar toda a rolagem no WebView:

<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 no WebView. O vertical ScrollView permitirá a rolagem do conteúdo da WebView.

Outras dicas

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

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

Fazendo o WebView Ignore Motion Events é o caminho errado para fazer isso. E se o WebView precisa ouvir sobre esses eventos?

Em vez disso, subclasse WebView e substituir 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 o fonte por WebView você pode ver isso onTouchEvent chamadas doDrag que chama Overcrollby.

Adicionar os detalhes da margem ao corpo impedirá a rolagem se o seu conteúdo for adequado, como assim:

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

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

Defina um ouvinte no seu WebView:

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

Eu não tentei isso, pois ainda não encontrei esse problema, mas talvez você possa superar a função Onscroll?

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

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

Basta colocar o WebView dentro de um scrollView. Torne a WebView ser muito maior que o possível conteúdo (em uma ou ambas as dimensões, dependendo dos requisitos). ..e configure a (s) barra de rolagem do scrollView como desejar.

Exemplo para desativar a barra de rolagem horizontal em um WebView:

<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 ;)

Para desativar a rolagem, use isso

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

Isso pode não ser a fonte do seu problema, mas passei horas tentando rastrear por que meu aplicativo funcionou bem no iPhone, porque o navegador Android vomitou constantemente as barras de rolagem vertical/horizontal e realmente move a página. Eu tinha uma etiqueta corporal HTML com altura e largura definidas para 100%, e o corpo estava cheio de várias etiquetas em diferentes locais. Não importa o que eu tentei, os navegadores do Android mostrariam suas barras de rolagem e moveriam a página um pouco, principalmente ao fazer um golpe rápido. A solução que funcionou para mim sem ter que fazer nada em um apk foi adicionar o seguinte à tag corporal:

leftmargin="0" topmargin="0"

Parece que as margens padrão para a etiqueta corporal estavam sendo aplicadas no dróide, mas ignoradas no iPhone

Eu resolvi a lama e a rolagem automática por:

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

No entanto, se ainda não funcionar por algum motivo, basta fazer uma aula que estende a WebView e coloque esse método:

// 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 a WebView, a fim de fornecer controle mais eficaz, como desativar/habilitar swipes, ativar/desativar toques, ouvintes, transições de controle, animações, definir configurações internamente assim ..

Se você subclasse WebView, você pode simplesmente substituir o 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);
    }
    ...

Estudando as respostas acima quase funcionou para mim ... mas ainda tinha um problema que eu poderia 'arremessar' a vista no 2.1 (parecia estar corrigido com 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);
}
}

Esta deve ser a resposta completa. Conforme sugerido por @gdanger. Estenda a WebView para substituir os métodos de rolagem e incorporar o WebView personalizado no 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 depois incorpore o arquivo de layout da seguinte maneira

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

Então, 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);

Apenas use android:focusableInTouchMode="false" Nas suas WebView.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top