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


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

что-то похожее на айфоны предупреждения onTouchMove событие было бы здорово!

15 74

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. Сделайте веб-представление слишком большим, чем возможное содержимое (в одном или обоих измерениях, в зависимости от требований). ..и установите полосу прокрутки scrollview, как вы хотите.

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

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

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

чтобы отменить прокрутку используйте это

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, чтобы обеспечить более эффективный контроль, например, отключить/включить пойло, включить/отключить прикосновения, прослушиватели, переходы управления, анимацию, определить внутренние настройки и т. д..

изучение вышеуказанных ответов почти сработало для меня ... но у меня все еще была проблема, что я мог "бросить" вид на 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.