Отключить прокрутку в webview?

до сих пор я был только разработчиком iPhone, и теперь я решил дать Android вихрь. То, что я не смог выяснить на Android, - это как программно предотвратить прокрутку в WebView?

что-то похожее на предотвращение iPhones onTouchMove событие было бы здорово!

15 ответов


вот мой код отключение всех прокрутки в webview:

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

чтобы только скрыть полосы прокрутки, но не отключить прокрутку:

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

или вы можете попробовать использовать одностоечный макет но это работает только с простыми страницами и отключает горизонтальную прокрутку:

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

вы также можете попробовать оберните свой webview с вертикальной прокруткой scrollview и отключить все прокрутка в 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>

и set

webview.setScrollContainer(false);

не забудьте добавить webview.setOnTouchListener(...) код выше, чтобы отключить всю прокрутку в webview. Вертикальный ScrollView позволит прокручивать содержимое WebView.


Я не знаю, нужно ли вам это или нет, но вот решение:

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

делает WebView игнорировать события движения-неправильный способ сделать это. Что если WebView нужно услышать об этих событиях?

вместо подкласса WebView и переопределить нечастных методов прокрутки.

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

если вы посмотрите на источник на WebView видно, что onTouchEvent звонки doDrag которых звонки overScrollBy.


добавление сведений о полях в тело предотвратит прокрутку, если ваш контент правильно обертывается, например:

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

достаточно легко, и намного меньше кода + ошибка накладные расходы:)


установите прослушиватель в вашем WebView:

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

Я не пробовал это, так как я еще не сталкивался с этой проблемой, но, возможно, вы могли бы перезапустить функцию onScroll?

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

мое грязное, но простое в реализации и хорошо работающее решение:

просто поместите webview внутри scrollview. Сделайте webview слишком большим, чем возможный контент (в одном или обоих измерениях, в зависимости от требований). ..и настройте полосы прокрутки scrollview, как вы хотите.

пример отключения горизонтальной полосы прокрутки в 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>

надеюсь, это поможет;)


для Disbale прокрутки используйте это

объект WebView.setOnTouchListener(новый вид.OnTouchListener() {

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

это не может быть источником вашей проблемы, но я потратил часы, пытаясь отследить, почему мое приложение, которое отлично работало на iphone, заставляет браузер android постоянно подбрасывать вертикальные / горизонтальные полосы прокрутки и фактически перемещать страницу. У меня был тег тела html с высотой и шириной, установленной на 100%, и тело было полно различных тегов в разных местах. Независимо от того, что я пытался, браузеры android будут показывать свои полосы прокрутки и перемещать страницу немного, особенно при выполнении быстрого свайпа. Решение, что работал для меня без необходимости делать что-либо в APK-файл чтобы добавить в тег body:

leftmargin="0" topmargin="0"

похоже, что поля по умолчанию для тега body применялись к дроиду, но игнорировались на iphone


Если вы подкласс Webview, вы можете просто переопределить onTouchEvent, чтобы отфильтровать события перемещения, которые запускают прокрутку.

public class SubWebView extends WebView {

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

я разрешил мерцание и автоматическую прокрутку:

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

однако, если он по-прежнему не работает по какой-то причине, просто сделайте класс, который расширяет WebView, и поместите на него этот метод:

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

Я предлагаю расширить WebView, чтобы обеспечить более эффективный контроль, например, отключить / включить swipes, включить / отключить касания, прослушиватели, переходы управления, анимацию, определить настройки внутри и так далее..


изучение вышеуказанных ответов почти сработало для меня ... но у меня все еще была проблема, что я мог "бросить" вид на 2.1 (казалось, был исправлен с 2.2 & 2.3).

вот мое окончательное решение

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

/ / отключить всю прокрутку

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

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

// отключить только горизонтальную прокрутку

WebView.setHorizontalScrollBarEnabled(false);
webview.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

/ / отключить только вертикальную прокрутку

WebView.setVerticalScrollBarEnabled(false);
webview.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
       switch (action)
        {
            case (MotionEvent.ACTION_DOWN):
                /**
                 * get Y position
                 */
                start_y = event.getY();
                break;
            case (MotionEvent.ACTION_MOVE):

               /*Disable vertical scrolling*/

              if (start_y-event.getY()>THRESHOLD_VALUE || start_y- event.getY()<-THRESHOLD_VALUE)
                    return true;
              break;
        }
    }
  });

В моем случае пороговое значение было 20


Это должен быть полный ответ. Как предложил @GDanger . Расширьте WebView, чтобы переопределить методы прокрутки и внедрить пользовательский webview в 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();
        }
    }
}

а затем встроить в файл макета следующим образом

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

затем в действии используйте некоторые дополнительные методы для отключения полос прокрутки.

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

просто использовать android:focusableInTouchMode="false" на объект WebView.